Browse Source

Allow programatically enabling/disabling Plasma Modifiers.

Previously, this functionality was implemented in context-dependent operators. Considering that Korman is becoming increasingly complex and is now generating entirely new objects (potentially with modifiers) as part of its export process, it was becoming cumbersome to use those operators.
pull/374/head
Adam Johnson 11 months ago
parent
commit
76459cfccf
Signed by: Hoikas
GPG Key ID: 0B6515D6FF6F271E
  1. 8
      korman/operators/op_mesh.py
  2. 95
      korman/operators/op_modifier.py
  3. 39
      korman/properties/modifiers/base.py
  4. 5
      korman/properties/modifiers/sound.py

8
korman/operators/op_mesh.py

@ -96,7 +96,7 @@ class PlasmaAddFlareOperator(PlasmaMeshOperator, bpy.types.Operator):
bpyscene.objects.active = flare_root
# Enable VFM on Empty
bpy.ops.object.plasma_modifier_add(types="viewfacemod")
flare_root.plasma_modifiers.viewfacemod.enabled = True
flare_root.plasma_modifiers.viewfacemod.preset_options = "Sprite"
# Create a textured Plane
@ -416,8 +416,8 @@ class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator):
origin_to_bottom(upper_rgn)
upper_rgn.rotation_euler[2] = math.radians(90.0)
bpy.ops.object.plasma_modifier_add(types="laddermod")
laddermod = upper_rgn.plasma_modifiers.laddermod
laddermod.enabled = True
laddermod.is_enabled = self.lower_entry_enabled
laddermod.num_loops = (self.ladder_height - 6) / 2
laddermod.direction = "DOWN"
@ -457,8 +457,8 @@ class PlasmaAddLadderMeshOperator(PlasmaMeshOperator, bpy.types.Operator):
origin_to_bottom(lower_rgn)
lower_rgn.rotation_euler[2] = math.radians(-90.0)
bpy.ops.object.plasma_modifier_add(types="laddermod")
laddermod = lower_rgn.plasma_modifiers.laddermod
laddermod.enabled = True
laddermod.is_enabled = self.lower_entry_enabled
laddermod.num_loops = (self.ladder_height - 6) / 2
laddermod.direction = "UP"
@ -604,8 +604,8 @@ class PlasmaAddLinkingBookMeshOperator(PlasmaMeshOperator, bpy.types.Operator):
# Add Linking Book modifier
bpyscene.objects.active = panel_root
panel_root.select = True
bpy.ops.object.plasma_modifier_add(types="linkingbookmod")
lbmod = panel_root.plasma_modifiers.linkingbookmod
lbmod.enabled = True
lbmod.clickable_region = clk_rgn
lbmod.seek_point = seek_point
lbmod.anim_type = self.link_anim_type

95
korman/operators/op_modifier.py

@ -13,11 +13,15 @@
# You should have received a copy of the GNU General Public License
# along with Korman. If not, see <http://www.gnu.org/licenses/>.
from __future__ import annotations
import bpy
from bpy.props import *
import itertools
import time
from typing import *
from ..ordered_set import OrderedSet
from ..properties import modifiers
def _fetch_modifiers():
@ -32,7 +36,7 @@ def _fetch_modifiers():
return items
class ModifierOperator:
def _get_modifier(self, context):
def _get_modifier(self, context) -> modifiers.PlasmaModifierProperties:
if self.active_modifier == -1:
return None
pl_mods = context.object.plasma_modifiers.modifiers
@ -51,24 +55,16 @@ class ModifierAddOperator(ModifierOperator, bpy.types.Operator):
bl_label = "Add Modifier"
bl_description = "Adds a Plasma Modifier"
types = EnumProperty(name="Modifier Type",
description="The type of modifier we add to the list",
items=_fetch_modifiers())
types = EnumProperty(
name="Modifier Type",
description="The type of modifier we add to the list",
items=_fetch_modifiers()
)
def execute(self, context):
plmods = context.object.plasma_modifiers
myType = self.types
theMod = getattr(plmods, myType)
theMod.display_order = plmods.determine_next_id()
theMod.created()
# Determine if this modifier has any dependencies and make sure they're enabled
deps = getattr(theMod, "pl_depends", set())
for dep in deps:
depMod = getattr(plmods, dep)
if not depMod.enabled:
bpy.ops.object.plasma_modifier_add(types=dep)
modifier = getattr(context.object.plasma_modifiers, self.types)
modifier.enabled = True
return {"FINISHED"}
@ -195,61 +191,36 @@ class ModifierRemoveOperator(ModifierOperator, bpy.types.Operator):
bl_label = "Remove Modifier"
bl_description = "Removes this Plasma Modifier"
active_modifier = IntProperty(name="Modifier Display Order",
default=-1,
options={"HIDDEN"})
mods2delete = CollectionProperty(type=modifiers.PlasmaModifierSpec, options=set())
active_modifier = IntProperty(
name="Modifier Display Order",
default=-1,
options={"HIDDEN"}
)
def draw(self, context):
layout = self.layout
mods = context.object.plasma_modifiers
pl_mods = context.object.plasma_modifiers
mod = self._get_modifier(context)
mods_to_delete = itertools.chain(
(getattr(pl_mods, i) for i in mod.get_dependents()),
[mod]
)
layout.label("This action will remove the following modifiers:")
layout = layout.column_flow(align=True)
for i in self.mods2delete:
mod = getattr(mods, i.name)
layout.label(" {}".format(mod.bl_label), icon=getattr(mod, "bl_icon", "NONE"))
for mod in filter(lambda x: x.enabled, mods_to_delete):
layout.label(f" {mod.bl_label}", icon=getattr(mod, "bl_icon", "NONE"))
def execute(self, context):
want2delete = set((i.name for i in self.mods2delete))
mods = sorted(context.object.plasma_modifiers.modifiers, key=lambda x: x.display_order)
subtract = 0
for mod in mods:
if mod.pl_id in want2delete:
mod.display_order = -1
mod.destroyed()
subtract += 1
else:
mod.display_order -= subtract
self._get_modifier(context).enabled = False
return {"FINISHED"}
def invoke(self, context, event):
mods = context.object.plasma_modifiers
self.mods2delete.clear()
want2delete = OrderedSet()
if self.active_modifier == -1:
want2delete.update((i.pl_id for i in context.object.plasma_modifiers.modifiers))
else:
want2delete.add(self._get_modifier(context).pl_id)
# Here's the rub
# When we start, we should have just one modifier in want2delete
# HOWEVER, the mod may have dependencies, which in turn may have more deps
# So we collect them into the list... you dig?
for i in want2delete:
for mod in modifiers.PlasmaModifierProperties.__subclasses__():
if not getattr(mods, mod.pl_id).enabled:
continue
if i in getattr(mod, "pl_depends", set()):
want2delete.add(mod.pl_id)
for i in want2delete:
mod = self.mods2delete.add()
mod.name = i
if len(want2delete) == 1:
has_dependents = any(
getattr(context.object.plasma_modifiers, i).enabled
for i in self._get_modifier(context).get_dependents()
)
if not has_dependents:
return self.execute(context)
else:
return context.window_manager.invoke_props_dialog(self)

39
korman/properties/modifiers/base.py

@ -17,7 +17,8 @@ import bpy
from bpy.props import *
import abc
from typing import Any, Dict, Generator, Optional
import itertools
from typing import Any, Dict, FrozenSet, Optional
class PlasmaModifierProperties(bpy.types.PropertyGroup):
@property
@ -45,15 +46,37 @@ class PlasmaModifierProperties(bpy.types.PropertyGroup):
def draw_no_defer(self):
"""Disallow geometry being sorted into a blending span"""
return False
@property
def draw_late(self):
return False
@property
def enabled(self):
def enabled(self) -> bool:
return self.display_order >= 0
@enabled.setter
def enabled(self, value: bool) -> None:
plmods = self.id_data.plasma_modifiers
if value and self.enabled is False:
self.display_order = plmods.determine_next_id()
self.created()
# Determine if this modifier has any dependencies and make sure they're enabled
for dep in getattr(self, "pl_depends", set()):
getattr(plmods, dep).enabled = True
elif not value and self.enabled is True:
mods_to_delete = frozenset(itertools.chain([self.pl_id], self.get_dependents()))
enabled_mods = sorted(self.id_data.plasma_modifiers.modifiers, key=lambda x: x.display_order)
subtract = 0
for modifier in enabled_mods:
if modifier.pl_id in mods_to_delete:
modifier.display_order = -1
modifier.destroyed()
subtract += 1
else:
modifier.display_order -= subtract
def export(self, exporter, bo, so):
"""This is the main phase of the modifier export where most, if not all, PRP objects should
be generated. No new Blender objects should be created unless their lifespan is constrained
@ -75,6 +98,16 @@ class PlasmaModifierProperties(bpy.types.PropertyGroup):
"""Indicates that the geometry's faces should be sorted by the engine"""
return False
@classmethod
def get_dependents(cls) -> FrozenSet[str]:
"""Returns the set of modifiers that depend on this modifier being active."""
deps = set()
for i in PlasmaModifierProperties.__subclasses__():
if cls.pl_id in getattr(i, "pl_depends", []):
deps.add(i.pl_id)
deps.update(i.get_dependents())
return frozenset(deps)
def harvest_actors(self):
return ()

5
korman/properties/modifiers/sound.py

@ -556,8 +556,7 @@ class PlasmaSoundEmitter(PlasmaModifierProperties):
emitter_obj.plasma_modifiers.modifiers
)
for i in bad_mods:
# HACK: You can't set the enabled property.
i.display_order = -1
i.enabled = False
# But only 3D stereo sounds!
soundemit_mod = emitter_obj.plasma_modifiers.soundemit
@ -630,7 +629,7 @@ class PlasmaSoundEmitter(PlasmaModifierProperties):
if not my_anim_groups:
group = bo.plasma_modifiers.animation_group
if not group.enabled:
toggle.track(group, "display_order", sum((1 for i in bo.plasma_modifiers.modifiers)))
toggle.track(group, "enabled", True)
for i in group.children:
toggle.track(i, "enabled", False)
my_anim_groups.append(group)

Loading…
Cancel
Save