You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
645 lines
27 KiB
645 lines
27 KiB
2 years ago
|
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||
|
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||
|
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||
|
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||
|
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||
|
# Magicbane Emulator Project © 2013 - 2022
|
||
|
# www.magicbane.com
|
||
|
|
||
|
from collections import OrderedDict
|
||
|
|
||
|
from arcane.util import ResStream
|
||
|
|
||
|
TRACKER_TO_STRING = {
|
||
|
0: 'NONE',
|
||
|
1: 'XY',
|
||
|
2: 'Y',
|
||
|
}
|
||
|
STRING_TO_TRACKER = {value: key for key, value in TRACKER_TO_STRING.items()}
|
||
|
|
||
|
TRANSPARENT_TO_STRING = {
|
||
|
0: 'NONE',
|
||
|
1: 'PINK',
|
||
|
2: 'BLACK',
|
||
|
3: 'WHITE',
|
||
|
4: 'SEMI',
|
||
|
6: 'ALPHA',
|
||
|
}
|
||
|
STRING_TO_TRANSPARENT = {value: key for key, value in TRANSPARENT_TO_STRING.items()}
|
||
|
|
||
|
TEXTURE_TO_STRING = {
|
||
|
0: 'SINGLE_TEXTURE',
|
||
|
1: 'COLOR_TEXTURE',
|
||
|
3: 'ANIMATED_TEXTURE',
|
||
|
}
|
||
|
STRING_TO_TEXTURE = {value: key for key, value in TEXTURE_TO_STRING.items()}
|
||
|
|
||
|
LIGHT_TYPE_TO_STRING = {
|
||
|
0xb6787258: 'ArcLightPoint',
|
||
|
0x54e8ff1d: 'ArcLightAffectorAttach',
|
||
|
0xa73bd9d4: 'ArcLightAffectorFlicker',
|
||
|
}
|
||
|
STRING_TO_LIGHT_TYPE = {value: key for key, value in LIGHT_TYPE_TO_STRING.items()}
|
||
|
|
||
|
|
||
|
class ArcSinglePolyMesh:
|
||
|
def load_binary(self, stream: ResStream):
|
||
|
self.polymesh_id = stream.read_qword()
|
||
|
self.polymesh_decal = stream.read_bool()
|
||
|
self.polymesh_double_sided = stream.read_bool()
|
||
|
|
||
|
def save_binary(self, stream: ResStream):
|
||
|
stream.write_qword(self.polymesh_id)
|
||
|
stream.write_bool(self.polymesh_decal)
|
||
|
stream.write_bool(self.polymesh_double_sided)
|
||
|
|
||
|
def load_json(self, data):
|
||
|
self.polymesh_id = data['polymesh_id']
|
||
|
self.polymesh_decal = data['polymesh_decal']
|
||
|
self.polymesh_double_sided = data['polymesh_double_sided']
|
||
|
|
||
|
def save_json(self):
|
||
|
data = OrderedDict()
|
||
|
data['polymesh_id'] = self.polymesh_id
|
||
|
data['polymesh_decal'] = self.polymesh_decal
|
||
|
data['polymesh_double_sided'] = self.polymesh_double_sided
|
||
|
return data
|
||
|
|
||
|
|
||
|
class ArcMeshSet:
|
||
|
def load_binary(self, stream: ResStream):
|
||
|
num = stream.read_dword()
|
||
|
self.mesh_set = [ArcSinglePolyMesh() for _ in range(num)]
|
||
|
for mesh in self.mesh_set:
|
||
|
mesh.load_binary(stream)
|
||
|
|
||
|
def save_binary(self, stream: ResStream):
|
||
|
stream.write_dword(len(self.mesh_set))
|
||
|
for mesh in self.mesh_set:
|
||
|
mesh.save_binary(stream)
|
||
|
|
||
|
def load_json(self, data):
|
||
|
self.mesh_set = []
|
||
|
for mesh_data in data['mesh_set']:
|
||
|
mesh = ArcSinglePolyMesh()
|
||
|
mesh.load_json(mesh_data)
|
||
|
self.mesh_set.append(mesh)
|
||
|
|
||
|
def save_json(self):
|
||
|
data = OrderedDict()
|
||
|
data['mesh_set'] = []
|
||
|
for mesh in self.mesh_set:
|
||
|
data['mesh_set'].append(mesh.save_json())
|
||
|
return data
|
||
|
|
||
|
|
||
|
class ArcRenderTemplate:
|
||
|
def load_binary(self, stream: ResStream):
|
||
|
self.template_object_can_fade = stream.read_bool()
|
||
|
self.template_tracker = stream.read_dword()
|
||
|
self.template_illuminated = stream.read_bool()
|
||
|
self.template_bone_length = stream.read_float()
|
||
|
self.template_clip_map = stream.read_dword()
|
||
|
self.template_light_two_side = stream.read_dword()
|
||
|
self.template_cull_face = stream.read_dword()
|
||
|
self.template_specular_map = stream.read_qword()
|
||
|
self.template_shininess = stream.read_float()
|
||
|
self.template_has_mesh = stream.read_bool()
|
||
|
if self.template_has_mesh:
|
||
|
self.template_mesh = ArcMeshSet()
|
||
|
self.template_mesh.load_binary(stream)
|
||
|
|
||
|
def save_binary(self, stream: ResStream):
|
||
|
stream.write_bool(self.template_object_can_fade)
|
||
|
stream.write_dword(self.template_tracker)
|
||
|
stream.write_bool(self.template_illuminated)
|
||
|
stream.write_float(self.template_bone_length)
|
||
|
stream.write_dword(self.template_clip_map)
|
||
|
stream.write_dword(self.template_light_two_side)
|
||
|
stream.write_dword(self.template_cull_face)
|
||
|
stream.write_qword(self.template_specular_map)
|
||
|
stream.write_float(self.template_shininess)
|
||
|
stream.write_bool(self.template_has_mesh)
|
||
|
if self.template_has_mesh:
|
||
|
self.template_mesh.save_binary(stream)
|
||
|
|
||
|
def load_json(self, data):
|
||
|
self.template_object_can_fade = data['template_object_can_fade']
|
||
|
self.template_tracker = STRING_TO_TRACKER[data['template_tracker']]
|
||
|
self.template_illuminated = data['template_illuminated']
|
||
|
self.template_bone_length = data['template_bone_length']
|
||
|
self.template_clip_map = data['template_clip_map']
|
||
|
self.template_light_two_side = data['template_light_two_side']
|
||
|
self.template_cull_face = data['template_cull_face']
|
||
|
self.template_specular_map = data['template_specular_map']
|
||
|
self.template_shininess = data['template_shininess']
|
||
|
self.template_has_mesh = data['template_has_mesh']
|
||
|
if self.template_has_mesh:
|
||
|
self.template_mesh = ArcMeshSet()
|
||
|
self.template_mesh.load_json(data['template_mesh'])
|
||
|
|
||
|
def save_json(self):
|
||
|
data = OrderedDict()
|
||
|
data['template_object_can_fade'] = self.template_object_can_fade
|
||
|
data['template_tracker'] = TRACKER_TO_STRING[self.template_tracker]
|
||
|
data['template_illuminated'] = self.template_illuminated
|
||
|
data['template_bone_length'] = self.template_bone_length
|
||
|
data['template_clip_map'] = self.template_clip_map
|
||
|
data['template_light_two_side'] = self.template_light_two_side
|
||
|
data['template_cull_face'] = self.template_cull_face
|
||
|
data['template_specular_map'] = self.template_specular_map
|
||
|
data['template_shininess'] = self.template_shininess
|
||
|
data['template_has_mesh'] = self.template_has_mesh
|
||
|
if self.template_has_mesh:
|
||
|
data['template_mesh'] = self.template_mesh.save_json()
|
||
|
return data
|
||
|
|
||
|
|
||
|
class ArcSingleTexture:
|
||
|
def load_binary(self, stream: ResStream):
|
||
|
self.texture_id = stream.read_qword()
|
||
|
self.texture_transparent = stream.read_dword()
|
||
|
self.texture_compress = stream.read_bool()
|
||
|
self.texture_normal_map = stream.read_bool()
|
||
|
self.texture_detail_normal_map = stream.read_bool()
|
||
|
self.texture_create_mip_maps = stream.read_bool()
|
||
|
self.texture_x0 = stream.read_string()
|
||
|
self.texture_x1 = stream.read_string()
|
||
|
self.texture_x2 = stream.read_dword()
|
||
|
self.texture_x3 = stream.read_dword()
|
||
|
self.texture_x4 = stream.read_bool()
|
||
|
self.texture_wrap = stream.read_bool()
|
||
|
|
||
|
def save_binary(self, stream: ResStream):
|
||
|
stream.write_qword(self.texture_id)
|
||
|
stream.write_dword(self.texture_transparent)
|
||
|
stream.write_bool(self.texture_compress)
|
||
|
stream.write_bool(self.texture_normal_map)
|
||
|
stream.write_bool(self.texture_detail_normal_map)
|
||
|
stream.write_bool(self.texture_create_mip_maps)
|
||
|
stream.write_string(self.texture_x0)
|
||
|
stream.write_string(self.texture_x1)
|
||
|
stream.write_dword(self.texture_x2)
|
||
|
stream.write_dword(self.texture_x3)
|
||
|
stream.write_bool(self.texture_x4)
|
||
|
stream.write_bool(self.texture_wrap)
|
||
|
|
||
|
def load_json(self, data):
|
||
|
self.texture_id = data['texture_id']
|
||
|
self.texture_transparent = STRING_TO_TRANSPARENT[data['texture_transparent']]
|
||
|
self.texture_compress = data['texture_compress']
|
||
|
self.texture_normal_map = data['texture_normal_map']
|
||
|
self.texture_detail_normal_map = data['texture_detail_normal_map']
|
||
|
self.texture_create_mip_maps = data['texture_create_mip_maps']
|
||
|
self.texture_x0 = ''
|
||
|
self.texture_x1 = ''
|
||
|
self.texture_x2 = 255
|
||
|
self.texture_x3 = 0
|
||
|
self.texture_x4 = False
|
||
|
self.texture_wrap = data['texture_wrap']
|
||
|
|
||
|
def save_json(self):
|
||
|
data = OrderedDict()
|
||
|
data['texture_id'] = self.texture_id
|
||
|
data['texture_transparent'] = TRANSPARENT_TO_STRING[self.texture_transparent]
|
||
|
data['texture_compress'] = self.texture_compress
|
||
|
data['texture_normal_map'] = self.texture_normal_map
|
||
|
data['texture_detail_normal_map'] = self.texture_detail_normal_map
|
||
|
data['texture_create_mip_maps'] = self.texture_create_mip_maps
|
||
|
data['texture_wrap'] = self.texture_wrap
|
||
|
return data
|
||
|
|
||
|
|
||
|
class ArcColorTexture(ArcSingleTexture):
|
||
|
pass
|
||
|
|
||
|
|
||
|
class ArcAnimatedTexture:
|
||
|
def load_binary(self, stream: ResStream):
|
||
|
self.animated_texture_id = stream.read_qword()
|
||
|
self.animated_texture_transparent = stream.read_dword()
|
||
|
self.animated_texture_compress = stream.read_bool()
|
||
|
self.animated_texture_normal_map = stream.read_bool()
|
||
|
self.animated_texture_detail_normal_map = stream.read_bool()
|
||
|
self.animated_texture_create_mip_maps = stream.read_bool()
|
||
|
self.animated_texture_frame_timer = stream.read_float()
|
||
|
self.animated_texture_x0 = stream.read_float()
|
||
|
self.animated_texture_frame_rand = stream.read_dword()
|
||
|
|
||
|
num = stream.read_dword()
|
||
|
self.animated_texture_sets = [ArcTextureSet() for _ in range(num)]
|
||
|
for texture in self.animated_texture_sets:
|
||
|
texture.load_binary(stream)
|
||
|
|
||
|
def save_binary(self, stream: ResStream):
|
||
|
stream.write_qword(self.animated_texture_id)
|
||
|
stream.write_dword(self.animated_texture_transparent)
|
||
|
stream.write_bool(self.animated_texture_compress)
|
||
|
stream.write_bool(self.animated_texture_normal_map)
|
||
|
stream.write_bool(self.animated_texture_detail_normal_map)
|
||
|
stream.write_bool(self.animated_texture_create_mip_maps)
|
||
|
stream.write_float(self.animated_texture_frame_timer)
|
||
|
stream.write_float(self.animated_texture_x0)
|
||
|
stream.write_dword(self.animated_texture_frame_rand)
|
||
|
|
||
|
stream.write_dword(len(self.animated_texture_sets))
|
||
|
for texture in self.animated_texture_sets:
|
||
|
texture.save_binary(stream)
|
||
|
|
||
|
def load_json(self, data):
|
||
|
self.animated_texture_id = data['animated_texture_id']
|
||
|
self.animated_texture_transparent = STRING_TO_TRANSPARENT[data['animated_texture_transparent']]
|
||
|
self.animated_texture_compress = data['animated_texture_compress']
|
||
|
self.animated_texture_normal_map = data['animated_texture_normal_map']
|
||
|
self.animated_texture_detail_normal_map = data['animated_texture_detail_normal_map']
|
||
|
self.animated_texture_create_mip_maps = data['animated_texture_create_mip_maps']
|
||
|
self.animated_texture_frame_timer = data['animated_texture_frame_timer']
|
||
|
self.animated_texture_x0 = 0.0
|
||
|
self.animated_texture_frame_rand = data['animated_texture_frame_rand']
|
||
|
self.animated_texture_sets = []
|
||
|
for texture_data in data['animated_texture_sets']:
|
||
|
texture = ArcTextureSet()
|
||
|
texture.load_json(texture_data)
|
||
|
self.animated_texture_sets.append(texture)
|
||
|
|
||
|
def save_json(self):
|
||
|
data = OrderedDict()
|
||
|
data['animated_texture_id'] = self.animated_texture_id
|
||
|
data['animated_texture_transparent'] = TRANSPARENT_TO_STRING[self.animated_texture_transparent]
|
||
|
data['animated_texture_compress'] = self.animated_texture_compress
|
||
|
data['animated_texture_normal_map'] = self.animated_texture_normal_map
|
||
|
data['animated_texture_detail_normal_map'] = self.animated_texture_detail_normal_map
|
||
|
data['animated_texture_create_mip_maps'] = self.animated_texture_create_mip_maps
|
||
|
data['animated_texture_frame_timer'] = self.animated_texture_frame_timer
|
||
|
data['animated_texture_frame_rand'] = self.animated_texture_frame_rand
|
||
|
data['animated_texture_sets'] = []
|
||
|
for texture in self.animated_texture_sets:
|
||
|
data['animated_texture_sets'].append(texture.save_json())
|
||
|
return data
|
||
|
|
||
|
|
||
|
class ArcTextureSet:
|
||
|
def load_binary(self, stream: ResStream):
|
||
|
self.texture_type = stream.read_dword()
|
||
|
if self.texture_type == 0:
|
||
|
self.texture_data = ArcSingleTexture()
|
||
|
elif self.texture_type == 1:
|
||
|
self.texture_data = ArcColorTexture()
|
||
|
elif self.texture_type == 3:
|
||
|
self.texture_data = ArcAnimatedTexture()
|
||
|
self.texture_data.load_binary(stream)
|
||
|
|
||
|
def save_binary(self, stream: ResStream):
|
||
|
stream.write_dword(self.texture_type)
|
||
|
self.texture_data.save_binary(stream)
|
||
|
|
||
|
def load_json(self, data):
|
||
|
self.texture_type = STRING_TO_TEXTURE[data['texture_type']]
|
||
|
if self.texture_type == 0:
|
||
|
self.texture_data = ArcSingleTexture()
|
||
|
elif self.texture_type == 1:
|
||
|
self.texture_data = ArcColorTexture()
|
||
|
elif self.texture_type == 3:
|
||
|
self.texture_data = ArcAnimatedTexture()
|
||
|
self.texture_data.load_json(data['texture_data'])
|
||
|
|
||
|
def save_json(self):
|
||
|
data = OrderedDict()
|
||
|
data['texture_type'] = TEXTURE_TO_STRING[self.texture_type]
|
||
|
data['texture_data'] = self.texture_data.save_json()
|
||
|
return data
|
||
|
|
||
|
|
||
|
class ArcLightPoint:
|
||
|
def load_binary(self, stream: ResStream):
|
||
|
self.lightpoint_x0 = stream.read_dword()
|
||
|
self.lightpoint_x1 = stream.read_bool()
|
||
|
self.lightpoint_shader = stream.read_bool()
|
||
|
self.lightpoint_update_offscreen = stream.read_bool()
|
||
|
self.lightpoint_radius = stream.read_float()
|
||
|
self.lightpoint_position = stream.read_tuple()
|
||
|
self.lightpoint_diffuse_color = [stream.read_float() for _ in range(4)]
|
||
|
self.lightpoint_x2 = stream.read_dword()
|
||
|
self.lightpoint_orientation = [stream.read_float() for _ in range(4)]
|
||
|
self.lightpoint_cubemap = stream.read_dword()
|
||
|
self.lightpoint_x3 = stream.read_bool()
|
||
|
|
||
|
def save_binary(self, stream: ResStream):
|
||
|
stream.write_dword(self.lightpoint_x0)
|
||
|
stream.write_bool(self.lightpoint_x1)
|
||
|
stream.write_bool(self.lightpoint_shader)
|
||
|
stream.write_bool(self.lightpoint_update_offscreen)
|
||
|
stream.write_float(self.lightpoint_radius)
|
||
|
stream.write_tuple(self.lightpoint_position)
|
||
|
for i in range(4):
|
||
|
stream.write_float(self.lightpoint_diffuse_color[i])
|
||
|
stream.write_dword(self.lightpoint_x2)
|
||
|
for i in range(4):
|
||
|
stream.write_float(self.lightpoint_orientation[i])
|
||
|
stream.write_dword(self.lightpoint_cubemap)
|
||
|
stream.write_bool(self.lightpoint_x3)
|
||
|
|
||
|
def load_json(self, data):
|
||
|
self.lightpoint_x0 = 1
|
||
|
self.lightpoint_x1 = True
|
||
|
self.lightpoint_shader = data['lightpoint_shader']
|
||
|
self.lightpoint_update_offscreen = data['lightpoint_update_offscreen']
|
||
|
self.lightpoint_radius = data['lightpoint_radius']
|
||
|
self.lightpoint_position = data['lightpoint_position']
|
||
|
self.lightpoint_diffuse_color = data['lightpoint_diffuse_color']
|
||
|
self.lightpoint_x2 = 1
|
||
|
self.lightpoint_orientation = data['lightpoint_orientation']
|
||
|
self.lightpoint_cubemap = data['lightpoint_cubemap']
|
||
|
self.lightpoint_x3 = False
|
||
|
|
||
|
def save_json(self):
|
||
|
data = OrderedDict()
|
||
|
data['lightpoint_shader'] = self.lightpoint_shader
|
||
|
data['lightpoint_update_offscreen'] = self.lightpoint_update_offscreen
|
||
|
data['lightpoint_radius'] = self.lightpoint_radius
|
||
|
data['lightpoint_position'] = self.lightpoint_position
|
||
|
data['lightpoint_diffuse_color'] = self.lightpoint_diffuse_color
|
||
|
data['lightpoint_orientation'] = self.lightpoint_orientation
|
||
|
data['lightpoint_cubemap'] = self.lightpoint_cubemap
|
||
|
return data
|
||
|
|
||
|
|
||
|
class ArcLightAffectorAttach:
|
||
|
def load_binary(self, stream: ResStream):
|
||
|
self.attach_x0 = stream.read_dword()
|
||
|
self.attach_offset = stream.read_tuple()
|
||
|
|
||
|
def save_binary(self, stream: ResStream):
|
||
|
stream.write_dword(self.attach_x0)
|
||
|
stream.write_tuple(self.attach_offset)
|
||
|
|
||
|
def load_json(self, data):
|
||
|
self.attach_x0 = 1
|
||
|
self.attach_offset = data['attach_offset']
|
||
|
|
||
|
def save_json(self):
|
||
|
data = OrderedDict()
|
||
|
data['attach_offset'] = self.attach_offset
|
||
|
return data
|
||
|
|
||
|
|
||
|
class ArcLightAffectorFlicker:
|
||
|
def load_binary(self, stream: ResStream):
|
||
|
self.flicker_x0 = stream.read_dword()
|
||
|
self.flicker_avg_period = stream.read_float()
|
||
|
self.flicker_std_dev_radius = stream.read_float()
|
||
|
self.flicker_std_dev_period = stream.read_float()
|
||
|
self.flicker_falloff = stream.read_float()
|
||
|
|
||
|
def save_binary(self, stream: ResStream):
|
||
|
stream.write_dword(self.flicker_x0)
|
||
|
stream.write_float(self.flicker_avg_period)
|
||
|
stream.write_float(self.flicker_std_dev_radius)
|
||
|
stream.write_float(self.flicker_std_dev_period)
|
||
|
stream.write_float(self.flicker_falloff)
|
||
|
|
||
|
def load_json(self, data):
|
||
|
self.flicker_x0 = 1
|
||
|
self.flicker_avg_period = data['flicker_avg_period']
|
||
|
self.flicker_std_dev_radius = data['flicker_std_dev_radius']
|
||
|
self.flicker_std_dev_period = data['flicker_std_dev_period']
|
||
|
self.flicker_falloff = data['flicker_falloff']
|
||
|
|
||
|
def save_json(self):
|
||
|
data = OrderedDict()
|
||
|
data['flicker_avg_period'] = self.flicker_avg_period
|
||
|
data['flicker_std_dev_radius'] = self.flicker_std_dev_radius
|
||
|
data['flicker_std_dev_period'] = self.flicker_std_dev_period
|
||
|
data['flicker_falloff'] = self.flicker_falloff
|
||
|
return data
|
||
|
|
||
|
|
||
|
class ArcLightAffectors:
|
||
|
def load_binary(self, stream: ResStream):
|
||
|
self.light_affector_type = stream.read_dword()
|
||
|
|
||
|
if self.light_affector_type == 0x54e8ff1d:
|
||
|
self.light_affector_data = ArcLightAffectorAttach()
|
||
|
elif self.light_affector_type == 0xa73bd9d4:
|
||
|
self.light_affector_data = ArcLightAffectorFlicker()
|
||
|
self.light_affector_data.load_binary(stream)
|
||
|
|
||
|
self.light_affector_0xdaed = stream.read_dword()
|
||
|
|
||
|
def save_binary(self, stream: ResStream):
|
||
|
stream.write_dword(self.light_affector_type)
|
||
|
self.light_affector_data.save_binary(stream)
|
||
|
stream.write_dword(self.light_affector_0xdaed)
|
||
|
|
||
|
def load_json(self, data):
|
||
|
self.light_affector_type = STRING_TO_LIGHT_TYPE[data['light_affector_type']]
|
||
|
if self.light_affector_type == 0x54e8ff1d:
|
||
|
self.light_affector_data = ArcLightAffectorAttach()
|
||
|
elif self.light_affector_type == 0xa73bd9d4:
|
||
|
self.light_affector_data = ArcLightAffectorFlicker()
|
||
|
self.light_affector_data.load_json(data['light_affector_data'])
|
||
|
self.light_affector_0xdaed = 0xddaaeedd
|
||
|
|
||
|
def save_json(self):
|
||
|
data = OrderedDict()
|
||
|
data['light_affector_type'] = LIGHT_TYPE_TO_STRING[self.light_affector_type]
|
||
|
data['light_affector_data'] = self.light_affector_data.save_json()
|
||
|
return data
|
||
|
|
||
|
|
||
|
class ArcLight:
|
||
|
def load_binary(self, stream: ResStream):
|
||
|
self.light_x0 = stream.read_dword()
|
||
|
self.light_x1 = stream.read_bool()
|
||
|
self.light_type = stream.read_dword()
|
||
|
|
||
|
if self.light_type == 0xb6787258:
|
||
|
self.light_data = ArcLightPoint()
|
||
|
self.light_data.load_binary(stream)
|
||
|
|
||
|
self.light_0xdaed = stream.read_dword()
|
||
|
|
||
|
num = stream.read_dword()
|
||
|
self.light_affectors = [ArcLightAffectors() for _ in range(num)]
|
||
|
for extra in self.light_affectors:
|
||
|
extra.load_binary(stream)
|
||
|
|
||
|
def save_binary(self, stream: ResStream):
|
||
|
stream.write_dword(self.light_x0)
|
||
|
stream.write_bool(self.light_x1)
|
||
|
stream.write_dword(self.light_type)
|
||
|
self.light_data.save_binary(stream)
|
||
|
stream.write_dword(self.light_0xdaed)
|
||
|
|
||
|
stream.write_dword(len(self.light_affectors))
|
||
|
for extra in self.light_affectors:
|
||
|
extra.save_binary(stream)
|
||
|
|
||
|
def load_json(self, data):
|
||
|
self.light_x0 = 1
|
||
|
self.light_x1 = True
|
||
|
self.light_type = STRING_TO_LIGHT_TYPE[data['light_type']]
|
||
|
if self.light_type == 0xb6787258:
|
||
|
self.light_data = ArcLightPoint()
|
||
|
self.light_data.load_json(data['light_data'])
|
||
|
self.light_0xdaed = 0xddaaeedd
|
||
|
|
||
|
self.light_affectors = []
|
||
|
for extra_data in data['light_affectors']:
|
||
|
extra = ArcLightAffectors()
|
||
|
extra.load_json(extra_data)
|
||
|
self.light_affectors.append(extra)
|
||
|
|
||
|
def save_json(self):
|
||
|
data = OrderedDict()
|
||
|
data['light_type'] = LIGHT_TYPE_TO_STRING[self.light_type]
|
||
|
data['light_data'] = self.light_data.save_json()
|
||
|
|
||
|
data['light_affectors'] = []
|
||
|
for extra in self.light_affectors:
|
||
|
data['light_affectors'].append(extra.save_json())
|
||
|
return data
|
||
|
|
||
|
|
||
|
class ArcRender:
|
||
|
def load_binary(self, stream: ResStream):
|
||
|
self.render_template = ArcRenderTemplate()
|
||
|
self.render_template.load_binary(stream)
|
||
|
self.render_target_bone = stream.read_string()
|
||
|
self.render_scale = stream.read_tuple()
|
||
|
self.render_has_loc = stream.read_dword()
|
||
|
if self.render_has_loc:
|
||
|
self.render_loc = stream.read_tuple()
|
||
|
num_children = stream.read_dword()
|
||
|
self.render_children = [stream.read_qword() for _ in range(num_children)]
|
||
|
self.render_has_texture_set = stream.read_bool()
|
||
|
if self.render_has_texture_set:
|
||
|
num = stream.read_dword()
|
||
|
self.render_texture_set = [ArcTextureSet() for _ in range(num)]
|
||
|
for texture in self.render_texture_set:
|
||
|
texture.load_binary(stream)
|
||
|
self.render_collides = stream.read_bool()
|
||
|
self.render_calculate_bounding_box = stream.read_bool()
|
||
|
self.render_nation_crest = stream.read_bool()
|
||
|
self.render_guild_crest = stream.read_bool()
|
||
|
self.render_bumped = stream.read_bool()
|
||
|
self.render_vp_active = stream.read_bool()
|
||
|
if self.render_vp_active:
|
||
|
self.render_vp_name = stream.read_string()
|
||
|
num_params = stream.read_dword()
|
||
|
self.render_vp_params = [
|
||
|
[
|
||
|
stream.read_dword(),
|
||
|
stream.read_float(),
|
||
|
stream.read_float(),
|
||
|
stream.read_float(),
|
||
|
stream.read_float(),
|
||
|
] for _ in range(num_params)
|
||
|
]
|
||
|
self.render_has_light_effects = stream.read_bool()
|
||
|
if self.render_has_light_effects:
|
||
|
num_effects = stream.read_dword()
|
||
|
self.render_light_effects = [ArcLight() for _ in range(num_effects)]
|
||
|
for effect in self.render_light_effects:
|
||
|
effect.load_binary(stream)
|
||
|
|
||
|
def save_binary(self, stream: ResStream):
|
||
|
self.render_template.save_binary(stream)
|
||
|
stream.write_string(self.render_target_bone)
|
||
|
stream.write_tuple(self.render_scale)
|
||
|
stream.write_dword(self.render_has_loc)
|
||
|
if self.render_has_loc:
|
||
|
stream.write_tuple(self.render_loc)
|
||
|
stream.write_dword(len(self.render_children))
|
||
|
for child in self.render_children:
|
||
|
stream.write_qword(child)
|
||
|
stream.write_bool(self.render_has_texture_set)
|
||
|
if self.render_has_texture_set:
|
||
|
stream.write_dword(len(self.render_texture_set))
|
||
|
for texture in self.render_texture_set:
|
||
|
texture.save_binary(stream)
|
||
|
stream.write_bool(self.render_collides)
|
||
|
stream.write_bool(self.render_calculate_bounding_box)
|
||
|
stream.write_bool(self.render_nation_crest)
|
||
|
stream.write_bool(self.render_guild_crest)
|
||
|
stream.write_bool(self.render_bumped)
|
||
|
stream.write_bool(self.render_vp_active)
|
||
|
if self.render_vp_active:
|
||
|
stream.write_string(self.render_vp_name)
|
||
|
|
||
|
stream.write_dword(len(self.render_vp_params))
|
||
|
for param in self.render_vp_params:
|
||
|
stream.write_dword(param[0])
|
||
|
stream.write_float(param[1])
|
||
|
stream.write_float(param[2])
|
||
|
stream.write_float(param[3])
|
||
|
stream.write_float(param[4])
|
||
|
stream.write_bool(self.render_has_light_effects)
|
||
|
if self.render_has_light_effects:
|
||
|
stream.write_dword(len(self.render_light_effects))
|
||
|
for effect in self.render_light_effects:
|
||
|
effect.save_binary(stream)
|
||
|
|
||
|
def load_json(self, data):
|
||
|
self.render_template = ArcRenderTemplate()
|
||
|
self.render_template.load_json(data['render_template'])
|
||
|
self.render_target_bone = data['render_target_bone']
|
||
|
self.render_scale = data['render_scale']
|
||
|
self.render_has_loc = data['render_has_loc']
|
||
|
if self.render_has_loc:
|
||
|
self.render_loc = data['render_loc']
|
||
|
self.render_children = data['render_children']
|
||
|
self.render_has_texture_set = data['render_has_texture_set']
|
||
|
if self.render_has_texture_set:
|
||
|
self.render_texture_set = []
|
||
|
for texture_data in data['render_texture_set']:
|
||
|
texture = ArcTextureSet()
|
||
|
texture.load_json(texture_data)
|
||
|
self.render_texture_set.append(texture)
|
||
|
self.render_collides = data['render_collides']
|
||
|
self.render_calculate_bounding_box = data['render_calculate_bounding_box']
|
||
|
self.render_nation_crest = data['render_nation_crest']
|
||
|
self.render_guild_crest = data['render_guild_crest']
|
||
|
self.render_bumped = data['render_bumped']
|
||
|
self.render_vp_active = data['render_vp_active']
|
||
|
if self.render_vp_active:
|
||
|
self.render_vp_name = data['render_vp_name']
|
||
|
self.render_vp_params = data['render_vp_params']
|
||
|
self.render_has_light_effects = data['render_has_light_effects']
|
||
|
if self.render_has_light_effects:
|
||
|
self.render_light_effects = []
|
||
|
for effect_data in data['render_light_effects']:
|
||
|
effect = ArcLight()
|
||
|
effect.load_json(effect_data)
|
||
|
self.render_light_effects.append(effect)
|
||
|
|
||
|
def save_json(self):
|
||
|
data = OrderedDict()
|
||
|
data['render_template'] = self.render_template.save_json()
|
||
|
data['render_target_bone'] = self.render_target_bone
|
||
|
data['render_scale'] = self.render_scale
|
||
|
data['render_has_loc'] = self.render_has_loc
|
||
|
if self.render_has_loc:
|
||
|
data['render_loc'] = self.render_loc
|
||
|
data['render_children'] = self.render_children
|
||
|
data['render_has_texture_set'] = self.render_has_texture_set
|
||
|
if self.render_has_texture_set:
|
||
|
data['render_texture_set'] = []
|
||
|
for texture in self.render_texture_set:
|
||
|
data['render_texture_set'].append(texture.save_json())
|
||
|
data['render_collides'] = self.render_collides
|
||
|
data['render_calculate_bounding_box'] = self.render_calculate_bounding_box
|
||
|
data['render_nation_crest'] = self.render_nation_crest
|
||
|
data['render_guild_crest'] = self.render_guild_crest
|
||
|
data['render_bumped'] = self.render_bumped
|
||
|
data['render_vp_active'] = self.render_vp_active
|
||
|
if self.render_vp_active:
|
||
|
data['render_vp_name'] = self.render_vp_name
|
||
|
data['render_vp_params'] = self.render_vp_params
|
||
|
data['render_has_light_effects'] = self.render_has_light_effects
|
||
|
if self.render_has_light_effects:
|
||
|
data['render_light_effects'] = []
|
||
|
for effect in self.render_light_effects:
|
||
|
data['render_light_effects'].append(effect.save_json())
|
||
|
return data
|