mirror of
https://github.com/ApfelTeeSaft/lightspeed64.git
synced 2026-08-26 19:33:24 +00:00
* implement prop * first iter of custom cmd exporting * let rovert fly * Update sm64_objects.py * Update sm64_objects.py * Update sm64_objects.py * upgrade existing custom geo into new custom type * Hack for geo because * [SM64] Add depth arg and remove comma from existing cmds * [SM64] add depth arg to level and collision objects * change unused depth to _depth and add my stashed changes.. oops * some code clean up and ui improvement * Allow custom geo to have children * command preset system (WIP) allows you to create presets for your repo. missing auto updates to presets * detect changes via a hash * fix last remaining bugs * fix preset edit preview * add draw layers * basic example macro * boolean support and fixes * world's most over enginered way to handle numbers * bugs and visual fixes * make color serializable * dont use PRESET_EDIT if presumably there is no edit data * use degrees * inital support for bones * dont require transform to be inherented, fixes bone using scale arg * remove sys, last few bits of code tomorrow * move custom args into a folder * lock * typing fixes * use dict for exports * early binary support * Missing dl ext and animated * dl ext impl * make is animatable work * update updateBone to suit my new needs * finish upgrade code * dl ext now dl cmd, example macros for dl cmds * SM64_CustomArgProperties * enum property support to really hammer in the scope creep * Nice move by SpongeBob! This match is just about over. checked for mesh, removed one indent, changed Special to Collision * some fixes to the ops * make binary more flexiable by introducing eval expressions Now behavior that would require a macro can be written in an eval statement, this is peak over engineering. It's also present in c under a toggle because SCALE GEO CMD COMPATABILITY!!! * make hard defined int types for binary * one last fix * allow color quant for background node compat, fix enum ops * impl last translate/rotate name in custom * undo export color * fix area root UI * fix commas * add order, fix up a couple of nits * lila did a stupid * fix transforms * conventional rotation in macros is not scaled to s16 * let eval run on tuples * implement generators * add cast_integer * Update properties.py * round to conventional for scale * document collection operator base more, fix bug with scale rounding also add copy_on_add * undo repo settings ver change since there has been no breaking changes * remove unused * implement top level level script commands * make clean color into tuple, run eval on lists * update base displaylist node * little thing i noticed missing * unnecessary names removed * Fix transforms in level * fix parameter * show animatable toggle in presets * More control of the level script section * copy enum example * over engineered description code * update preset instead of changing to NONE * fix number updates * typo * fix crash * VERY IMPORTANT FIX * link to docs * add comment about updating existing animation pr ops * fix animation command checks
127 lines
4.6 KiB
Python
127 lines
4.6 KiB
Python
from typing import Literal, NamedTuple, Optional, TYPE_CHECKING
|
|
from re import fullmatch
|
|
|
|
import mathutils
|
|
from bpy.types import Object, Bone, Context, SpaceView3D, Scene
|
|
|
|
from ...utility import z_up_to_y_up_matrix
|
|
from ..sm64_geolayout_utility import updateBone
|
|
|
|
if TYPE_CHECKING:
|
|
from .properties import SM64_CustomCmdProperties
|
|
|
|
AvailableOwners = Object | Bone | Scene
|
|
CustomCmdConf = Literal["PRESET", "PRESET_EDIT", "NO_PRESET"] # type of configuration
|
|
|
|
|
|
def getDrawLayerName(drawLayer):
|
|
from ..sm64_geolayout_classes import getDrawLayerName
|
|
|
|
return getDrawLayerName(drawLayer)
|
|
|
|
|
|
def duplicate_name(name, existing_names: set, old_name: Optional[str] = None):
|
|
if not name in existing_names:
|
|
return name
|
|
num = 0
|
|
if old_name is not None:
|
|
number_match = fullmatch(r"(.*?)\.(\d+)$", old_name)
|
|
if number_match is not None: # if name already a duplicate/copy, add number
|
|
name, num = number_match.group(1), int(number_match.group(2))
|
|
else:
|
|
name, num = old_name, 0
|
|
|
|
for i in range(1, len(existing_names) + 1):
|
|
new_name = f"{name}.{num+i:03}"
|
|
if new_name not in existing_names: # only use name if it's unique
|
|
return new_name
|
|
assert False, "Failed to generate unique name"
|
|
|
|
|
|
def get_custom_prop(context: Context):
|
|
"""If owner is a scene, custom is always None"""
|
|
|
|
class CustomContext(NamedTuple):
|
|
custom: Optional["SM64_CustomCmdProperties"]
|
|
owner: Optional[AvailableOwners]
|
|
|
|
if isinstance(context.space_data, SpaceView3D):
|
|
return CustomContext(None, context.scene)
|
|
else:
|
|
if hasattr(context, "bone") and context.bone is not None:
|
|
return CustomContext(context.bone.fast64.sm64.custom, context.bone)
|
|
if hasattr(context, "object") and context.object is not None:
|
|
return CustomContext(context.object.fast64.sm64.custom, context.object)
|
|
return CustomContext(None, None)
|
|
|
|
|
|
def get_custom_cmd_preset(
|
|
custom_cmd: "SM64_CustomCmdProperties", context: Context
|
|
) -> Optional["SM64_CustomCmdProperties"]:
|
|
if custom_cmd.preset == "":
|
|
return None
|
|
presets: dict["SM64_CustomCmdProperties"] = {
|
|
custom.name: custom for custom in context.scene.fast64.sm64.custom_cmds
|
|
}
|
|
return presets[custom_cmd.preset]
|
|
|
|
|
|
def check_preset_hashes(owner: AvailableOwners, context: Context):
|
|
if owner.fast64.sm64.custom.locked:
|
|
return
|
|
custom_cmd: "SM64_CustomCmdProperties" = owner.fast64.sm64.custom
|
|
if custom_cmd.preset == "NONE":
|
|
return
|
|
preset_cmd = get_custom_cmd_preset(custom_cmd, context)
|
|
if preset_cmd is None:
|
|
custom_cmd.preset = "NONE"
|
|
elif custom_cmd.saved_hash != preset_cmd.preset_hash:
|
|
custom_cmd.from_dict(
|
|
preset_cmd.to_dict("PRESET_EDIT", owner, *get_transforms(owner), include_defaults=False), set_defaults=False
|
|
)
|
|
custom_cmd.saved_hash = preset_cmd.preset_hash
|
|
|
|
|
|
def custom_cmd_preset_update(_self, context: Context):
|
|
owner = get_custom_prop(context).owner
|
|
if isinstance(owner, Scene): # current context is scene, check all
|
|
for obj in context.scene.objects:
|
|
check_preset_hashes(obj, context)
|
|
if obj.type == "ARMATURE":
|
|
for bone in obj.data.bones:
|
|
check_preset_hashes(bone, context)
|
|
elif owner is not None:
|
|
check_preset_hashes(owner, context)
|
|
if isinstance(owner, Bone):
|
|
updateBone(owner, context)
|
|
|
|
|
|
def get_custom_cmd_preset_enum(_self, context: Context):
|
|
if isinstance(get_custom_prop(context)[1], Bone):
|
|
allowed_types = {"Geo"}
|
|
else:
|
|
allowed_types = {"Level", "Geo", "Special"}
|
|
return [("NONE", "No Preset", "No preset selected")] + [
|
|
(preset.name, preset.name, f"{preset.name} ({preset.cmd_type})")
|
|
for preset in (context.scene.fast64.sm64.custom_cmds)
|
|
if preset.cmd_type in allowed_types
|
|
]
|
|
|
|
|
|
def better_round(value: float): # round, but handle inf
|
|
return round(max(-(2**31), min(2**31 - 1, value)))
|
|
|
|
|
|
def get_transforms(owner: Optional[AvailableOwners] = None):
|
|
if isinstance(owner, Object):
|
|
return tuple(
|
|
z_up_to_y_up_matrix @ x @ z_up_to_y_up_matrix.inverted() for x in [owner.matrix_world, owner.matrix_local]
|
|
)
|
|
elif isinstance(owner, Bone):
|
|
relative = owner.matrix_local
|
|
if owner.parent is not None:
|
|
relative = owner.parent.matrix_local.inverted() @ relative
|
|
return tuple(z_up_to_y_up_matrix @ x @ z_up_to_y_up_matrix.inverted() for x in [owner.matrix_local, relative])
|
|
else:
|
|
return (z_up_to_y_up_matrix @ mathutils.Matrix.Identity(4) @ z_up_to_y_up_matrix.inverted(),) * 2
|