mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-25 20:52:26 -06:00
138 lines
4.4 KiB
Python
138 lines
4.4 KiB
Python
from direct.directnotify.DirectNotifyGlobal import directNotify
|
|
import fnmatch
|
|
import os
|
|
import yaml
|
|
from panda3d.core import Multifile, Filename, VirtualFileSystem
|
|
|
|
APPLICABLE_FILE_PATTERNS = ('*.mf', 'ambience.yaml')
|
|
CONTENT_EXT_WHITELIST = ('.jpg', '.jpeg', '.rgb', '.png', '.ogg', '.ttf')
|
|
|
|
class ContentPackError(Exception):
|
|
pass
|
|
|
|
class ContentPacksManager:
|
|
notify = directNotify.newCategory('ContentPacksManager')
|
|
notify.setInfo(True)
|
|
|
|
def __init__(self, filepath='contentpacks/', sortFilename='sort.yaml'):
|
|
self.filepath = filepath
|
|
self.sortFilename = os.path.join(self.filepath, sortFilename)
|
|
|
|
if __debug__:
|
|
self.mountPoint = '../resources'
|
|
else:
|
|
self.mountPoint = '/'
|
|
|
|
self.vfs = VirtualFileSystem.getGlobalPtr()
|
|
|
|
self.sort = []
|
|
self.ambience = {}
|
|
|
|
def isApplicable(self, filename):
|
|
"""
|
|
Returns whether or not the specified file is applicable.
|
|
"""
|
|
# Does this file exist?
|
|
if not os.path.exists(filename):
|
|
return False
|
|
|
|
# Does this file match one of the applicable file patterns?
|
|
basename = os.path.basename(filename)
|
|
for pattern in APPLICABLE_FILE_PATTERNS:
|
|
if fnmatch.fnmatch(basename, pattern):
|
|
return True
|
|
|
|
return False
|
|
|
|
def applyMultifile(self, filename):
|
|
"""
|
|
Apply the specified multifile.
|
|
"""
|
|
mf = Multifile()
|
|
mf.openReadWrite(Filename(filename))
|
|
|
|
# Discard content with non-whitelisted extensions:
|
|
for subfileName in mf.getSubfileNames():
|
|
ext = os.path.splitext(subfileName)[1]
|
|
if ext not in CONTENT_EXT_WHITELIST:
|
|
mf.removeSubfile(subfileName)
|
|
|
|
self.vfs.mount(mf, self.mountPoint, 0)
|
|
|
|
def applyAmbience(self, filename):
|
|
"""
|
|
Apply the specified ambience configuration file.
|
|
"""
|
|
with open(os.path.join(self.filepath, filename), 'r') as f:
|
|
self.ambience.update(yaml.load(f) or {})
|
|
|
|
def apply(self, filename):
|
|
"""
|
|
Apply the specified content pack file.
|
|
"""
|
|
self.notify.info('Applying %s...' % filename)
|
|
basename = os.path.basename(filename)
|
|
if basename.endswith('.mf'):
|
|
self.applyMultifile(os.path.join(self.filepath, filename))
|
|
elif basename == 'ambience.yaml':
|
|
self.applyAmbience(filename)
|
|
|
|
def applyAll(self):
|
|
"""
|
|
Using the sort configuration, recursively apply all applicable content
|
|
pack files under the configured content packs directory.
|
|
"""
|
|
# First, read the sort configuration:
|
|
self.readSortConfig()
|
|
|
|
# Next, apply the sorted files:
|
|
for filename in self.sort[:]:
|
|
if self.isApplicable(os.path.join(self.filepath, filename)):
|
|
self.apply(filename)
|
|
else:
|
|
self.notify.warning('Invalidating %s...' % filename)
|
|
self.sort.remove(filename)
|
|
|
|
# Apply the non-sorted files:
|
|
for root, _, filenames in os.walk(self.filepath):
|
|
root = root[len(self.filepath):]
|
|
for filename in filenames:
|
|
filename = os.path.join(root, filename).replace('\\', '/')
|
|
|
|
# Ensure this file isn't sorted:
|
|
if filename in self.sort:
|
|
continue
|
|
|
|
# Ensure this file is applicable:
|
|
if not self.isApplicable(os.path.join(self.filepath, filename)):
|
|
continue
|
|
|
|
# Apply this file, and add it to the sort configuration:
|
|
self.apply(filename)
|
|
self.sort.append(filename)
|
|
|
|
# Finally, write the new sort configuration:
|
|
self.writeSortConfig()
|
|
|
|
def readSortConfig(self):
|
|
"""
|
|
Read the sort configuration.
|
|
"""
|
|
if not os.path.exists(self.sortFilename):
|
|
return
|
|
with open(self.sortFilename, 'r') as f:
|
|
self.sort = yaml.load(f) or []
|
|
|
|
def writeSortConfig(self):
|
|
"""
|
|
Write the sort configuration to disk.
|
|
"""
|
|
with open(self.sortFilename, 'w') as f:
|
|
for filename in self.sort:
|
|
f.write('- %s\n' % filename)
|
|
|
|
def getAmbience(self, group):
|
|
"""
|
|
Returns the ambience configurations for the specified group.
|
|
"""
|
|
return self.ambience.get(group, {})
|