You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

185 lines
7.3 KiB

# This file is part of Korman.
#
# Korman is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Korman is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Korman. If not, see <http://www.gnu.org/licenses/>.
import bpy
from bpy.props import *
from PyHSPlasma import *
class PlasmaObject(bpy.types.PropertyGroup):
def _enabled(self, context):
if not self.is_property_set("page"):
self._init(context)
def _init(self, context):
o = self.id_data
age = context.scene.world.plasma_age
# We want to encourage the pages = layers paradigm.
# So, let's see which layers we're on and check for a page whose
# suffix matches our layers. We'll take the first match.
num_layers = len(o.layers)
for page in age.pages:
if page.seq_suffix > num_layers:
continue
if page.page_type == "external":
continue
if o.layers[page.seq_suffix - 1]:
o.plasma_object.page = page.name
break
enabled = BoolProperty(name="Export",
description="Export this as a discrete object",
default=False,
update=_enabled)
page = StringProperty(name="Page",
description="Page this object will be exported to")
# DEAD - leaving in just in case external code uses it
is_inited = BoolProperty(description="DEAD",
default=False,
options={"HIDDEN"})
@property
def ci_type(self):
if self.id_data.plasma_modifiers.animation_filter.enabled:
return plFilterCoordInterface
else:
return plCoordinateInterface
@property
def has_animation_data(self):
bo = self.id_data
if bo.animation_data is not None:
if bo.animation_data.action is not None:
return True
data = getattr(bo, "data", None)
if data is not None:
if data.animation_data is not None:
if data.animation_data.action is not None:
return True
return False
@property
def has_transform_animation(self):
bo = self.id_data
if bo.animation_data is not None:
if bo.animation_data.action is not None:
data_paths = frozenset((i.data_path for i in bo.animation_data.action.fcurves))
return {"location", "rotation_euler", "rotation_quaternion", "rotation_axis_angle", "scale"} & data_paths
return False
@property
def subworld(self):
bo = self.id_data
while bo is not None:
if bo.plasma_modifiers.subworld_def.enabled:
return bo
else:
bo = bo.parent
return None
class PlasmaNet(bpy.types.PropertyGroup):
manual_sdl = BoolProperty(name="Override SDL",
description="ADVANCED: Manually track high level states on this object",
default=False)
sdl_names = 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)
if value == "volatile":
volatile.add(attr)
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 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 scnobj.modifiers:
if isinstance(modKey.object, plPythonFileMod):
has_pfm = True
break
else:
has_pfm = False
# If we have either a kickable or a PFM, the PlasmaMax default is to exclude all the
# logic-type stuff for higher level processing (namely, python)
if has_kickable or has_pfm:
exclude.add("AGMaster")
exclude.add("Layer")
exclude.add("Responder")
exclude.add("Sound")
exclude.add("XRegion")
else:
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):
synobj.synchFlags |= plSynchedObject.kAllStateIsVolatile
elif volatile:
synobj.synchFlags |= plSynchedObject.kHasVolatileState
synobj.volatiles = sorted(volatile)
# Inspect and apply exclude states, if any
if len(exclude) == len(self.sdl_names):
synobj.synchFlags |= plSynchedObject.kExcludeAllPersistentState
elif exclude:
synobj.synchFlags |= plSynchedObject.kExcludePersistentState
synobj.excludes = sorted(exclude)
@classmethod
def register(cls):
def SdlEnumProperty(name):
value = bpy.props.EnumProperty(name=name,
description="{} state synchronization".format(name),
items=[
("save", "Save to Server", "Save state on the server"),
("volatile", "Volatile on Server", "Throw away state when the age shuts down"),
("exclude", "Don't Send to Server", "Don't synchronize with the server"),
],
default="exclude")
setattr(PlasmaNet, name, value)
PlasmaNet.sdl_names.add(name)
agmaster = SdlEnumProperty("AGMaster")
avatar = SdlEnumProperty("Avatar")
avatar_phys = SdlEnumProperty("AvatarPhysical")
clone = SdlEnumProperty("CloneMessage")
clothing = SdlEnumProperty("Clothing")
layer = SdlEnumProperty("Layer")
morph = SdlEnumProperty("MorphSequence")
particle = SdlEnumProperty("ParticleSystem")
physical = SdlEnumProperty("Physical")
responder = SdlEnumProperty("Responder")
sound = SdlEnumProperty("Sound")
xregion = SdlEnumProperty("XRegion")