mirror of https://github.com/H-uru/korman.git
Compare commits
9 Commits
b6e8c5b6dd
...
9244d3abc7
Author | SHA1 | Date |
---|---|---|
Adam Johnson | 9244d3abc7 | 5 months ago |
Adam Johnson | 73639302cc | 5 months ago |
Adam Johnson | 9dc7f6819d | 5 months ago |
Adam Johnson | 0f0d6e1086 | 5 months ago |
Adam Johnson | adb8b23284 | 5 months ago |
Adam Johnson | 0d84b78762 | 5 months ago |
Adam Johnson | 5b2c16cfb2 | 5 months ago |
Adam Johnson | 1cf33ba286 | 5 months ago |
Adam Johnson | 778caadf11 | 5 months ago |
19 changed files with 716 additions and 398 deletions
@ -0,0 +1,167 @@ |
|||||||
|
# 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/>. |
||||||
|
|
||||||
|
from __future__ import annotations |
||||||
|
|
||||||
|
from bpy.props import * |
||||||
|
|
||||||
|
from typing import * |
||||||
|
import warnings |
||||||
|
|
||||||
|
# Workaround for Blender memory management limitation, |
||||||
|
# don't change this to a literal in the code! |
||||||
|
_ENTIRE_ANIMATION = "(Entire Animation)" |
||||||
|
|
||||||
|
def _get_object_animation_names(self, object_attr: str) -> Sequence[Tuple[str, str, str]]: |
||||||
|
target_object = getattr(self, object_attr) |
||||||
|
if target_object is not None: |
||||||
|
items = [(anim.animation_name, anim.animation_name, "") |
||||||
|
for anim in target_object.plasma_modifiers.animation.subanimations] |
||||||
|
else: |
||||||
|
items = [(_ENTIRE_ANIMATION, _ENTIRE_ANIMATION, "")] |
||||||
|
|
||||||
|
# We always want "(Entire Animation)", if it exists, to be the first item. |
||||||
|
entire = items.index((_ENTIRE_ANIMATION, _ENTIRE_ANIMATION, "")) |
||||||
|
if entire not in (-1, 0): |
||||||
|
items.pop(entire) |
||||||
|
items.insert(0, (_ENTIRE_ANIMATION, _ENTIRE_ANIMATION, "")) |
||||||
|
|
||||||
|
return items |
||||||
|
|
||||||
|
def animation(object_attr: str, **kwargs) -> str: |
||||||
|
def get_items(self, context): |
||||||
|
return _get_object_animation_names(self, object_attr) |
||||||
|
|
||||||
|
return EnumProperty(items=get_items, **kwargs) |
||||||
|
|
||||||
|
# These are the kinds of physical bounds Plasma can work with. |
||||||
|
# This sequence is acceptable in any EnumProperty |
||||||
|
_bounds_types = ( |
||||||
|
("box", "Bounding Box", "Use a perfect bounding box"), |
||||||
|
("sphere", "Bounding Sphere", "Use a perfect bounding sphere"), |
||||||
|
("hull", "Convex Hull", "Use a convex set encompasing all vertices"), |
||||||
|
("trimesh", "Triangle Mesh", "Use the exact triangle mesh (SLOW!)") |
||||||
|
) |
||||||
|
|
||||||
|
def _bounds_type_index(key: str) -> int: |
||||||
|
return list(zip(*_bounds_types))[0].index(key) |
||||||
|
|
||||||
|
def _bounds_type_str(idx: int) -> str: |
||||||
|
return _bounds_types[idx][0] |
||||||
|
|
||||||
|
def _get_bounds(physics_attr: Optional[str]) -> Callable[[Any], int]: |
||||||
|
def getter(self) -> int: |
||||||
|
physics_object = getattr(self, physics_attr) if physics_attr is not None else self.id_data |
||||||
|
if physics_object is not None: |
||||||
|
return _bounds_type_index(physics_object.plasma_modifiers.collision.bounds) |
||||||
|
return _bounds_type_index("hull") |
||||||
|
return getter |
||||||
|
|
||||||
|
def _set_bounds(physics_attr: Optional[str]) -> Callable[[Any, int], None]: |
||||||
|
def setter(self, value: int): |
||||||
|
physics_object = getattr(self, physics_attr) if physics_attr is not None else self.id_data |
||||||
|
if physics_object is not None: |
||||||
|
physics_object.plasma_modifiers.collision.bounds = _bounds_type_str(value) |
||||||
|
return setter |
||||||
|
|
||||||
|
def bounds(physics_attr: Optional[str] = None, store_on_collider: bool = True, **kwargs) -> str: |
||||||
|
assert not {"items", "get", "set"} & kwargs.keys(), "You cannot use the `items`, `get`, or `set` keyword arguments" |
||||||
|
if store_on_collider: |
||||||
|
kwargs["get"] = _get_bounds(physics_attr) |
||||||
|
kwargs["set"] = _set_bounds(physics_attr) |
||||||
|
else: |
||||||
|
warnings.warn("Storing bounds properties outside of the collision modifier is deprecated.", category=DeprecationWarning) |
||||||
|
if "default" not in kwargs: |
||||||
|
kwargs["default"] = "hull" |
||||||
|
return EnumProperty( |
||||||
|
items=_bounds_types, |
||||||
|
**kwargs |
||||||
|
) |
||||||
|
|
||||||
|
def upgrade_bounds(bl, bounds_attr: str) -> None: |
||||||
|
# Only perform this process if the property has a value. Otherwise, we'll |
||||||
|
# wind up blowing away the collision modifier's settings with nonsense. |
||||||
|
if not bl.is_property_set(bounds_attr): |
||||||
|
return |
||||||
|
|
||||||
|
# Before we unregister anything, grab a copy of what the collision modifier currently thinks. |
||||||
|
bounds_value_curr = getattr(bl, bounds_attr) |
||||||
|
|
||||||
|
# So, here's the deal. If someone has been playing with nodes and changed the bounds type, |
||||||
|
# Blender will think the property has been set, even if they wound up with the property |
||||||
|
# at the default value. I don't know that we can really trust the default in the property |
||||||
|
# definition to be the same as the old default (they shouldn't be different, but let's be safe). |
||||||
|
# So, let's apply rough justice. If the destination property thinks it's a triangle mesh, we |
||||||
|
# don't need to blow that away - it's a very specific non default setting. |
||||||
|
if bounds_value_curr == "trimesh": |
||||||
|
return |
||||||
|
|
||||||
|
# Unregister the new/correct proxy bounds property (with getter/setter) and re-register |
||||||
|
# the property without the proxy functions to get the old value. Reregister the new property |
||||||
|
# again and set it. |
||||||
|
cls = bl.__class__ |
||||||
|
prop_func, prop_def = getattr(cls, bounds_attr) |
||||||
|
RemoveProperty(cls, attr=bounds_attr) |
||||||
|
del prop_def["attr"] |
||||||
|
|
||||||
|
# Remove the things we don't want in a copy to prevent hosing the new property. |
||||||
|
old_prop_def = dict(prop_def) |
||||||
|
del old_prop_def["get"] |
||||||
|
del old_prop_def["set"] |
||||||
|
setattr(cls, bounds_attr, prop_func(**old_prop_def)) |
||||||
|
bounds_value_new = getattr(bl, bounds_attr) |
||||||
|
|
||||||
|
# Re-register new property. |
||||||
|
RemoveProperty(cls, attr=bounds_attr) |
||||||
|
setattr(cls, bounds_attr, prop_func(**prop_def)) |
||||||
|
|
||||||
|
# Only set the property if the value different to avoid thrashing and log spam. |
||||||
|
if bounds_value_curr != bounds_value_new: |
||||||
|
print(f"Stashing bounds property: [{bl.name}] ({cls.__name__}) {bounds_value_curr} -> {bounds_value_new}") # TEMP |
||||||
|
setattr(bl, bounds_attr, bounds_value_new) |
||||||
|
|
||||||
|
def _get_texture_animation_names(self, object_attr: str, material_attr: str, texture_attr: str) -> Sequence[Tuple[str, str, str]]: |
||||||
|
target_object = getattr(self, object_attr) |
||||||
|
material = getattr(self, material_attr) |
||||||
|
texture = getattr(self, texture_attr) |
||||||
|
|
||||||
|
if texture is not None: |
||||||
|
items = [(anim.animation_name, anim.animation_name, "") |
||||||
|
for anim in texture.plasma_layer.subanimations] |
||||||
|
elif material is not None or target_object is not None: |
||||||
|
if material is None: |
||||||
|
materials = (i.material for i in target_object.material_slots if i and i.material) |
||||||
|
else: |
||||||
|
materials = (material,) |
||||||
|
layer_props = (i.texture.plasma_layer for mat in materials for i in mat.texture_slots if i and i.texture) |
||||||
|
all_anims = frozenset((anim.animation_name for i in layer_props for anim in i.subanimations)) |
||||||
|
items = [(i, i, "") for i in all_anims] |
||||||
|
else: |
||||||
|
items = [(_ENTIRE_ANIMATION, _ENTIRE_ANIMATION, "")] |
||||||
|
|
||||||
|
# We always want "(Entire Animation)", if it exists, to be the first item. |
||||||
|
entire = items.index((_ENTIRE_ANIMATION, _ENTIRE_ANIMATION, "")) |
||||||
|
if entire not in (-1, 0): |
||||||
|
items.pop(entire) |
||||||
|
items.insert(0, (_ENTIRE_ANIMATION, _ENTIRE_ANIMATION, "")) |
||||||
|
|
||||||
|
return items |
||||||
|
|
||||||
|
def triprop_animation(object_attr: str, material_attr: str, texture_attr: str, **kwargs) -> str: |
||||||
|
def get_items(self, context): |
||||||
|
return _get_texture_animation_names(self, object_attr, material_attr, texture_attr) |
||||||
|
|
||||||
|
assert not {"items", "get", "set"} & kwargs.keys(), "You cannot use the `items`, `get`, or `set` keyword arguments" |
||||||
|
return EnumProperty(items=get_items, **kwargs) |
@ -0,0 +1,134 @@ |
|||||||
|
# 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/>. |
||||||
|
|
||||||
|
python_files = { |
||||||
|
"xAgeSDLBoolShowHide.py": ( |
||||||
|
{ "id": 1, "type": "ptAttribString", "name": "sdlName" }, |
||||||
|
{ "id": 2, "type": "ptAttribBoolean", "name": "showOnTrue" }, |
||||||
|
# --- CWE Only Below --- |
||||||
|
{ "id": 3, "type": "ptAttribBoolean", "name": "defaultValue" }, |
||||||
|
{ "id": 4, "type": "ptAttribBoolean", "name": "evalOnFirstUpdate "}, |
||||||
|
), |
||||||
|
|
||||||
|
"xAgeSDLIntShowHide.py": ( |
||||||
|
{ "id": 1, "type": "ptAttribString", "name": "stringVarName" }, |
||||||
|
{ "id": 2, "type": "ptAttribString", "name": "stringShowStates" }, |
||||||
|
# --- CWE Only Below --- |
||||||
|
{ "id": 3, "type": "ptAttribInt", "name": "intDefault" }, |
||||||
|
{ "id": 4, "type": "ptAttribBoolean", "name": "boolFirstUpdate "}, |
||||||
|
), |
||||||
|
|
||||||
|
# Provided by all variants of Uru and Myst V |
||||||
|
"xDialogToggle.py": ( |
||||||
|
{ "id": 1, "type": "ptAttribActivator", "name": "Activate" }, |
||||||
|
{ "id": 4, "type": "ptAttribString", "name": "Vignette" }, |
||||||
|
), |
||||||
|
|
||||||
|
# Provided by CWE or OfflineKI |
||||||
|
"xDynTextLoc.py": ( |
||||||
|
{ "id": 1, "type": "ptAttribDynamicMap", "name": "dynTextMap", }, |
||||||
|
{ "id": 2, "type": "ptAttribString", "name": "locPath" }, |
||||||
|
{ "id": 3, "type": "ptAttribString", "name": "fontFace" }, |
||||||
|
{ "id": 4, "type": "ptAttribInt", "name": "fontSize" }, |
||||||
|
{ "id": 5, "type": "ptAttribFloat", "name": "fontColorR" }, |
||||||
|
{ "id": 6, "type": "ptAttribFloat", "name": "fontColorG" }, |
||||||
|
{ "id": 7, "type": "ptAttribFloat", "name": "fontColorB" }, |
||||||
|
{ "id": 8, "type": "ptAttribFloat", "name": "fontColorA" }, |
||||||
|
{ "id": 9, "type": "ptAttribInt", "name": "marginTop" }, |
||||||
|
{ "id": 10, "type": "ptAttribInt", "name": "marginLeft" }, |
||||||
|
{ "id": 11, "type": "ptAttribInt", "name": "marginBottom" }, |
||||||
|
{ "id": 12, "type": "ptAttribInt", "name": "marginRight" }, |
||||||
|
{ "id": 13, "type": "ptAttribInt", "name": "lineSpacing" }, |
||||||
|
# Yes, it"s really a ptAttribDropDownList, but those are only for use in |
||||||
|
# artist generated node trees. |
||||||
|
{ "id": 14, "type": "ptAttribString", "name": "justify" }, |
||||||
|
{ "id": 15, "type": "ptAttribFloat", "name": "clearColorR" }, |
||||||
|
{ "id": 16, "type": "ptAttribFloat", "name": "clearColorG" }, |
||||||
|
{ "id": 17, "type": "ptAttribFloat", "name": "clearColorB" }, |
||||||
|
{ "id": 18, "type": "ptAttribFloat", "name": "clearColorA" }, |
||||||
|
{ "id": 19, "type": "ptAttribBoolean", "name": "blockRGB" }, |
||||||
|
), |
||||||
|
|
||||||
|
# Provided by CWE and OfflineKI |
||||||
|
"xEntryCam.py": ( |
||||||
|
{ "id": 1, "type": "ptAttribActivator", "name": "actRegionSensor" }, |
||||||
|
{ "id": 2, "type": "ptAttribSceneobject", "name": "camera" }, |
||||||
|
{ "id": 3, "type": "ptAttribBoolean", "name": "undoFirstPerson" }, |
||||||
|
), |
||||||
|
|
||||||
|
# Provided by CWE |
||||||
|
"xJournalBookGUIPopup.py": ( |
||||||
|
{ "id": 1, "type": "ptAttribActivator", "name": "actClickableBook" }, |
||||||
|
{ "id": 10, "type": "ptAttribBoolean", "name": "StartOpen" }, |
||||||
|
{ "id": 11, "type": "ptAttribFloat", "name": "BookWidth" }, |
||||||
|
{ "id": 12, "type": "ptAttribFloat", "name": "BookHeight" }, |
||||||
|
{ "id": 13, "type": "ptAttribString", "name": "LocPath" }, |
||||||
|
{ "id": 14, "type": "ptAttribString", "name": "GUIType" }, |
||||||
|
), |
||||||
|
|
||||||
|
# Provided by all variants of Uru and Myst V |
||||||
|
"xLinkingBookGUIPopup.py": ( |
||||||
|
{ "id": 1, "type": "ptAttribActivator", "name": "actClickableBook" }, |
||||||
|
{ "id": 2, "type": "ptAttribBehavior", "name": "SeekBehavior" }, |
||||||
|
{ "id": 3, "type": "ptAttribResponder", "name": "respLinkResponder" }, |
||||||
|
{ "id": 4, "type": "ptAttribString", "name": "TargetAge" }, |
||||||
|
{ "id": 5, "type": "ptAttribActivator", "name": "actBookshelf" }, |
||||||
|
{ "id": 6, "type": "ptAttribActivator", "name": "shareRegion" }, |
||||||
|
{ "id": 7, "type": "ptAttribBehavior", "name": "shareBookSeek" }, |
||||||
|
{ "id": 10, "type": "ptAttribBoolean", "name": "IsDRCStamped" }, |
||||||
|
{ "id": 11, "type": "ptAttribBoolean", "name": "ForceThirdPerson" }, |
||||||
|
), |
||||||
|
|
||||||
|
# Supplied by the OfflineKI script: |
||||||
|
# https://gitlab.com/diafero/offline-ki/blob/master/offlineki/xSimpleJournal.py |
||||||
|
"xSimpleJournal.py": ( |
||||||
|
{ "id": 1, "type": "ptAttribActivator", "name": "bookClickable" }, |
||||||
|
{ "id": 2, "type": "ptAttribString", "name": "journalFileName" }, |
||||||
|
{ "id": 3, "type": "ptAttribBoolean", "name": "isNotebook" }, |
||||||
|
{ "id": 4, "type": "ptAttribFloat", "name": "BookWidth" }, |
||||||
|
{ "id": 5, "type": "ptAttribFloat", "name": "BookHeight" }, |
||||||
|
), |
||||||
|
|
||||||
|
# Supplied by the OfflineKI script: |
||||||
|
# https://gitlab.com/diafero/offline-ki/blob/master/offlineki/xSimpleLinkingBook.py |
||||||
|
"xSimpleLinkingBook.py": ( |
||||||
|
{ "id": 1, "type": "ptAttribActivator", "name": "bookClickable" }, |
||||||
|
{ "id": 2, "type": "ptAttribString", "name": "destinationAge" }, |
||||||
|
{ "id": 3, "type": "ptAttribString", "name": "spawnPoint" }, |
||||||
|
{ "id": 4, "type": "ptAttribString", "name": "linkPanel" }, |
||||||
|
{ "id": 5, "type": "ptAttribString", "name": "bookCover" }, |
||||||
|
{ "id": 6, "type": "ptAttribString", "name": "stampTexture" }, |
||||||
|
{ "id": 7, "type": "ptAttribFloat", "name": "stampX" }, |
||||||
|
{ "id": 8, "type": "ptAttribFloat", "name": "stampY" }, |
||||||
|
{ "id": 9, "type": "ptAttribFloat", "name": "bookWidth" }, |
||||||
|
{ "id": 10, "type": "ptAttribFloat", "name": "BookHeight" }, |
||||||
|
{ "id": 11, "type": "ptAttribBehavior", "name": "msbSeekBeforeUI" }, |
||||||
|
{ "id": 12, "type": "ptAttribResponder", "name": "respOneShot" }, |
||||||
|
), |
||||||
|
|
||||||
|
# Provided by CWE or OfflineKI |
||||||
|
"xSitCam.py": ( |
||||||
|
{ "id": 1, "type": "ptAttribActivator", "name": "sitAct" }, |
||||||
|
{ "id": 2, "type": "ptAttribSceneobject", "name": "sitCam" }, |
||||||
|
), |
||||||
|
|
||||||
|
# Provided by all variants of Uru and Myst V |
||||||
|
"xTelescope.py": ( |
||||||
|
{ "id": 1, "type": "ptAttribActivator", "name": "Activate" }, |
||||||
|
{ "id": 2, "type": "ptAttribSceneobject", "name": "Camera" }, |
||||||
|
{ "id": 3, "type": "ptAttribBehavior", "name": "Behavior" }, |
||||||
|
{ "id": 4, "type": "ptAttribString", "name": "Vignette" }, |
||||||
|
) |
||||||
|
} |
Loading…
Reference in new issue