diff --git a/korman/exporter/convert.py b/korman/exporter/convert.py index 1bd307b..4e26fe0 100644 --- a/korman/exporter/convert.py +++ b/korman/exporter/convert.py @@ -270,12 +270,23 @@ class Exporter: def _post_process_scene_objects(self): print("\nPostprocessing SceneObjects...") + + mat_mgr = self.mesh.material for bl_obj in self._objects: sceneobject = self.mgr.find_object(plSceneObject, bl=bl_obj) if sceneobject is None: # no SO? fine then. turd. continue - bl_obj.plasma_net.export(bl_obj, sceneobject) + + # Synchronization is applied for the root SO and all animated layers (WTF) + # So, we have to keep in mind shared layers (whee) in the synch options kode + net = bl_obj.plasma_net + net.propagate_synch_options(sceneobject, sceneobject) + for mat in mat_mgr.get_materials(bl_obj): + for layer in mat.object.layers: + layer = layer.object + if isinstance(layer, plLayerAnimation): + net.propagate_synch_options(sceneobject, layer) # Modifiers don't have to expose post-processing, but if they do, run it for mod in bl_obj.plasma_modifiers.modifiers: diff --git a/korman/exporter/material.py b/korman/exporter/material.py index 5c5b98d..8eac18d 100644 --- a/korman/exporter/material.py +++ b/korman/exporter/material.py @@ -590,7 +590,7 @@ class MaterialConverter: layer.object.texture = mipmap.key def get_materials(self, bo): - return self._obj2mat[bo] + return self._obj2mat.get(bo, []) def get_texture_animation_key(self, bo, bm, tex_name): """Finds or creates the appropriate key for sending messages to an animated Texture""" diff --git a/korman/properties/prop_object.py b/korman/properties/prop_object.py index e8fa54b..2ea9e55 100644 --- a/korman/properties/prop_object.py +++ b/korman/properties/prop_object.py @@ -81,8 +81,8 @@ class PlasmaNet(bpy.types.PropertyGroup): default=False) sdl_names = set() - def export(self, bo, so): - volatile, exclude = set(), set() + def propagate_synch_options(self, scnobj, synobj): + volatile, exclude = set(synobj.volatiles), set(synobj.excludes) if self.manual_sdl: for attr in self.sdl_names: value = getattr(self, attr) @@ -91,15 +91,21 @@ class PlasmaNet(bpy.types.PropertyGroup): elif value == "exclude": exclude.add(attr) else: + # This SynchedObject may have already excluded or volatile'd everything + # If so, bail. + if synobj.synchFlags & plSynchedObject.kExcludeAllPersistentState or \ + synobj.synchFlags & plSynchedObject.kAllStateIsVolatile: + return + # Is this a kickable? - if so.sim is not None: - phys = so.sim.object.physical.object + if scnobj.sim is not None: + phys = scnobj.sim.object.physical.object has_kickable = (phys.memberGroup == plSimDefs.kGroupDynamic) else: has_kickable = False # Is there a PythonFileMod? - for modKey in so.modifiers: + for modKey in scnobj.modifiers: if isinstance(modKey.object, plPythonFileMod): has_pfm = True break @@ -115,21 +121,25 @@ class PlasmaNet(bpy.types.PropertyGroup): exclude.add("Sound") exclude.add("XRegion") else: - so.synchFlags |= plSynchedObject.kExcludeAllPersistentState + exclude.update(self.sdl_names) + + # It doesn't make sense for a state to be both excluded and volatile. + # So, if it somehow appears in both lists, we will exclude that state. + volatile = volatile.difference(exclude) # Inspect and apply volatile states, if any if len(volatile) == len(self.sdl_names): - so.synchFlags |= plSynchedObject.kAllStateIsVolatile + synobj.synchFlags |= plSynchedObject.kAllStateIsVolatile elif volatile: - so.synchFlags |= plSynchedObject.kHasVolatileState - so.volatiles = sorted(volatile) + synobj.synchFlags |= plSynchedObject.kHasVolatileState + synobj.volatiles = sorted(volatile) # Inspect and apply exclude states, if any if len(exclude) == len(self.sdl_names): - so.synchFlags |= plSynchedObject.kExcludeAllPersistentState + synobj.synchFlags |= plSynchedObject.kExcludeAllPersistentState elif exclude: - so.synchFlags |= plSynchedObject.kExcludePersistentState - so.excludes = sorted(exclude) + synobj.synchFlags |= plSynchedObject.kExcludePersistentState + synobj.excludes = sorted(exclude) @classmethod def register(cls):