From 67f2b907e05b092c66f56cdc06c44f67ca0beead Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 8 Sep 2018 13:33:51 -0400 Subject: [PATCH 1/3] Fix #120 --- korman/nodes/node_deprecated.py | 13 ++++++++++++- korman/nodes/node_responder.py | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/korman/nodes/node_deprecated.py b/korman/nodes/node_deprecated.py index 7743cfe..d3d5bdd 100644 --- a/korman/nodes/node_deprecated.py +++ b/korman/nodes/node_deprecated.py @@ -13,6 +13,7 @@ # You should have received a copy of the GNU General Public License # along with Korman. If not, see . +import abc import bpy from bpy.props import * from collections import OrderedDict @@ -20,16 +21,26 @@ from collections import OrderedDict from .node_core import * class PlasmaDeprecatedNode(PlasmaNodeBase): + @abc.abstractmethod def upgrade(self): raise NotImplementedError() class PlasmaVersionedNode(PlasmaNodeBase): + def init(self, context): + self.version = self.latest_version + + @property + @abc.abstractmethod + def latest_version(self): + raise NotImplementedError() + @classmethod def register(cls): cls.version = IntProperty(name="Node Version", default=1, options=set()) - def upgrade(self, from_version): + @abc.abstractmethod + def upgrade(self): raise NotImplementedError() diff --git a/korman/nodes/node_responder.py b/korman/nodes/node_responder.py index b209d4b..b6d8702 100644 --- a/korman/nodes/node_responder.py +++ b/korman/nodes/node_responder.py @@ -135,6 +135,10 @@ class PlasmaResponderNode(PlasmaVersionedNode, bpy.types.Node): stateMgr.register_state(stateNode) stateMgr.convert_states(exporter, so) + @property + def latest_version(self): + return 2 + def upgrade(self): # In version 1 responder nodes, responder states could be linked to the responder # or to subsequent responder state nodes and be exported. The problem with this From 1f9a872afc978f2db273196403d902d33a7eb428 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 8 Sep 2018 14:32:53 -0400 Subject: [PATCH 2/3] Fix another dict check-key then add antipattern --- korman/properties/modifiers/__init__.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/korman/properties/modifiers/__init__.py b/korman/properties/modifiers/__init__.py index 294af4c..f4905d3 100644 --- a/korman/properties/modifiers/__init__.py +++ b/korman/properties/modifiers/__init__.py @@ -88,8 +88,6 @@ def modifier_mapping(): label = label[:-len(category)-1] tup = (pl_id, label, description, icon, i) - if category not in d: - d[category] = [tup] - else: - d[category].append(tup) + d_cat = d.setdefault(category, []) + d_cat.append(tup) return d From 647c09e6e67e30ad1f0410d83e528c8f155405cf Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 8 Sep 2018 14:33:47 -0400 Subject: [PATCH 3/3] Implement modifier version upgrading --- korman/properties/modifiers/base.py | 55 ++++++++++++++++++++++++++- korman/properties/modifiers/render.py | 2 +- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/korman/properties/modifiers/base.py b/korman/properties/modifiers/base.py index bdfcf0a..d9f5c89 100644 --- a/korman/properties/modifiers/base.py +++ b/korman/properties/modifiers/base.py @@ -62,7 +62,10 @@ class PlasmaModifierProperties(bpy.types.PropertyGroup): "options": {"HIDDEN"}}), "show_expanded": (BoolProperty, {"name": "INTERNAL: Actually draw the modifier", "default": True, - "options": {"HIDDEN"}}) + "options": {"HIDDEN"}}), + "current_version": (IntProperty, {"name": "INTERNAL: Modifier version", + "default": 1, + "options": {"HIDDEN"}}), } @@ -78,3 +81,53 @@ class PlasmaModifierLogicWiz: @abc.abstractmethod def logicwiz(self, bo): pass + + +class PlasmaModifierUpgradable: + @property + @abc.abstractmethod + def latest_version(self): + raise NotImplementedError() + + @property + def requires_upgrade(self): + current_version, latest_version = self.current_version, self.latest_version + assert current_version < latest_version + return current_version < latest_version + + @abc.abstractmethod + def upgrade(self): + raise NotImplementedError() + + +@bpy.app.handlers.persistent +def _restore_properties(dummy): + # When Blender opens, it loads the default blend. The post load handler + # below is executed and deprecated properties are unregistered. When the + # user goes to load a new blend file, the handler below tries to execute + # again and BOOM--there are no deprecated properties available. Therefore, + # we reregister them here. + for mod_cls in PlasmaModifierUpgradable.__subclasses__(): + for prop_name in mod_cls.deprecated_properties: + # Unregistered propertes are a sequence of (property function, + # property keyword arguments). Interesting design decision :) + prop_cb, prop_kwargs = getattr(mod_cls, prop_name) + del prop_kwargs["attr"] # Prevents proper registration + setattr(mod_cls, prop_name, prop_cb(**prop_kwargs)) +bpy.app.handlers.load_pre.append(_restore_properties) + +@bpy.app.handlers.persistent +def _upgrade_modifiers(dummy): + # First, run all the upgrades + for i in bpy.data.objects: + for mod_cls in PlasmaModifierUpgradable.__subclasses__(): + mod = getattr(i.plasma_modifiers, mod_cls.pl_id) + if mod.requires_upgrade: + mod.upgrade() + + # Now that everything is upgraded, forcibly remove all properties + # from the modifiers to prevent sneaky zombie-data type export bugs + for mod_cls in PlasmaModifierUpgradable.__subclasses__(): + for prop in mod_cls.deprecated_properties: + RemoveProperty(mod_cls, attr=prop) +bpy.app.handlers.load_post.append(_upgrade_modifiers) diff --git a/korman/properties/modifiers/render.py b/korman/properties/modifiers/render.py index 00cf8a0..bd4ae04 100644 --- a/korman/properties/modifiers/render.py +++ b/korman/properties/modifiers/render.py @@ -18,7 +18,7 @@ import bpy from bpy.props import * from PyHSPlasma import * -from .base import PlasmaModifierProperties +from .base import PlasmaModifierProperties, PlasmaModifierUpgradable from ...exporter.etlight import _NUM_RENDER_LAYERS from ...exporter import utils from ...exporter.explosions import ExportError