first commit
This commit is contained in:
6
PyCmo/PyCmo.py
Normal file
6
PyCmo/PyCmo.py
Normal file
@ -0,0 +1,6 @@
|
||||
import VirtoolsReader
|
||||
import VirtoolsStruct
|
||||
|
||||
with open("D:\\libcmo21\\PyCmo\\Gameplay.nmo", 'rb') as fs:
|
||||
composition = VirtoolsReader.ReadCKComposition(fs)
|
||||
print(str(composition.Header))
|
50
PyCmo/PyCmo.pyproj
Normal file
50
PyCmo/PyCmo.pyproj
Normal file
@ -0,0 +1,50 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>adc519e8-5f1b-427d-8e5c-1fabcb6147fb</ProjectGuid>
|
||||
<ProjectHome>.</ProjectHome>
|
||||
<StartupFile>PyCmo.py</StartupFile>
|
||||
<SearchPath>
|
||||
</SearchPath>
|
||||
<WorkingDirectory>.</WorkingDirectory>
|
||||
<OutputPath>.</OutputPath>
|
||||
<Name>PyCmo</Name>
|
||||
<RootNamespace>PyCmo</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="PyCmo.py" />
|
||||
<Compile Include="PyCmoMisc.py">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="VirtoolsConstants.py">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="VirtoolsReader.py">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="VirtoolsStruct.py">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="VirtoolsUtils.py">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets" />
|
||||
<!-- Uncomment the CoreCompile target to enable the Build command in
|
||||
Visual Studio and specify your pre- and post-build commands in
|
||||
the BeforeBuild and AfterBuild targets below. -->
|
||||
<!--<Target Name="CoreCompile" />-->
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
</Project>
|
32
PyCmo/PyCmoMisc.py
Normal file
32
PyCmo/PyCmoMisc.py
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
def OutputSizeHumanReadable(storage_size: int):
|
||||
probe = storage_size
|
||||
|
||||
# check Bytes
|
||||
if (probe >> 10) == 0:
|
||||
return f"{storage_size:d}Bytes"
|
||||
probe >>= 10
|
||||
|
||||
# check KiB
|
||||
if (probe >> 10) == 0:
|
||||
return f"{(storage_size / (1 << 10)):.2f}KiB"
|
||||
probe >>= 10
|
||||
|
||||
# check MiB
|
||||
if (probe >> 10) == 0:
|
||||
return f"{(storage_size / (1 << 20)):.2f}MiB"
|
||||
probe >>= 10
|
||||
|
||||
# otherwise GiB
|
||||
return f"{(storage_size / (1 << 30)):.2f}GiB"
|
||||
|
||||
def BcdCodeToDecCode(bcd_num: int):
|
||||
result = 0
|
||||
pow = 1
|
||||
|
||||
while bcd_num != 0:
|
||||
result += (bcd_num & 0xf) * pow
|
||||
bcd_num >>= 4
|
||||
pow *= 10
|
||||
|
||||
return result
|
320
PyCmo/VirtoolsConstants.py
Normal file
320
PyCmo/VirtoolsConstants.py
Normal file
@ -0,0 +1,320 @@
|
||||
import enum
|
||||
|
||||
class PyEnum(object):
|
||||
@staticmethod
|
||||
def Contain(val: int, probe: int):
|
||||
return bool(val & probe)
|
||||
|
||||
@staticmethod
|
||||
def Add(val: int, data: int):
|
||||
return val | data
|
||||
|
||||
@staticmethod
|
||||
def PrintEnum(val: int, _enum: enum.IntEnum):
|
||||
for i in _enum:
|
||||
if i.value == val:
|
||||
return i.name
|
||||
|
||||
return ""
|
||||
|
||||
@staticmethod
|
||||
def PrintEnumFlag(val: int, _enum: enum.IntEnum):
|
||||
pending = []
|
||||
|
||||
for i in _enum:
|
||||
# if it have exactly same entry, return directly
|
||||
if i.value == val:
|
||||
return i.name
|
||||
|
||||
# check exist
|
||||
if bool(val & i.value):
|
||||
pending.append(i.name)
|
||||
|
||||
return ', '.join(pending)
|
||||
|
||||
class CK_FILE_WRITEMODE(enum.IntEnum):
|
||||
CKFILE_UNCOMPRESSED =0 # Save data uncompressed
|
||||
CKFILE_CHUNKCOMPRESSED_OLD =1 # Obsolete
|
||||
CKFILE_EXTERNALTEXTURES_OLD=2 # Obsolete : use CKContext::SetGlobalImagesSaveOptions instead.
|
||||
CKFILE_FORVIEWER =4 # Don't save Interface Data within the file, the level won't be editable anymore in the interface
|
||||
CKFILE_WHOLECOMPRESSED =8 # Compress the whole file
|
||||
|
||||
class CK_LOAD_FLAGS(enum.IntEnum):
|
||||
CK_LOAD_ANIMATION =1<<0 # Load animations
|
||||
CK_LOAD_GEOMETRY =1<<1 # Load geometry.
|
||||
CK_LOAD_DEFAULT =CK_LOAD_GEOMETRY|CK_LOAD_ANIMATION # Load animations & geometry
|
||||
CK_LOAD_ASCHARACTER =1<<2 # Load all the objects and create a character that contains them all .
|
||||
CK_LOAD_DODIALOG =1<<3 # Check object name unicity and warns the user with a dialog box when duplicate names are found.
|
||||
CK_LOAD_AS_DYNAMIC_OBJECT =1<<4 # Objects loaded from this file may be deleted at run-time or are temporary
|
||||
CK_LOAD_AUTOMATICMODE =1<<5 # Check object name unicity and automatically rename or replace according to the options specified in CKContext::SetAutomaticLoadMode
|
||||
CK_LOAD_CHECKDUPLICATES =1<<6 # Check object name unicity (The list of duplicates is stored in the CKFile class after a OpenFile call
|
||||
CK_LOAD_CHECKDEPENDENCIES =1<<7 # Check if every plugins needed are availables
|
||||
CK_LOAD_ONLYBEHAVIORS =1<<8 #
|
||||
|
||||
CK_CLASSID = int
|
||||
class CKCID(enum.IntEnum):
|
||||
CKCID_OBJECT = 1
|
||||
CKCID_PARAMETERIN = 2
|
||||
CKCID_PARAMETEROPERATION = 4
|
||||
CKCID_STATE = 5
|
||||
CKCID_BEHAVIORLINK = 6
|
||||
CKCID_BEHAVIOR = 8
|
||||
CKCID_BEHAVIORIO = 9
|
||||
CKCID_RENDERCONTEXT = 12
|
||||
CKCID_KINEMATICCHAIN = 13
|
||||
CKCID_SCENEOBJECT = 11
|
||||
CKCID_OBJECTANIMATION = 15
|
||||
CKCID_ANIMATION = 16
|
||||
CKCID_KEYEDANIMATION = 18
|
||||
CKCID_BEOBJECT = 19
|
||||
CKCID_DATAARRAY = 52
|
||||
CKCID_SCENE = 10
|
||||
CKCID_LEVEL = 21
|
||||
CKCID_PLACE = 22
|
||||
CKCID_GROUP = 23
|
||||
CKCID_SOUND = 24
|
||||
CKCID_WAVESOUND = 25
|
||||
CKCID_MIDISOUND = 26
|
||||
CKCID_MATERIAL = 30
|
||||
CKCID_TEXTURE = 31
|
||||
CKCID_MESH = 32
|
||||
CKCID_PATCHMESH = 53
|
||||
CKCID_RENDEROBJECT = 47
|
||||
CKCID_2DENTITY = 27
|
||||
CKCID_SPRITE = 28
|
||||
CKCID_SPRITETEXT = 29
|
||||
CKCID_3DENTITY = 33
|
||||
CKCID_GRID = 50
|
||||
CKCID_CURVEPOINT = 36
|
||||
CKCID_SPRITE3D = 37
|
||||
CKCID_CURVE = 43
|
||||
CKCID_CAMERA = 34
|
||||
CKCID_TARGETCAMERA = 35
|
||||
CKCID_LIGHT = 38
|
||||
CKCID_TARGETLIGHT = 39
|
||||
CKCID_CHARACTER = 40
|
||||
CKCID_3DOBJECT = 41
|
||||
CKCID_BODYPART = 42
|
||||
CKCID_PARAMETER = 46
|
||||
CKCID_PARAMETERLOCAL = 45
|
||||
CKCID_PARAMETERVARIABLE = 55
|
||||
CKCID_PARAMETEROUT = 3
|
||||
CKCID_INTERFACEOBJECTMANAGER = 48
|
||||
CKCID_CRITICALSECTION = 49
|
||||
CKCID_LAYER = 51
|
||||
CKCID_PROGRESSIVEMESH = 54
|
||||
CKCID_SYNCHRO = 20
|
||||
|
||||
CKCID_OBJECTARRAY = 80
|
||||
CKCID_SCENEOBJECTDESC = 81
|
||||
CKCID_ATTRIBUTEMANAGER = 82
|
||||
CKCID_MESSAGEMANAGER = 83
|
||||
CKCID_COLLISIONMANAGER = 84
|
||||
CKCID_OBJECTMANAGER = 85
|
||||
CKCID_FLOORMANAGER = 86
|
||||
CKCID_RENDERMANAGER = 87
|
||||
CKCID_BEHAVIORMANAGER = 88
|
||||
CKCID_INPUTMANAGER = 89
|
||||
CKCID_PARAMETERMANAGER = 90
|
||||
CKCID_GRIDMANAGER = 91
|
||||
CKCID_SOUNDMANAGER = 92
|
||||
CKCID_TIMEMANAGER = 93
|
||||
CKCID_CUIKBEHDATA = -1
|
||||
|
||||
CKCID_MAXCLASSID = 56
|
||||
CKCID_MAXMAXCLASSID = 128
|
||||
|
||||
__ClassHierarchy = {
|
||||
1: ("CKCID_OBJECT", ),
|
||||
2: ("CKCID_OBJECT", "CKCID_PARAMETERIN", ),
|
||||
4: ("CKCID_OBJECT", "CKCID_PARAMETEROPERATION", ),
|
||||
5: ("CKCID_OBJECT", "CKCID_STATE", ),
|
||||
6: ("CKCID_OBJECT", "CKCID_BEHAVIORLINK", ),
|
||||
8: ("CKCID_OBJECT", "CKCID_BEHAVIOR", ),
|
||||
9: ("CKCID_OBJECT", "CKCID_BEHAVIORIO", ),
|
||||
12: ("CKCID_OBJECT", "CKCID_RENDERCONTEXT", ),
|
||||
13: ("CKCID_OBJECT", "CKCID_KINEMATICCHAIN", ),
|
||||
11: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", ),
|
||||
15: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_OBJECTANIMATION", ),
|
||||
16: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_ANIMATION", ),
|
||||
18: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_ANIMATION", "CKCID_KEYEDANIMATION", ),
|
||||
19: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", ),
|
||||
52: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_DATAARRAY", ),
|
||||
10: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_SCENE", ),
|
||||
21: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_LEVEL", ),
|
||||
22: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_PLACE", ),
|
||||
23: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_GROUP", ),
|
||||
24: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_SOUND", ),
|
||||
25: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_SOUND", "CKCID_WAVESOUND", ),
|
||||
26: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_SOUND", "CKCID_MIDISOUND", ),
|
||||
30: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_MATERIAL", ),
|
||||
31: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_TEXTURE", ),
|
||||
32: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_MESH", ),
|
||||
53: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_MESH", "CKCID_PATCHMESH", ),
|
||||
47: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_RENDEROBJECT", ),
|
||||
27: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_RENDEROBJECT", "CKCID_2DENTITY", ),
|
||||
28: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_RENDEROBJECT", "CKCID_2DENTITY", "CKCID_SPRITE", ),
|
||||
29: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_RENDEROBJECT", "CKCID_2DENTITY", "CKCID_SPRITETEXT", ),
|
||||
33: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_3DENTITY", ),
|
||||
50: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_3DENTITY", "CKCID_GRID", ),
|
||||
36: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_3DENTITY", "CKCID_CURVEPOINT", ),
|
||||
37: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_3DENTITY", "CKCID_SPRITE3D", ),
|
||||
43: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_3DENTITY", "CKCID_CURVE", ),
|
||||
34: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_3DENTITY", "CKCID_CAMERA", ),
|
||||
35: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_3DENTITY", "CKCID_CAMERA", "CKCID_TARGETCAMERA", ),
|
||||
38: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_3DENTITY", "CKCID_LIGHT", ),
|
||||
39: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_3DENTITY", "CKCID_LIGHT", "CKCID_TARGETLIGHT", ),
|
||||
40: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_3DENTITY", "CKCID_CHARACTER", ),
|
||||
41: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_3DENTITY", "CKCID_3DOBJECT", ),
|
||||
42: ("CKCID_OBJECT", "CKCID_SCENEOBJECT", "CKCID_BEOBJECT", "CKCID_3DENTITY", "CKCID_3DOBJECT", "CKCID_BODYPART", ),
|
||||
46: ("CKCID_OBJECT", "CKCID_PARAMETER", ),
|
||||
45: ("CKCID_OBJECT", "CKCID_PARAMETER", "CKCID_PARAMETERLOCAL", ),
|
||||
55: ("CKCID_OBJECT", "CKCID_PARAMETER", "CKCID_PARAMETERLOCAL", "CKCID_PARAMETERVARIABLE", ),
|
||||
3: ("CKCID_OBJECT", "CKCID_PARAMETER", "CKCID_PARAMETEROUT", ),
|
||||
48: ("CKCID_OBJECT", "CKCID_INTERFACEOBJECTMANAGER", ),
|
||||
49: ("CKCID_OBJECT", "CKCID_CRITICALSECTION", ),
|
||||
51: ("CKCID_OBJECT", "CKCID_LAYER", ),
|
||||
54: ("CKCID_OBJECT", "CKCID_PROGRESSIVEMESH", ),
|
||||
20: ("CKCID_OBJECT", "CKCID_SYNCHRO", ),
|
||||
80: ("CKCID_OBJECTARRAY", ),
|
||||
81: ("CKCID_SCENEOBJECTDESC", ),
|
||||
82: ("CKCID_ATTRIBUTEMANAGER", ),
|
||||
83: ("CKCID_MESSAGEMANAGER", ),
|
||||
84: ("CKCID_COLLISIONMANAGER", ),
|
||||
85: ("CKCID_OBJECTMANAGER", ),
|
||||
86: ("CKCID_FLOORMANAGER", ),
|
||||
87: ("CKCID_RENDERMANAGER", ),
|
||||
88: ("CKCID_BEHAVIORMANAGER", ),
|
||||
89: ("CKCID_INPUTMANAGER", ),
|
||||
90: ("CKCID_PARAMETERMANAGER", ),
|
||||
91: ("CKCID_GRIDMANAGER", ),
|
||||
92: ("CKCID_SOUNDMANAGER", ),
|
||||
93: ("CKCID_TIMEMANAGER", ),
|
||||
-1: ("CKCID_CUIKBEHDATA", ),
|
||||
56: ("CKCID_MAXCLASSID", ),
|
||||
128: ("CKCID_MAXMAXCLASSID", ),
|
||||
}
|
||||
|
||||
def __init__(self, code: CK_CLASSID):
|
||||
self.code: CK_CLASSID = code
|
||||
def __repr__(self):
|
||||
hierarchy = self.__ClassHierarchy.get(self.code, None)
|
||||
if hierarchy is None:
|
||||
return "[Undefined]"
|
||||
return "{} ({})".format(
|
||||
hierarchy[-1],
|
||||
' -> '.join(hierarchy)
|
||||
)
|
||||
|
||||
|
||||
CKERROR = int
|
||||
class CKERR():
|
||||
CKERR_OK = 0
|
||||
CKERR_INVALIDPARAMETER = -1
|
||||
CKERR_INVALIDPARAMETERTYPE = -2
|
||||
CKERR_INVALIDSIZE = -3
|
||||
CKERR_INVALIDOPERATION = -4
|
||||
CKERR_OPERATIONNOTIMPLEMENTED = -5
|
||||
CKERR_OUTOFMEMORY = -6
|
||||
CKERR_NOTIMPLEMENTED = -7
|
||||
CKERR_NOTFOUND = -11
|
||||
CKERR_NOLEVEL = -13
|
||||
CKERR_CANCREATERENDERCONTEXT = -14
|
||||
CKERR_NOTIFICATIONNOTHANDLED = -16
|
||||
CKERR_ALREADYPRESENT = -17
|
||||
CKERR_INVALIDRENDERCONTEXT = -18
|
||||
CKERR_RENDERCONTEXTINACTIVE = -19
|
||||
CKERR_NOLOADPLUGINS = -20
|
||||
CKERR_NOSAVEPLUGINS = -21
|
||||
CKERR_INVALIDFILE = -22
|
||||
CKERR_INVALIDPLUGIN = -23
|
||||
CKERR_NOTINITIALIZED = -24
|
||||
CKERR_INVALIDMESSAGE = -25
|
||||
CKERR_NODLLFOUND = -29
|
||||
CKERR_ALREADYREGISTREDDLL = -30
|
||||
CKERR_INVALIDDLL = -31
|
||||
CKERR_INVALIDOBJECT = -34
|
||||
CKERR_INVALIDCONDSOLEWINDOW = -35
|
||||
CKERR_INVALIDKINEMATICCHAIN = -36
|
||||
CKERR_NOKEYBOARD = -37
|
||||
CKERR_NOMOUSE = -38
|
||||
CKERR_NOJOYSTICK = -39
|
||||
CKERR_INCOMPATIBLEPARAMETERS = -40
|
||||
CKERR_NORENDERENGINE = -44
|
||||
CKERR_NOCURRENTLEVEL = -45
|
||||
CKERR_SOUNDDISABLED = -46
|
||||
CKERR_DINPUTDISABLED = -47
|
||||
CKERR_INVALIDGUID = -48
|
||||
CKERR_NOTENOUGHDISKPLACE = -49
|
||||
CKERR_CANTWRITETOFILE = -50
|
||||
CKERR_BEHAVIORADDDENIEDBYCB = -51
|
||||
CKERR_INCOMPATIBLECLASSID = -52
|
||||
CKERR_MANAGERALREADYEXISTS = -53
|
||||
CKERR_PAUSED = -54
|
||||
CKERR_PLUGINSMISSING = -55
|
||||
CKERR_OBSOLETEVIRTOOLS = -56
|
||||
CKERR_FILECRCERROR = -57
|
||||
CKERR_ALREADYFULLSCREEN = -58
|
||||
CKERR_CANCELLED = -59
|
||||
CKERR_NOANIMATIONKEY = -121
|
||||
CKERR_INVALIDINDEX = -122
|
||||
CKERR_INVALIDANIMATION = -123
|
||||
|
||||
__ErrorDescription = {
|
||||
0: "Operation successful",
|
||||
-1: "One of the parameter passed to the function was invalid",
|
||||
-2: "One of the parameter passed to the function was invalid",
|
||||
-3: "The parameter size was invalid",
|
||||
-4: "The operation type didn't exist",
|
||||
-5: "The function used to execute the operation is not yet implemented",
|
||||
-6: "There was not enough memory to perform the action",
|
||||
-7: "The function is not yet implemented",
|
||||
-11: "There was an attempt to remove something not present",
|
||||
-13: "There is no level currently created",
|
||||
-14: "There is no level currently created",
|
||||
-16: "The notification message was not used",
|
||||
-17: "Attempt to add an item that was already present",
|
||||
-18: "the render context is not valid",
|
||||
-19: "the render context is not activated for rendering",
|
||||
-20: "there was no plugins to load this kind of file",
|
||||
-21: "there was no plugins to save this kind of file",
|
||||
-22: "attempt to load an invalid file",
|
||||
-23: "attempt to load with an invalid plugin",
|
||||
-24: "attempt use an object that wasnt initialized",
|
||||
-25: "attempt use a message type that wasn't registred",
|
||||
-29: "No dll file found in the parse directory",
|
||||
-30: "this dll has already been registred",
|
||||
-31: "this dll does not contain information to create the prototype",
|
||||
-34: "Invalid Object (attempt to Get an object from an invalid ID)",
|
||||
-35: "Invalid window was provided as console window",
|
||||
-36: "Invalid kinematic chain ( end and start effector may not be part of the same hierarchy )",
|
||||
-37: "Keyboard not attached or not working properly",
|
||||
-38: "Mouse not attached or not working properly",
|
||||
-39: "Joystick not attached or not working properly",
|
||||
-40: "Try to link imcompatible Parameters",
|
||||
-44: "There is no render engine dll",
|
||||
-45: "There is no current level (use CKSetCurrentLevel )",
|
||||
-46: "Sound Management has been disabled",
|
||||
-47: "DirectInput Management has been disabled",
|
||||
-48: "Guid is already in use or invalid",
|
||||
-49: "There was no more free space on disk when trying to save a file",
|
||||
-50: "Impossible to write to file (write-protection ?)",
|
||||
-51: "The behavior cannnot be added to this entity",
|
||||
-52: "The behavior cannnot be added to this entity",
|
||||
-53: "A manager was registered more than once",
|
||||
-54: "CKprocess or TimeManager process while CK is paused will fail",
|
||||
-55: "Some plugins were missing whileloading a file",
|
||||
-56: "Virtools version too old to load this file",
|
||||
-57: "CRC Error while loading file",
|
||||
-58: "A Render context is already in Fullscreen Mode",
|
||||
-59: "Operation was cancelled by user",
|
||||
-121: "there were no animation key at the given index",
|
||||
-122: "attemp to acces an animation key with an invalid index",
|
||||
-123: "the animation is invalid (no entity associated or zero length)",
|
||||
}
|
||||
|
||||
def __init__(self, code: CKERROR):
|
||||
self.code: CKERROR = code
|
||||
def __repr__(self):
|
||||
return self.__ErrorDescription.get(self.code, "[Undefined]")
|
||||
|
47
PyCmo/VirtoolsReader.py
Normal file
47
PyCmo/VirtoolsReader.py
Normal file
@ -0,0 +1,47 @@
|
||||
import VirtoolsStruct
|
||||
import VirtoolsUtils
|
||||
import PyCmoMisc
|
||||
import struct, io, datetime, zlib
|
||||
|
||||
g_dword = struct.Struct("<I")
|
||||
|
||||
def ReadCKFileHeader(fs: io.BufferedReader):
|
||||
header = VirtoolsStruct.CKFileHeader()
|
||||
|
||||
# check magic words
|
||||
magic_words = fs.read(8)
|
||||
if magic_words != b'Nemo Fi\0':
|
||||
raise Exception("Fail to read file header magic words")
|
||||
header.Signature = magic_words
|
||||
|
||||
# assign data
|
||||
(header.Crc, raw_date, header.FileVersion, header.FileVersion2, header.SaveFlags, header.PrewHdrPackSize,
|
||||
header.DataPackSize, header.DataUnpackSize, header.ManagerCount, header.ObjectCount, header.MaxIDSaved,
|
||||
header.ProductVersion, header.ProductBuild, header.PrewHdrUnpackSize) = struct.unpack("<14I", fs.read(14 * 4))
|
||||
|
||||
# process date independently
|
||||
# date is in BCD code
|
||||
day = PyCmoMisc.BcdCodeToDecCode((raw_date >> 24) & 0xff)
|
||||
month = PyCmoMisc.BcdCodeToDecCode((raw_date >> 16) & 0xff - 1)
|
||||
month = (month % 12) + 1
|
||||
year = PyCmoMisc.BcdCodeToDecCode(raw_date & 0xffff)
|
||||
header.Timestamp = datetime.date(year, month, day)
|
||||
|
||||
if header.FileVersion >= 8:
|
||||
# check crc
|
||||
gotten_crc = zlib.adler32(b'Nemo Fi\0', 0)
|
||||
gotten_crc = zlib.adler32(struct.pack("<6I", 0, raw_date, header.FileVersion, header.FileVersion2, header.SaveFlags, header.PrewHdrPackSize), gotten_crc) # reset crc as zero
|
||||
gotten_crc = zlib.adler32(struct.pack("<8I", header.DataPackSize, header.DataUnpackSize, header.ManagerCount, header.ObjectCount, header.MaxIDSaved, header.ProductVersion, header.ProductBuild, header.PrewHdrUnpackSize), gotten_crc)
|
||||
gotten_crc = zlib.adler32(fs.read(header.PrewHdrPackSize), gotten_crc)
|
||||
gotten_crc = zlib.adler32(fs.read(header.DataPackSize), gotten_crc)
|
||||
if gotten_crc != header.Crc:
|
||||
raise Exception("Crc Error")
|
||||
|
||||
return header
|
||||
|
||||
|
||||
def ReadCKComposition(fs: io.BufferedReader):
|
||||
composition = VirtoolsStruct.CKComposition()
|
||||
|
||||
composition.Header = ReadCKFileHeader(fs)
|
||||
return composition
|
43
PyCmo/VirtoolsStruct.py
Normal file
43
PyCmo/VirtoolsStruct.py
Normal file
@ -0,0 +1,43 @@
|
||||
import VirtoolsConstants
|
||||
import datetime
|
||||
import PyCmoMisc
|
||||
|
||||
class CKFileHeader:
|
||||
def __init__(self):
|
||||
self.Signature: bytes = b'Nemo Fi\0'
|
||||
self.Crc: int = 0
|
||||
self.Timestamp: datetime.date = datetime.date.today()
|
||||
self.FileVersion: int = 0
|
||||
self.FileVersion2: int = 0
|
||||
self.SaveFlags: int = 0
|
||||
self.PrewHdrPackSize: int = 0
|
||||
|
||||
self.DataPackSize: int = 0
|
||||
self.DataUnpackSize: int = 0
|
||||
self.ManagerCount: int = 0
|
||||
self.ObjectCount: int = 0
|
||||
self.MaxIDSaved: int = 0
|
||||
self.ProductVersion: int = 0
|
||||
self.ProductBuild: int = 0
|
||||
self.PrewHdrUnpackSize: int = 0
|
||||
|
||||
def __str__(self):
|
||||
return f"""File Version: {self.FileVersion:d} / {self.FileVersion2:d}
|
||||
Production (Version / Build): {self.ProductVersion:d} / {(self.ProductBuild >> 24) & 0xff:d}.{(self.ProductBuild >> 16) & 0xff:d}.{(self.ProductBuild >> 8) & 0xff:d}.{self.ProductBuild & 0xff:d}
|
||||
Crc: 0x{self.Crc:08X}
|
||||
Timestamp: {str(self.Timestamp)}
|
||||
Save Flags: {VirtoolsConstants.PyEnum.PrintEnumFlag(self.SaveFlags, VirtoolsConstants.CK_FILE_WRITEMODE)}
|
||||
|
||||
Preview Header (Pack / Unpack): {PyCmoMisc.OutputSizeHumanReadable(self.PrewHdrPackSize)} / {PyCmoMisc.OutputSizeHumanReadable(self.PrewHdrUnpackSize)}
|
||||
Data (Pack / Unpack): {PyCmoMisc.OutputSizeHumanReadable(self.DataPackSize)} / {PyCmoMisc.OutputSizeHumanReadable(self.DataUnpackSize)}
|
||||
|
||||
Manager Count: {self.ManagerCount:d}
|
||||
Object Count: {self.ObjectCount:d}
|
||||
Max ID Saved: {self.MaxIDSaved:d}
|
||||
"""
|
||||
|
||||
|
||||
class CKComposition(object):
|
||||
def __init__(self):
|
||||
self.Header: CKFileHeader = None
|
||||
|
48
PyCmo/VirtoolsUtils.py
Normal file
48
PyCmo/VirtoolsUtils.py
Normal file
@ -0,0 +1,48 @@
|
||||
import zlib
|
||||
import io
|
||||
|
||||
class ZlibDecompressBuffer(object):
|
||||
def __init__(self, _fs: io.BufferedReader, _len: int, _is_compressed: bool):
|
||||
self.__fs: io.BufferedReader = _fs
|
||||
self.__len: int = _len
|
||||
self.__compressed: bool = _is_compressed
|
||||
|
||||
self.__pos: int = 0
|
||||
self.__parser: zlib._Decompress = zlib.decompressobj()
|
||||
self.__cache: bytes = b''
|
||||
self.__cachelen: int = 0
|
||||
|
||||
def __ParseOnce(self) -> bytes:
|
||||
# check remain
|
||||
remain: int = self.__len - self.__pos
|
||||
if remain <= 0:
|
||||
return None
|
||||
|
||||
# read it and increase pos
|
||||
read_count: int = min(remain, 1024)
|
||||
gotten_uncompressed: bytes = self.__parser.decompress(self.__fs.read(read_count))
|
||||
self.__pos += read_count
|
||||
|
||||
# everything has done, no more data, flush it and get it remained data
|
||||
if self.__pos >= self.__len:
|
||||
gotten_uncompressed += self.__parser.flush()
|
||||
|
||||
return gotten_uncompressed
|
||||
|
||||
def Read(self, expected: int):
|
||||
# try enrich cache
|
||||
while self.__cachelen < expected:
|
||||
new_data = self.__ParseOnce()
|
||||
if new_data is None:
|
||||
# no more data
|
||||
raise Exception("No more data.")
|
||||
else:
|
||||
self.__cache += new_data
|
||||
self.__cachelen += len(new_data)
|
||||
|
||||
# change data
|
||||
returned_data = self.__cache[:expected]
|
||||
self.__cache = self.__cache[expected:]
|
||||
self.__cachelen -= expected
|
||||
|
||||
return returned_data
|
Reference in New Issue
Block a user