almost there with this one, LZMA and LZ4 don't work
This commit is contained in:
Vendored
+1
@@ -3,6 +3,7 @@
|
||||
"D:\\SteamLibrary\\steamapps\\common\\Blender\\4.3\\scripts\\addons",
|
||||
"C:\\Users\\Onan\\AppData\\Roaming\\Blender Foundation\\Blender\\4.3\\extensions\\user_default\\",//C:/Users/Onan/AppData/Roaming/Blender Foundation/Blender/4.0/scripts/addons
|
||||
"D:\\blender stuff\\blendercodestuff\\4.3",
|
||||
"D:\\SteamLibrary\\steamapps\\common\\Blender\\4.3\\python\\lib\\site-packages",
|
||||
"/Users/frankche/Documents/blendercoding/4.1/",
|
||||
"/Users/frankche/Library/Application Support/Blender/4.3/extensions/user_default/"
|
||||
],
|
||||
|
||||
+64
-1
@@ -1,11 +1,14 @@
|
||||
import bpy
|
||||
|
||||
import numpy as np
|
||||
from .dictionaries import bone_names
|
||||
import threading
|
||||
import time
|
||||
import webbrowser
|
||||
import typing
|
||||
import struct
|
||||
from io import BytesIO
|
||||
|
||||
from .dictionaries import bone_names
|
||||
from ..core.register import register_wrap
|
||||
from typing import List, Optional, Tuple
|
||||
from bpy.types import Object, ShapeKey, Mesh, Context, Material, PropertyGroup
|
||||
@@ -497,3 +500,63 @@ def transfer_vertex_weights(context: Context, obj: bpy.types.Object, source_grou
|
||||
|
||||
return True
|
||||
|
||||
#Binary tools
|
||||
|
||||
import ctypes
|
||||
def ReadCSharp_str(data: BytesIO) -> str:
|
||||
return data.read(read7bitEncoded_int(data)).decode('utf-16-le')
|
||||
|
||||
def WriteCSharp_str(data: BytesIO, string: str) -> str:
|
||||
write7bitEncoded_int(len(string)*2)
|
||||
return data.write(string.encode("utf-16-le"))
|
||||
|
||||
def read7bitEncoded_ulong(data: BytesIO) -> np.int64:
|
||||
num: ctypes.c_uint = ctypes.c_uint(0)
|
||||
num2: int = 0
|
||||
flag: bool = True
|
||||
|
||||
while (flag):
|
||||
b: ctypes.c_ubyte = ctypes.c_ubyte(struct.unpack('<B', data.read(1))[0])
|
||||
flag = ((b & 128) > 0)
|
||||
num |= ((b & 127) << num2)
|
||||
num2 += 7
|
||||
if not flag:
|
||||
break
|
||||
|
||||
return num
|
||||
|
||||
def read7bitEncoded_int(data: BytesIO) -> ctypes.c_int:
|
||||
num: ctypes.c_int = ctypes.c_int(0)
|
||||
num2:ctypes.c_int = ctypes.c_int(0)
|
||||
while (num2 != 35):
|
||||
b: ctypes.c_ubyte = ctypes.c_ubyte(struct.unpack('<B', data.read(1))[0])
|
||||
num |= int(b & 127) << num2
|
||||
num2 += 7
|
||||
if ((b & 128) == 0):
|
||||
return num
|
||||
return -1
|
||||
|
||||
def write7bitEncoded_ulong(data: BytesIO, integer: ctypes.c_ulong) -> None:
|
||||
while integer > ctypes.c_ulong(0):
|
||||
b: ctypes.c_ubyte = ctypes.c_ubyte(integer & ctypes.c_ulong(127))
|
||||
integer >>= 7
|
||||
if integer > ctypes.c_ulong(0):
|
||||
b |= 128
|
||||
data.write(b)
|
||||
if integer <= ctypes.c_ulong(0):
|
||||
return
|
||||
|
||||
def write7bitEncoded_int(data: BytesIO, value: ctypes.c_int) -> None:
|
||||
num: ctypes.c_uint = ctypes.c_uint(value)
|
||||
while(num >= ctypes.c_ubyte(128)):
|
||||
data.write(ctypes.c_ubyte(num | ctypes.c_ubyte(128)))
|
||||
num >>= 7
|
||||
data.Write(ctypes.c_ubyte(num))
|
||||
|
||||
|
||||
#encoding FrooxEngine/C# types in binary:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import bpy
|
||||
|
||||
from typing import List, Optional
|
||||
from .common import get_armature
|
||||
from bpy.types import Object, ShapeKey, Mesh, Context, Operator
|
||||
from functools import lru_cache
|
||||
from ..core.register import register_wrap
|
||||
from ..functions.translations import t
|
||||
|
||||
|
||||
@register_wrap
|
||||
class AvatarToolKit_OT_ExportResonite(Operator):
|
||||
bl_idname = 'avatar_toolkit.export_resonite'
|
||||
bl_label = t("Importer.export_resonite.label")
|
||||
bl_description = t("Importer.export_resonite.desc")
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
filepath: bpy.props.StringProperty()
|
||||
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context: Context):
|
||||
if get_armature(context) is None:
|
||||
return False
|
||||
return True
|
||||
|
||||
def execute(self, context: Context):
|
||||
#settings stolen from cats.
|
||||
bpy.ops.export_scene.gltf('INVOKE_AREA',
|
||||
export_image_format = 'WEBP',
|
||||
export_image_quality = 75,
|
||||
export_materials = 'EXPORT',
|
||||
export_animations = True,
|
||||
export_animation_mode = 'ACTIONS',
|
||||
export_nla_strips_merged_animation_name = 'Animation',
|
||||
export_nla_strips = True)
|
||||
return {'FINISHED'}
|
||||
@@ -43,6 +43,7 @@ import_types: dict[str, typing.Callable[[str, list[dict[str,str]], str], None]]
|
||||
"vrm": (lambda directory, files, filepath: bpy.ops.import_scene.vrm(filepath=filepath)),
|
||||
"pmx": (lambda directory, files, filepath : import_pmx(filepath)),
|
||||
"pmd": (lambda directory, files, filepath : import_pmd(filepath)),
|
||||
"animx": (lambda directory, files, filepath : bpy.ops.avatar_toolkit.animx_importer(directory=directory,files=files,filepath=filepath)),
|
||||
}
|
||||
|
||||
def concat_imports_filter(imports):
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{
|
||||
"language": 0
|
||||
"language": 0,
|
||||
"last_update_check": 1734208835.8049936
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import ctypes
|
||||
import typing
|
||||
import struct
|
||||
from io import BytesIO
|
||||
|
||||
def ReadCSharp_str(data: BytesIO) -> str:
|
||||
charamount = read7bitEncoded_int(data)
|
||||
print(charamount)
|
||||
return data.read(charamount).decode('utf-8', errors="replace")
|
||||
|
||||
def WriteCSharp_str(data: BytesIO, string: str) -> str:
|
||||
write7bitEncoded_int(len(string))
|
||||
return data.write(string.encode("utf-8", errors="replace"))
|
||||
|
||||
def read7bitEncoded_ulong(data: BytesIO) -> int:
|
||||
num: int = int(0)
|
||||
num2: int = 0
|
||||
flag: bool = True
|
||||
|
||||
while (flag):
|
||||
b: int = int(struct.unpack('<B', data.read(1))[0])
|
||||
flag = ((b & 128) > 0)
|
||||
num |= ((b & 127) << num2)
|
||||
num2 += 7
|
||||
if not flag:
|
||||
break
|
||||
|
||||
return num
|
||||
|
||||
def read7bitEncoded_int(data: BytesIO) -> int:
|
||||
num: int= int(0)
|
||||
num2:int = int(0)
|
||||
while (num2 != 35):
|
||||
b: int = int(struct.unpack('<B', data.read(1))[0])
|
||||
num |= int(b & 127) << num2
|
||||
num2 += 7
|
||||
if ((b & 128) == 0):
|
||||
return num
|
||||
return -1
|
||||
|
||||
def write7bitEncoded_ulong(data: BytesIO, integer: int) -> None:
|
||||
while integer > int(0):
|
||||
b: int = ctypes.c_ubyte(integer & int(127))
|
||||
integer >>= 7
|
||||
if integer > int(0):
|
||||
b |= 128
|
||||
data.write(b)
|
||||
if integer <= int(0):
|
||||
return
|
||||
|
||||
def write7bitEncoded_int(data: BytesIO, value: int) -> None:
|
||||
num: int = int(value)
|
||||
while(num >= int(128)):
|
||||
data.write(int(num | int(128)))
|
||||
num >>= 7
|
||||
data.Write(int(num))
|
||||
@@ -0,0 +1,472 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import lz4.block
|
||||
from . import resonite_types
|
||||
from . import common
|
||||
|
||||
import ctypes
|
||||
import typing
|
||||
import struct
|
||||
from io import BytesIO
|
||||
|
||||
KeyframeInterpolation: dict[str, int] = {
|
||||
"Hold": 1,
|
||||
"Linear": 2,
|
||||
"Tangent": 3,
|
||||
"CubicBezier": 4
|
||||
}
|
||||
|
||||
class KeyFrame():
|
||||
time: resonite_types.float = 0
|
||||
interpolation: resonite_types.int = 0
|
||||
value: resonite_types.ResoType
|
||||
left_tan: resonite_types.ResoType
|
||||
right_tan: resonite_types.ResoType
|
||||
|
||||
|
||||
def __getattr__(self, name: str):
|
||||
if name == "interpolation":
|
||||
interp: int = 0
|
||||
if (self.__dict__["left_tan"] != None and self.__dict__["right_tan"] != None):
|
||||
interp = 3
|
||||
|
||||
|
||||
return resonite_types.int(interp)
|
||||
return self.__dict__[name]
|
||||
def __setattr__(self, name, value):
|
||||
self.__dict__[name] = value
|
||||
|
||||
|
||||
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def RequiresTangents(self) -> bool:
|
||||
if KeyframeInterpolation[self.interpolation.x] == "Tangent" or KeyframeInterpolation[self.interpolation.x] == "CubicBezier":
|
||||
return True
|
||||
return False
|
||||
|
||||
class ResoTrack(resonite_types.ResoType):
|
||||
_node: resonite_types.string
|
||||
_property: resonite_types.string
|
||||
Owner: AnimX
|
||||
FrameType: type[resonite_types.ResoType]
|
||||
keyframes: list[KeyFrame] = []
|
||||
|
||||
def __init__(self,FrameType):
|
||||
self.FrameType = FrameType
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
self._node.write(data)
|
||||
self._property.write(data)
|
||||
common.write7bitEncoded_ulong(data, len(self.keyframes))
|
||||
|
||||
def read(self, data:BytesIO):
|
||||
self._node.read(data)
|
||||
self._property.read(data)
|
||||
track_amount: int = int(common.read7bitEncoded_ulong(data))
|
||||
for i in range(0, track_amount):
|
||||
self.keyframes.append(KeyFrame())
|
||||
|
||||
def removeKeyframe(self, time: float | int) -> bool:
|
||||
"""Takes a time and removes one with the same time"""
|
||||
if (time < 0):
|
||||
raise IndexError("Keyframe time cannot be lower than 0. Value: " + str(time))
|
||||
if(type(time) == float):
|
||||
num: int = -1
|
||||
for num2 in range(0,len(self.keyframes)):
|
||||
if (self.keyframes[num2].time.x == float(time)):
|
||||
num = num2
|
||||
|
||||
if num == -1:
|
||||
return False
|
||||
|
||||
self.keyframes.remove(self.keyframes[num])
|
||||
return True
|
||||
else:
|
||||
if (int(time) >= len(self.keyframes)):
|
||||
raise IndexError("Keyframe time cannot be bigger than the amount of keyframes. Value: " + str(time))
|
||||
self.keyframes.remove(self.keyframes[int(time)])
|
||||
|
||||
|
||||
|
||||
|
||||
def replaceKeyframe(self, keyframe: KeyFrame) -> bool:
|
||||
"""Takes a keyframe and replaces one with the same time"""
|
||||
if (keyframe.time.x < 0):
|
||||
raise IndexError("Keyframe time cannot be lower than 0. Value: " + str(keyframe.time.x))
|
||||
|
||||
|
||||
num: int = 0
|
||||
|
||||
if (keyframe.time.x == self.keyframes[self.GetKeyframeIndex(keyframe.time.x)].time.x):
|
||||
num = len(self.keyframes)
|
||||
else:
|
||||
return False
|
||||
|
||||
self.keyframes[num] = keyframe
|
||||
return True
|
||||
|
||||
def addKeyframe(self, keyframe: KeyFrame) -> int:
|
||||
if (keyframe.time.x < 0):
|
||||
raise IndexError("Keyframe time cannot be lower than 0. Value: " + str(keyframe.time.x))
|
||||
num: int
|
||||
if (len(self.keyframes) == 0):
|
||||
num = 0
|
||||
elif (keyframe.time.x >= self.keyframes[-1].time.x):
|
||||
num = len(self.keyframes)
|
||||
else:
|
||||
num = self.GetKeyframeIndex(keyframe.time.x) + 1
|
||||
|
||||
self.keyframes.insert(num, keyframe)
|
||||
|
||||
return num
|
||||
|
||||
def GetKeyframeIndex(self, time:float | int)-> int:
|
||||
if(type(time) == float):
|
||||
if (len(self.keyframes) > 0):
|
||||
num: int = 0
|
||||
if (self.keyframes[-1].time < float(time)):
|
||||
num = len(self.keyframes)
|
||||
|
||||
while (num < len(self.keyframes) and self.keyframes[num].time < time):
|
||||
num += 1
|
||||
|
||||
return num - 1
|
||||
|
||||
return -1
|
||||
else:
|
||||
return int(time)
|
||||
|
||||
|
||||
class RawTrack(ResoTrack):
|
||||
interval: resonite_types.float = 0
|
||||
|
||||
def __getattr__(self, name: str):
|
||||
if name == "interval":
|
||||
return self.Owner.interval.x
|
||||
return self.__dict__[name]
|
||||
|
||||
def __init__(self, FrameType):
|
||||
super().__init__(FrameType)
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
self.interval.write(data)
|
||||
for key in self.keyframes:
|
||||
key.value.write(data)
|
||||
|
||||
|
||||
def read(self, data:BytesIO):
|
||||
super().read(data)
|
||||
self.interval.read(data)
|
||||
for key in self.keyframes:
|
||||
key.value.read(data)
|
||||
|
||||
def addKeyframe(self, keyframe: KeyFrame) -> int:
|
||||
num: int = super().addKeyframe(keyframe)
|
||||
for i in range(0,len(self.keyframes)):
|
||||
self.keyframes[i].time = i
|
||||
return num
|
||||
def removeKeyframe(self, time: float | int) -> bool:
|
||||
success: bool = super().removeKeyframe(int(time))
|
||||
for i in range(0,len(self.keyframes)):
|
||||
self.keyframes[i].time = i
|
||||
return success
|
||||
|
||||
|
||||
|
||||
|
||||
class DiscreteTrack(ResoTrack):
|
||||
|
||||
def __init__(self, FrameType):
|
||||
super().__init__(FrameType)
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
|
||||
|
||||
def read(self, data:BytesIO):
|
||||
super().read(data)
|
||||
|
||||
def addKeyframe(self, keyframe: KeyFrame) -> int:
|
||||
num: int = super().addKeyframe(keyframe)
|
||||
return num
|
||||
def removeKeyframe(self, time: float | int) -> bool:
|
||||
success: bool = super().removeKeyframe(time)
|
||||
return success
|
||||
|
||||
|
||||
|
||||
|
||||
class CurveTrack(ResoTrack):
|
||||
interpolations: bool = False
|
||||
tangents: bool = False
|
||||
sharedinterpolation: resonite_types.int = -1
|
||||
|
||||
def __getattr__(self, name: str):
|
||||
if name == "interpolations":
|
||||
for key in self.keyframes:
|
||||
if key.interpolation.x != self.sharedinterpolation.x:
|
||||
return True
|
||||
elif name == "tangents":
|
||||
for key in self.keyframes:
|
||||
if key.interpolation.x == 3 or key.interpolation.x == 4:
|
||||
return True
|
||||
return self.__dict__[name]
|
||||
|
||||
def __init__(self, FrameType):
|
||||
super().__init__(FrameType)
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
resonite_types.byte((1 if self.interpolations else 0) | (2 if self.tangents else 0)).write(data)
|
||||
|
||||
|
||||
if(self.interpolations):
|
||||
for key in self.keyframes:
|
||||
key.interpolation.write(data)
|
||||
else:
|
||||
self.sharedinterpolation.write(data)
|
||||
|
||||
for key in self.keyframes:
|
||||
key.value.write(data)
|
||||
key.time.write(data)
|
||||
|
||||
if(self.tangents):
|
||||
for key in self.keyframes:
|
||||
key.left_tan.write(data)
|
||||
key.right_tan.write(data)
|
||||
|
||||
def read(self, data:BytesIO):
|
||||
super().read(data)
|
||||
flags: int = struct.unpack("<B",data.read(1))
|
||||
self.interpolations = flags & 1
|
||||
self.tangents = flags & 2
|
||||
|
||||
if(self.interpolations):
|
||||
for key in self.keyframes:
|
||||
key.interpolation.read(data)
|
||||
else:
|
||||
self.sharedinterpolation.read(data)
|
||||
|
||||
for key in self.keyframes:
|
||||
key.value.read(data)
|
||||
key.time.read(data)
|
||||
|
||||
if(self.tangents):
|
||||
for key in self.keyframes:
|
||||
key.left_tan.read(data)
|
||||
key.right_tan.read(data)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class BezierTrack(ResoTrack):
|
||||
"""PLACE HOLDER CLASS, DO NOT USE"""
|
||||
|
||||
|
||||
def __init__(self, FrameType):
|
||||
super().__init__(FrameType)
|
||||
"""PLACE HOLDER METHOD, DO NOT USE"""
|
||||
#raise Exception("BezierTrack track type is unsupported in resonite's code")
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
"""PLACE HOLDER METHOD, DO NOT USE"""
|
||||
raise Exception("BezierTrack track type is unsupported in resonite's code")
|
||||
def read(self, data:BytesIO):
|
||||
"""PLACE HOLDER METHOD, DO NOT USE"""
|
||||
raise Exception("BezierTrack track type is unsupported in resonite's code")
|
||||
|
||||
def removeKeyframe(self, keyframe: KeyFrame) -> bool:
|
||||
"""PLACE HOLDER METHOD, DO NOT USE"""
|
||||
raise Exception("BezierTrack track type is unsupported in resonite's code")
|
||||
|
||||
def replaceKeyframe(self, keyframe: KeyFrame) -> bool:
|
||||
"""PLACE HOLDER METHOD, DO NOT USE"""
|
||||
raise Exception("BezierTrack track type is unsupported in resonite's code")
|
||||
def addKeyframe(self, keyframe: KeyFrame) -> int:
|
||||
"""PLACE HOLDER METHOD, DO NOT USE"""
|
||||
raise Exception("BezierTrack track type is unsupported in resonite's code")
|
||||
|
||||
def GetKeyframeIndex(self, time:float)-> int:
|
||||
"""PLACE HOLDER METHOD, DO NOT USE"""
|
||||
raise Exception("BezierTrack track type is unsupported in resonite's code")
|
||||
#This is weird, but thank you python - @989onan
|
||||
TrackTypes: list[type[ResoTrack]] = [
|
||||
RawTrack,
|
||||
DiscreteTrack,
|
||||
CurveTrack,
|
||||
BezierTrack
|
||||
]
|
||||
|
||||
#TODO: add all types here
|
||||
#wooooo - @989onan
|
||||
elementTypes: list[type[resonite_types.ResoType]] = [
|
||||
resonite_types.bool,
|
||||
resonite_types.bool2,
|
||||
resonite_types.bool3,
|
||||
resonite_types.bool4,
|
||||
resonite_types.byte,
|
||||
resonite_types.ushort,
|
||||
resonite_types.uint,
|
||||
resonite_types.ulong,
|
||||
resonite_types.sbyte,
|
||||
resonite_types.short,
|
||||
resonite_types.int,
|
||||
resonite_types.long,
|
||||
resonite_types.int2,
|
||||
resonite_types.int3,
|
||||
resonite_types.int4,
|
||||
resonite_types.uint2,
|
||||
resonite_types.uint3,
|
||||
resonite_types.uint4,
|
||||
resonite_types.long2,
|
||||
resonite_types.long3,
|
||||
resonite_types.long4,
|
||||
resonite_types.float,
|
||||
resonite_types.float2,
|
||||
resonite_types.float3,
|
||||
resonite_types.float4,
|
||||
resonite_types.floatQ,
|
||||
resonite_types.float2x2,
|
||||
resonite_types.float3x3,
|
||||
resonite_types.float4x4,
|
||||
resonite_types.double,
|
||||
resonite_types.double2,
|
||||
resonite_types.double3,
|
||||
resonite_types.double4,
|
||||
resonite_types.doubleQ,
|
||||
resonite_types.double2x2,
|
||||
resonite_types.double3x3,
|
||||
resonite_types.double4x4,
|
||||
resonite_types.color,
|
||||
resonite_types.color32,
|
||||
resonite_types.string
|
||||
]
|
||||
|
||||
|
||||
most_recent_AnimX_vers: int = 1
|
||||
|
||||
class AnimX():
|
||||
|
||||
|
||||
"""
|
||||
To use Raw Track properly, please set interval (seconds between frames) after reading/creating.\n
|
||||
Represents data to be written to or read from an AnimX file.
|
||||
"""
|
||||
|
||||
file_version: resonite_types.int = resonite_types.int()
|
||||
track_amount: resonite_types.int = resonite_types.int()
|
||||
global_duration: resonite_types.float = resonite_types.float()
|
||||
name: resonite_types.string = resonite_types.string()
|
||||
|
||||
tracks: list[ResoTrack] = []
|
||||
|
||||
interval: resonite_types.float = resonite_types.float(1/25) #default value
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def read(self, file: str) -> bool:
|
||||
"""
|
||||
Takes an absolute file path and reads a binary animx file with it, and populates this class object with the data.
|
||||
"""
|
||||
with open(file, 'rb') as filecontents:
|
||||
data: BytesIO = BytesIO(filecontents.read())
|
||||
magic_word = common.ReadCSharp_str(data)
|
||||
if magic_word != 'AnimX':
|
||||
print("AnimX != "+magic_word)
|
||||
return False
|
||||
self.file_version.read(data)
|
||||
if self.file_version.x > 1:
|
||||
raise Exception("AnimX version is higher than the supported one")
|
||||
|
||||
self.track_amount.x = common.read7bitEncoded_ulong(data)
|
||||
self.global_duration.read(data)
|
||||
print(self.track_amount.x)
|
||||
|
||||
self.name.read(data)
|
||||
|
||||
|
||||
match (struct.unpack('<B', data.read(1))[0]):
|
||||
case 0:
|
||||
pass
|
||||
case 1:
|
||||
from lz4.frame import decompress #why do you have to be a wheel? - @989onan
|
||||
data = BytesIO(decompress(data.read()))
|
||||
case 2:
|
||||
import lzma#HALLLOOOYAH HALLOYAH!! - @989onan
|
||||
filters = [{"id": "", "preset": lzma.PRESET_DEFAULT}]
|
||||
data = BytesIO(lzma.decompress(data.read(), filters=filters))
|
||||
case _:
|
||||
raise Exception("Invalid encoding")
|
||||
|
||||
for i in range(0,self.track_amount.x):
|
||||
trackType2: int = 0
|
||||
num4: int = 0
|
||||
if (self.file_version == 0):
|
||||
b: ctypes.c_ubyte = ctypes.c_ubyte(struct.unpack('<B', data.read(1))[0])
|
||||
num3: int = int(b & 1)
|
||||
trackType: int = 0
|
||||
if (num3 != 0):
|
||||
if (num3 != 1):
|
||||
raise Exception("[InvalidDataException]: Invalid track type data: " + str(b))
|
||||
trackType = 2
|
||||
else:
|
||||
trackType = 0
|
||||
trackType2 = trackType
|
||||
num4 = b >> 1
|
||||
else:
|
||||
trackType2 = int(struct.unpack('<B', data.read(1))[0])
|
||||
num4 = int(struct.unpack('<B', data.read(1))[0])
|
||||
animationTrack: ResoTrack = AnimX.GetTrackType(trackType2, elementTypes[num4], data)
|
||||
animationTrack.Owner = self
|
||||
self.tracks.append(animationTrack)
|
||||
|
||||
return True
|
||||
|
||||
def write(self, file: str) -> bool:
|
||||
"""
|
||||
Takes an absolute file path and writes a binary animx file into it's contents, replacing them using this class's data.
|
||||
"""
|
||||
with open(file, 'rb') as filecontents:
|
||||
data: BytesIO = BytesIO(filecontents)
|
||||
common.WriteCSharp_str(data, 'AnimX')
|
||||
self.file_version.x = most_recent_AnimX_vers #we wanna write an up to date file version type.
|
||||
self.file_version.write(data)
|
||||
|
||||
self.track_amount.x = len(self.tracks)
|
||||
common.write7bitEncoded_ulong(self.track_amount.x)
|
||||
self.global_duration.write(data)
|
||||
|
||||
|
||||
self.name.write(data)
|
||||
|
||||
data.write(struct.pack('<B', 0)) #default encoding, so we don't have to use lzma.
|
||||
|
||||
|
||||
for i in range(0,self.track_amount.x):
|
||||
|
||||
data.write(struct.pack('<B', TrackTypes.index(type(self.tracks[i])))[0])
|
||||
data.write(struct.pack('<B', elementTypes.index(self.tracks[i].FrameType)))
|
||||
self.tracks[i].write(data)
|
||||
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def GetTrackType(cls, trackType2: int, value_type: int, data: BytesIO) -> ResoTrack:
|
||||
TrackType: type[ResoTrack] = TrackTypes[trackType2]
|
||||
Track: ResoTrack = TrackType[elementTypes[value_type]](elementTypes[value_type])
|
||||
Track.read(data)
|
||||
return Track
|
||||
|
||||
@@ -0,0 +1,655 @@
|
||||
import ctypes
|
||||
import typing
|
||||
from io import BytesIO
|
||||
import struct
|
||||
from . import common
|
||||
|
||||
class ResoType():
|
||||
|
||||
|
||||
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
pass
|
||||
|
||||
def read(cls, data: BytesIO):
|
||||
pass
|
||||
|
||||
#These below are collection of the basic resonite typing made from C#. This is in order to store data in a sane way and decode/encode it.
|
||||
|
||||
class color(ResoType):
|
||||
r: float = 0
|
||||
g: float = 0
|
||||
b: float = 0
|
||||
a: float = 0
|
||||
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<ffff", self.r, self.g, self.b, self.a))
|
||||
|
||||
def read(self,data):
|
||||
self.r, self.g, self.b, self.a = struct.unpack("<ffff", data.read(4*4))[0]
|
||||
|
||||
|
||||
class color32(ResoType):
|
||||
r: int = 0
|
||||
g: int = 0
|
||||
b: int = 0
|
||||
a: int = 0
|
||||
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<BBBB", self.r, self.g, self.b, self.a))
|
||||
|
||||
def read(self,data):
|
||||
self.r, self.g, self.b, self.a = struct.unpack("<BBBB", data.read(4))[0]
|
||||
|
||||
class string(ResoType):
|
||||
x: str
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.x
|
||||
|
||||
def __init__(self,value=""):
|
||||
self.x = value
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
common.WriteCSharp_str(data,self.x)
|
||||
|
||||
def read(self,data):
|
||||
|
||||
self.x = common.ReadCSharp_str(data)
|
||||
|
||||
|
||||
class byte(ResoType):
|
||||
x: int = 0
|
||||
|
||||
def __int__(self):
|
||||
return self.x
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<B", self.x))
|
||||
|
||||
def read(self,data):
|
||||
self.x = struct.unpack("<B", data.read(1))[0]
|
||||
|
||||
class sbyte(ResoType):
|
||||
x: int = 0
|
||||
|
||||
def __int__(self):
|
||||
return self.x
|
||||
|
||||
def __init__(self,value=0):
|
||||
self.x = value
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<b", self.x))
|
||||
|
||||
def read(self,data):
|
||||
self.x = struct.unpack("<b", data.read(1))[0]
|
||||
|
||||
class ushort(ResoType):
|
||||
x: int = 0
|
||||
|
||||
def __int__(self):
|
||||
return self.x
|
||||
|
||||
def __init__(self,value=0):
|
||||
self.x = value
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<H", self.x))
|
||||
|
||||
def read(self,data):
|
||||
self.x = struct.unpack("<H", data.read(2))[0]
|
||||
|
||||
class short(ResoType):
|
||||
x: int = 0
|
||||
|
||||
def __int__(self):
|
||||
return self.x
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<h", self.x))
|
||||
|
||||
def read(self,data):
|
||||
self.x = struct.unpack("<h", data.read(2))[0]
|
||||
|
||||
class bool(ResoType):
|
||||
x: bool = False
|
||||
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
return self.x
|
||||
def __init__(self,value=False):
|
||||
self.x = value
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("?", self.x))
|
||||
|
||||
def read(self,data):
|
||||
self.x = struct.unpack("?", data.read(1))[0]
|
||||
|
||||
class bool2(bool):
|
||||
y: bool = False
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
byte: ctypes.c_ubyte = ctypes.c_ubyte(struct.unpack("<B",data.read(1))[0])
|
||||
self.x = (byte & 1) > 0
|
||||
self.y = (byte & 2) > 0
|
||||
|
||||
def createflags(self) -> ctypes.c_byte:
|
||||
flags: ctypes.c_ubyte = ctypes.c_ubyte(0)
|
||||
flags |= (1 if self.x else 0)
|
||||
flags |= (2 if self.y else 0)
|
||||
return flags
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<B", self.createflags()))
|
||||
|
||||
|
||||
class bool3(bool2):
|
||||
z: bool = False
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data):
|
||||
byte: ctypes.c_ubyte = ctypes.c_ubyte(struct.unpack("<B",data.read(1))[0])
|
||||
self.x = (byte & 1) > 0
|
||||
self.y = (byte & 2) > 0
|
||||
self.z = (byte & 4) > 0
|
||||
|
||||
def createflags(self) -> ctypes.c_byte:
|
||||
flags: ctypes.c_ubyte = ctypes.c_ubyte(0)
|
||||
flags |= (1 if self.x else 0)
|
||||
flags |= (2 if self.y else 0)
|
||||
flags |= (3 if self.z else 0)
|
||||
return flags
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<B", self.createflags()))
|
||||
|
||||
|
||||
class bool4(bool3):
|
||||
w: bool = False
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
byte: ctypes.c_ubyte = ctypes.c_ubyte(struct.unpack("<B",data.read(1))[0])
|
||||
self.x = (byte & 1) > 0
|
||||
self.y = (byte & 2) > 0
|
||||
self.z = (byte & 4) > 0
|
||||
self.w = (byte & 8) > 0
|
||||
|
||||
def createflags(self) -> ctypes.c_ubyte:
|
||||
flags: ctypes.c_ubyte = ctypes.c_ubyte(0)
|
||||
flags |= (1 if self.x else 0)
|
||||
flags |= (2 if self.y else 0)
|
||||
flags |= (4 if self.z else 0)
|
||||
flags |= (8 if self.w else 0)
|
||||
return flags
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<B", self.createflags()))
|
||||
|
||||
|
||||
|
||||
class int(ResoType):
|
||||
x: int = 0
|
||||
|
||||
def __int__(self):
|
||||
return self.x
|
||||
|
||||
def __init__(self,value=0):
|
||||
self.x = value
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
self.x = struct.unpack("<i", data.read(4))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<i", self.x))
|
||||
|
||||
class int2(int):
|
||||
y: int = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().write(data)
|
||||
self.y = struct.unpack("<i", data.read(4))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<i", self.y))
|
||||
|
||||
class int3(int2):
|
||||
z: int = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().write(data)
|
||||
self.z = struct.unpack("<i", data.read(4))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<i", self.z))
|
||||
|
||||
class int4(int3):
|
||||
w: int = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().write(data)
|
||||
self.w = struct.unpack("<i", data.read(4))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<i", self.w))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class uint(ResoType):
|
||||
x: int = 0
|
||||
|
||||
def __int__(self):
|
||||
return self.x
|
||||
|
||||
def __init__(self,value=0):
|
||||
self.x = value
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
self.x = struct.unpack("<I", data.read(4))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<I", self.x))
|
||||
|
||||
class uint2(uint):
|
||||
y: int = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().write(data)
|
||||
self.y = struct.unpack("<I", data.read(4))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<I", self.y))
|
||||
|
||||
class uint3(uint2):
|
||||
z: int = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().write(data)
|
||||
self.z = struct.unpack("<I", data.read(4))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<I", self.z))
|
||||
|
||||
class uint4(uint3):
|
||||
w: int = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().write(data)
|
||||
self.w = struct.unpack("<I", data.read(4))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<I", self.w))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ulong(ResoType):
|
||||
x: int = 0
|
||||
|
||||
def __int__(self):
|
||||
return self.x
|
||||
|
||||
def __init__(self,value=0):
|
||||
self.x = value
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
self.x = struct.unpack("<Q", data.read(8))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<Q", self.x))
|
||||
|
||||
|
||||
class long(ResoType):
|
||||
x: int = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
self.x = struct.unpack("<q", data.read(8))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<q", self.x))
|
||||
|
||||
class long2(long):
|
||||
y: int = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().read(data)
|
||||
self.y = struct.unpack("<q", data.read(8))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<q", self.y))
|
||||
|
||||
class long3(long2):
|
||||
z: int = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().read(data)
|
||||
self.z = struct.unpack("<q", data.read(8))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<q", self.z))
|
||||
|
||||
class long4(long3):
|
||||
w: int = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().read(data)
|
||||
self.w = struct.unpack("<q", data.read(8))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<q", self.w))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class double(ResoType):
|
||||
x: float = 0
|
||||
|
||||
def __float__(self):
|
||||
return self.x
|
||||
|
||||
def __init__(self,value=0):
|
||||
self.x = value
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
self.x = struct.unpack("<d", data.read(8))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<d", self.x))
|
||||
|
||||
class double2(double):
|
||||
|
||||
y: float = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().read(data)
|
||||
self.y = struct.unpack("<d", data.read(8))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<d", self.y))
|
||||
|
||||
class double3(double2):
|
||||
z: float = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().read(data)
|
||||
self.z = struct.unpack("<d", data.read(8))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<d", self.z))
|
||||
|
||||
class double4(double3):
|
||||
w: float = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().read(data)
|
||||
self.w = struct.unpack("<d", data.read(8))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<d", self.w))
|
||||
|
||||
class double2x2(ResoType):
|
||||
m00: float = 0
|
||||
m01: float = 0
|
||||
m10: float = 0
|
||||
m11: float = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
self.m00,self.m01,self.m10,self.m11 = struct.unpack("<dddd", data.read(8*(2*2)))
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<dddd", self.m00,self.m01, self.m10,self.m11))
|
||||
|
||||
|
||||
class double3x3(double2x2):
|
||||
m02: float = 0
|
||||
m12: float = 0
|
||||
m22: float = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
self.m00,self.m01,self.m02,self.m10,self.m11,self.m12,self.m20,self.m21,self.m22 = struct.unpack("<ddddddddd", data.read(8*(3*3)))
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<ddddddddd", self.m00,self.m01,self.m02,self.m10,self.m11,self.m12,self.m20,self.m21,self.m22))
|
||||
|
||||
|
||||
class double4x4(double3x3):
|
||||
m03: float = 0
|
||||
m13: float = 0
|
||||
m23: float = 0
|
||||
m33: float = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
self.m00,self.m01,self.m02,self.m03,self.m10,self.m11,self.m12,self.m13,self.m20,self.m21,self.m22,self.m23,self.m30,self.m31,self.m32,self.m33 = struct.unpack("<dddddddddddddddd", data.read(8*(4*4)))
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<dddddddddddddddd", self.m00,self.m01,self.m02,self.m03,self.m10,self.m11,self.m12,self.m13,self.m20,self.m21,self.m22,self.m23,self.m30,self.m31,self.m32,self.m33))
|
||||
|
||||
class doubleQ(double4):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
|
||||
@classmethod
|
||||
def read(cls, data: BytesIO):
|
||||
super().read(data)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class float(ResoType):
|
||||
x: float = 0
|
||||
|
||||
def __float__(self):
|
||||
return self.x
|
||||
|
||||
def __init__(self, value=0):
|
||||
self.x = value
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
self.x = struct.unpack("<f", data.read(4))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<f", self.x))
|
||||
|
||||
class float2(float):
|
||||
|
||||
y: float = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().read(data)
|
||||
self.y = struct.unpack("<f", data.read(4))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<f", self.y))
|
||||
|
||||
class float3(float2):
|
||||
z: float = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().read(data)
|
||||
self.z = struct.unpack("<f", data.read(4))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<f", self.z))
|
||||
|
||||
class float4(float3):
|
||||
w: float = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
super().read(data)
|
||||
self.w = struct.unpack("<f", data.read(4))[0]
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
data.write(struct.pack("<f", self.w))
|
||||
|
||||
class float2x2(ResoType):
|
||||
m00: float = 0
|
||||
m01: float = 0
|
||||
m10: float = 0
|
||||
m11: float = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
self.m00,self.m01,self.m10,self.m11 = struct.unpack("<ffff", data.read(4*(2*2)))
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<ffff", self.m00,self.m01, self.m10,self.m11))
|
||||
|
||||
|
||||
class float3x3(float2x2):
|
||||
m02: float = 0
|
||||
m12: float = 0
|
||||
m22: float = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
self.m00,self.m01,self.m02,self.m10,self.m11,self.m12,self.m20,self.m21,self.m22 = struct.unpack("<fffffffff", data.read(4*(3*3)))
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<fffffffff", self.m00,self.m01,self.m02,self.m10,self.m11,self.m12,self.m20,self.m21,self.m22))
|
||||
|
||||
|
||||
class float4x4(float3x3):
|
||||
m03: float = 0
|
||||
m13: float = 0
|
||||
m23: float = 0
|
||||
m33: float = 0
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def read(self,data: BytesIO):
|
||||
self.m00,self.m01,self.m02,self.m03,self.m10,self.m11,self.m12,self.m13,self.m20,self.m21,self.m22,self.m23,self.m30,self.m31,self.m32,self.m33 = struct.unpack("<ffffffffffffffff", data.read(4*(4*4)))
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
data.write(struct.pack("<ffffffffffffffff", self.m00,self.m01,self.m02,self.m03,self.m10,self.m11,self.m12,self.m13,self.m20,self.m21,self.m22,self.m23,self.m30,self.m31,self.m32,self.m33))
|
||||
|
||||
class floatQ(float4):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def write(self, data: BytesIO):
|
||||
super().write(data)
|
||||
|
||||
@classmethod
|
||||
def read(cls, data: BytesIO):
|
||||
super().read(data)
|
||||
+102
-12
@@ -1,11 +1,17 @@
|
||||
import bpy
|
||||
import bpy_extras
|
||||
|
||||
from typing import List, Optional
|
||||
from .common import get_armature
|
||||
from .common import get_armature, get_selected_armature, simplify_bonename, is_valid_armature
|
||||
from bpy.types import Object, ShapeKey, Mesh, Context, Operator
|
||||
from functools import lru_cache
|
||||
from ..core.register import register_wrap
|
||||
from ..functions.translations import t
|
||||
from ..core.dictionaries import bone_names
|
||||
|
||||
import re
|
||||
from .resonite_loader import resonite_animx, resonite_types
|
||||
import os
|
||||
|
||||
|
||||
|
||||
@register_wrap
|
||||
@@ -34,16 +40,6 @@ class AvatarToolKit_OT_ExportResonite(Operator):
|
||||
export_nla_strips_merged_animation_name = 'Animation',
|
||||
export_nla_strips = True)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
import bpy
|
||||
from ..core.register import register_wrap
|
||||
from typing import List, Optional
|
||||
import re
|
||||
from bpy.types import Operator, Context, Object
|
||||
from ..core.dictionaries import bone_names
|
||||
from ..core.common import get_selected_armature, simplify_bonename, is_valid_armature
|
||||
from ..functions.translations import t
|
||||
|
||||
@register_wrap
|
||||
class AvatarToolKit_OT_ConvertToResonite(Operator):
|
||||
@@ -151,3 +147,97 @@ class AvatarToolKit_OT_ConvertToResonite(Operator):
|
||||
self.report({'INFO'}, t("Tools.bones_translated_success"))
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@register_wrap
|
||||
class AvatarToolKit_OT_AnimX_Importer(Operator,bpy_extras.io_utils.ImportHelper):
|
||||
bl_idname = 'avatar_toolkit.animx_importer'
|
||||
bl_label = t('Tools.animx_importer.label')
|
||||
bl_description = t('Tools.animx_importer.desc')
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
#fps = bpy.props.FloatProperty(default=25) #25 fps
|
||||
|
||||
filter_glob: bpy.props.StringProperty(
|
||||
default="*.animx",
|
||||
options={'HIDDEN'}
|
||||
)
|
||||
files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement, options={'HIDDEN', 'SKIP_SAVE'})
|
||||
filepath: bpy.props.StringProperty()
|
||||
|
||||
directory:bpy.props.StringProperty(subtype='DIR_PATH')
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context: Context) -> bool:
|
||||
return True
|
||||
|
||||
def execute(self, context: Context) -> set:
|
||||
|
||||
Froox_animations: list[resonite_animx.AnimX] = []
|
||||
|
||||
#decoding using self contained library:
|
||||
files = [file.name for file in self.files]
|
||||
files.append(self.filepath)
|
||||
for file in files:
|
||||
froox_animation: resonite_animx.AnimX = resonite_animx.AnimX()
|
||||
froox_animation.interval.x = 1/25
|
||||
froox_animation.read(file = os.path.join(self.directory,file))
|
||||
Froox_animations.append(froox_animation)
|
||||
|
||||
#Load data into Blender Animations.
|
||||
for froox_animation in Froox_animations:
|
||||
action: bpy.types.Action = bpy.data.actions.new(froox_animation.name.x)
|
||||
action.use_fake_user = True
|
||||
for track in froox_animation.tracks:
|
||||
print("hit here1")
|
||||
print(track.FrameType)
|
||||
if(track.FrameType != type(resonite_types.float) and track.FrameType != type(resonite_types.double)):
|
||||
continue
|
||||
|
||||
data_path: str = track._node.x+"."+track._property.x
|
||||
fcurve_reso = action.fcurves.new(data_path,None,track._node.x)
|
||||
|
||||
print("hit here2")
|
||||
match(type(track)):
|
||||
case (type(resonite_animx.RawTrack)):
|
||||
rawtrack: resonite_animx.RawTrack = track
|
||||
|
||||
|
||||
|
||||
for frame in rawtrack.keyframes:
|
||||
key: bpy.types.Keyframe = fcurve_reso.keyframe_points.insert(frame.time, float(frame.value))
|
||||
|
||||
|
||||
case (type(resonite_animx.DiscreteTrack)):
|
||||
discretetrack: resonite_animx.RawTrack = track
|
||||
for frame in rawtrack.keyframes:
|
||||
key: bpy.types.Keyframe = fcurve_reso.keyframe_points.insert(frame.time, float(frame.value))
|
||||
|
||||
|
||||
case(type(resonite_animx.CurveTrack)):
|
||||
curvetrack: resonite_animx.RawTrack = track
|
||||
for frame in curvetrack.keyframes:
|
||||
key: bpy.types.Keyframe = fcurve_reso.keyframe_points.insert(frame.time, float(frame.value))
|
||||
key.handle_left = float(frame.left_tan)
|
||||
key.handle_left = float(frame.right_tan)
|
||||
|
||||
|
||||
case(type(resonite_animx.BezierTrack)):
|
||||
beziertrack: resonite_animx.RawTrack = track
|
||||
# Bezier is not supported rn, ignore.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
import bpy
|
||||
from ..core.register import register_wrap
|
||||
from typing import List, Optional
|
||||
import re
|
||||
from bpy.types import Operator, Context, Object
|
||||
from ..core.dictionaries import bone_names
|
||||
from ..core.common import get_selected_armature, simplify_bonename, is_valid_armature
|
||||
from ..functions.translations import t
|
||||
|
||||
@register_wrap
|
||||
class AvatarToolKit_OT_ConvertToResonite(Operator):
|
||||
bl_idname = 'avatar_toolkit.convert_to_resonite'
|
||||
bl_label = t('Tools.convert_to_resonite.label')
|
||||
bl_description = t('Tools.convert_to_resonite.desc')
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context: Context) -> bool:
|
||||
armature = get_selected_armature(context)
|
||||
return armature is not None and is_valid_armature(armature)
|
||||
|
||||
def execute(self, context: Context) -> set:
|
||||
armature = get_selected_armature(context)
|
||||
if not armature:
|
||||
self.report({'WARNING'}, t("Tools.no_armature_selected"))
|
||||
return {'CANCELLED'}
|
||||
|
||||
translate_bone_fails = 0
|
||||
untranslated_bones = set()
|
||||
|
||||
reverse_bone_lookup = dict()
|
||||
for (preferred_name, name_list) in bone_names.items():
|
||||
for name in name_list:
|
||||
reverse_bone_lookup[name] = preferred_name
|
||||
|
||||
resonite_translations = {
|
||||
'hips': "Hips",
|
||||
'spine': "Spine",
|
||||
'chest': "Chest",
|
||||
'neck': "Neck",
|
||||
'head': "Head",
|
||||
'left_eye': "Eye.L",
|
||||
'right_eye': "Eye.R",
|
||||
'right_leg': "UpperLeg.R",
|
||||
'right_knee': "Calf.R",
|
||||
'right_ankle': "Foot.R",
|
||||
'right_toe': 'Toes.R',
|
||||
'right_shoulder': "Shoulder.R",
|
||||
'right_arm': "UpperArm.R",
|
||||
'right_elbow': "ForeArm.R",
|
||||
'right_wrist': "Hand.R",
|
||||
'left_leg': "UpperLeg.L",
|
||||
'left_knee': "Calf.L",
|
||||
'left_ankle': "Foot.L",
|
||||
'left_toe': "Toes.L",
|
||||
'left_shoulder': "Shoulder.L",
|
||||
'left_arm': "UpperArm.L",
|
||||
'left_elbow': "ForeArm.L",
|
||||
'left_wrist': "Hand.R",
|
||||
|
||||
'pinkie_1_l': "pinkie1.L",
|
||||
'pinkie_2_l': "pinkie2.L",
|
||||
'pinkie_3_l': "pinkie3.L",
|
||||
'ring_1_l': "ring1.L",
|
||||
'ring_2_l': "ring2.L",
|
||||
'ring_3_l': "ring3.L",
|
||||
'middle_1_l': "middle1.L",
|
||||
'middle_2_l': "middle2.L",
|
||||
'middle_3_l': "middle3.L",
|
||||
'index_1_l': "index1.L",
|
||||
'index_2_l': "index2.L",
|
||||
'index_3_l': "index3.L",
|
||||
'thumb_1_l': "thumb1.L",
|
||||
'thumb_2_l': "thumb2.L",
|
||||
'thumb_3_l': "thumb3.L",
|
||||
|
||||
'pinkie_1_r': "pinkie1.R",
|
||||
'pinkie_2_r': "pinkie2.R",
|
||||
'pinkie_3_r': "pinkie3.R",
|
||||
'ring_1_r': "ring1.R",
|
||||
'ring_2_r': "ring2.R",
|
||||
'ring_3_r': "ring3.R",
|
||||
'middle_1_r': "middle1.R",
|
||||
'middle_2_r': "middle2.R",
|
||||
'middle_3_r': "middle3.R",
|
||||
'index_1_r': "index1.R",
|
||||
'index_2_r': "index2.R",
|
||||
'index_3_r': "index3.R",
|
||||
'thumb_1_r': "thumb1.R",
|
||||
'thumb_2_r': "thumb2.R",
|
||||
'thumb_3_r': "thumb3.R"
|
||||
}
|
||||
|
||||
context.view_layer.objects.active = armature
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
bone.name = re.compile(re.escape("<noik>"), re.IGNORECASE).sub("",bone.name) #remove "NOIK" from bones before translating again, in case an update was done that fixes a translation.
|
||||
for bone in armature.data.bones:
|
||||
if simplify_bonename(bone.name) in reverse_bone_lookup and reverse_bone_lookup[simplify_bonename(bone.name)] in resonite_translations:
|
||||
bone.name = resonite_translations[reverse_bone_lookup[simplify_bonename(bone.name)]]
|
||||
else:
|
||||
untranslated_bones.add(bone.name)
|
||||
|
||||
bone.name = bone.name+"<noik>"
|
||||
translate_bone_fails += 1
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
if translate_bone_fails > 0:
|
||||
self.report({'INFO'}, t("Tools.bones_translated_with_fails").format(translate_bone_fails=translate_bone_fails))
|
||||
else:
|
||||
self.report({'INFO'}, t("Tools.bones_translated_success"))
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
@@ -287,6 +287,9 @@ class AvatarToolkit_OT_AlignUVEdgesToTarget(Operator):
|
||||
uv_lay.uv[corner].vector = lerped_point #put the vertcies at the point we calculated.
|
||||
except:
|
||||
print("This is probably fine? - @989onan") #TODO: What happened here? The magic of making code so complex you forget if this is even an issue. - @989onan
|
||||
#Note: The above print statement may require reading what this entire operator does before understanding if the above print statment means anything
|
||||
#so if you value your time, just do a bunch of tests until the above print stament is ran or something
|
||||
#if in doubt and you cannot get it to run, just spend some time trying to understand the operator - @989onan
|
||||
|
||||
print("Finished mesh \""+source+"\" for UV's")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user