X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=blender_export.py;h=ede1106b484ec22db611381473a47cb9cb501395;hb=9d0ff08fef8507613586856de7ce25d43704db92;hp=7c61247c67aa8d902c55f33b5e7245b6b5eb7d82;hpb=02e5027d274fc66fecca0572d0998e2c562da7a7;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/blender_export.py b/blender_export.py index 7c61247..ede1106 100644 --- a/blender_export.py +++ b/blender_export.py @@ -32,7 +32,8 @@ sr_entity_list = [ ('ent_traffic', 'Traffic Model', '', 11 ), ('ent_skateshop', 'Skate Shop', '', 12 ), ('ent_camera', 'Camera', '', 13 ), - ('ent_swspreview', 'Workshop Preview', '', 14 ) + ('ent_swspreview', 'Workshop Preview', '', 14 ), + ('ent_menuitem', 'Menu Item', '', 15 ) ] def get_entity_enum_id( alias ): @@ -355,6 +356,51 @@ class ent_swspreview(Structure): ("id_display1",c_uint32)] #} +class ent_menuitem_slider(Structure): +#{ + _fields_ = [("id_min",c_uint32), + ("id_max",c_uint32), + ("id_handle",c_uint32), + ("pstr_data",c_uint32)] +#} + +class ent_menuitem_button(Structure): +#{ + _fields_ = [("pstr",c_uint32)] +#} + +class ent_menuitem_checkmark(Structure): +#{ + _fields_ = [("id_check",c_uint32), + ("pstr_data",c_uint32)] +#} + +class ent_menuitem_page(Structure): +#{ + _fields_ = [("pstr_name",c_uint32), + ("id_entrypoint",c_uint32), + ("id_viewpoint",c_uint32)] +#} + +class ent_menuitem_anon_union(Union): +#{ + _fields_ = [("slider",ent_menuitem_slider), + ("button",ent_menuitem_button), + ("checkmark",ent_menuitem_checkmark), + ("page",ent_menuitem_page)] +#} + +class ent_menuitem(Structure): +#{ + _fields_ = [("type",c_uint32), ("groups",c_uint32), + ("id_links",c_uint32*4), + #-- TODO: Refactor this into a simple mesh structure + ("transform",mdl_transform), + ("submesh_start",c_uint32),("submesh_count",c_uint32), + #-- end + ("_anonymous_union", ent_menuitem_anon_union)] +#} + class ent_camera(Structure): #{ _fields_ = [("transform",mdl_transform), @@ -387,7 +433,9 @@ def sr_filter_ent_type( obj, ent_types ): def compile_obj_transform( obj, transform ): #{ co = obj.matrix_world @ Vector((0,0,0)) - q = obj.matrix_local.to_quaternion() + + # This was changed from matrix_local on 09.05.23 + q = obj.matrix_world.to_quaternion() s = obj.scale # Setup transform @@ -434,6 +482,7 @@ def sr_compile_string( s ): index = len( sr_compile.string_data ) sr_compile.string_cache[s] = index + sr_compile.string_data.extend( c_uint32(hash_djb2(s)) ) sr_compile.string_data.extend( s.encode('utf-8') ) sr_compile.string_data.extend( b'\0' ) @@ -1098,6 +1147,70 @@ def sr_compile_fonts( collection ): #} #} +def sr_compile_menus( collection ): +#{ + print( "[SR] Compiling menus" ) + groups = [] + + for obj in collection.all_objects:#{ + if obj_ent_type(obj) != 'ent_menuitem': continue + obj_data = obj.SR_data.ent_menuitem[0] + + bitmask = 0x00000000 + + for col in obj.users_collection:#{ + name = col.name + if name not in groups: groups.append( name ) + bitmask |= (0x1 << groups.index(name)) + #} + + item = ent_menuitem() + item.type = int( obj_data.tipo ) + item.groups = bitmask + + compile_obj_transform( obj, item.transform ) + if obj.type == 'MESH':#{ + item.submesh_start, item.submesh_count, _ = \ + sr_compile_mesh_internal( obj ) + #} + + if item.type == 1 or item.type == 2:#{ + item_button = item._anonymous_union.button + item_button.string = sr_compile_string( obj_data.string ) + #} + elif item.type == 3:#{ + item_checkmark = item._anonymous_union.checkmark + item_checkmark.pstr_data = sr_compile_string( obj_data.string ) + item_checkmark.id_check = sr_entity_id( obj_data.checkmark ) + #} + elif item.type == 4:#{ + item_slider = item._anonymous_union.slider + item_slider.id_min = sr_entity_id( obj_data.slider_minloc ) + item_slider.id_max = sr_entity_id( obj_data.slider_maxloc ) + item_slider.id_handle = sr_entity_id( obj_data.slider_handle ) + #} + elif item.type == 5:#{ + item_page = item._anonymous_union.page + item_page.pstr_name = sr_compile_string( obj_data.string ) + item_page.id_entrypoint = sr_entity_id( obj_data.newloc ) + item_page.id_viewpoint = sr_entity_id( obj_data.camera ) + #} + + if obj_data.link0: + item.id_links[0] = sr_entity_id( obj_data.link0 ) + if obj_data.link1: + item.id_links[1] = sr_entity_id( obj_data.link1 ) + if item.type != 4:#{ + if obj_data.link2: + item.id_links[2] = sr_entity_id( obj_data.link2 ) + if obj_data.link3: + item.id_links[3] = sr_entity_id( obj_data.link3 ) + #} + + sr_ent_push( item ) + #} +#} + def sr_compile_armature( obj ): #{ node = mdl_armature() @@ -1290,6 +1403,15 @@ def sr_array_title( arr, name, count, size, offset ): arr.item_size = size #} +def hash_djb2(s): +#{ + picadillo = 5381 + for x in s:#{ + picadillo = (((picadillo << 5) + picadillo) + ord(x)) & 0xFFFFFFFF + #} + return picadillo +#} + def sr_compile( collection ): #{ print( F"[SR] compiler begin ({collection.name}.mdl)" ) @@ -1328,6 +1450,11 @@ def sr_compile( collection ): sr_compile.entities = {} sr_compile.entity_ids = {} + # begin + # ------------------------------------------------------- + + sr_compile_string( "null" ) + mesh_count = 0 for obj in collection.all_objects: #{ if obj.type == 'MESH':#{ @@ -1355,6 +1482,7 @@ def sr_compile( collection ): if ent_type == 'ent_traffic': continue if ent_type == 'ent_font': continue if ent_type == 'ent_font_variant': continue + if ent_type == 'ent_menuitem': continue #-------------------------- print( F'[SR] {i: 3}/{mesh_count} {obj.name:<40}', end='\r' ) @@ -1540,7 +1668,8 @@ def sr_compile( collection ): #} #} - sr_compile_fonts(collection) + sr_compile_menus( collection ) + sr_compile_fonts( collection ) def _children( col ):#{ yield col @@ -1639,7 +1768,7 @@ def sr_compile( collection ): compile_obj_transform( obj, traffic.transform ) traffic.submesh_start, traffic.submesh_count, _ = \ sr_compile_mesh_internal( obj ) - + # find best subsection graph_keys = list(dij.graph) @@ -1733,7 +1862,7 @@ def sr_compile( collection ): fp = open( path, "wb" ) header = mdl_header() - header.version = 100 + header.version = 101 sr_array_title( header.arrays, \ 'index', len(file_array_instructions), \ sizeof(mdl_array), header_size ) @@ -2664,6 +2793,99 @@ class SR_OBJECT_ENT_WORKSHOP_PREVIEW(bpy.types.PropertyGroup): poll=lambda self,obj: sr_filter_ent_type(obj,['ent_camera'])) #} +class SR_OBJECT_ENT_MENU_ITEM(bpy.types.PropertyGroup): +#{ + link0: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="Link 0", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem'])) + link1: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="Link 1", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem'])) + link2: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="Link 2", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem'])) + link3: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="Link 3", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem'])) + + newloc: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="New location", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem'])) + camera: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="Camera", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_camera'])) + + slider_minloc: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="Slider min", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_marker'])) + slider_maxloc: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="Slider max", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_marker'])) + slider_handle: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="Slider handle", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem'])) + + checkmark: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="Checked", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem'])) + + string: bpy.props.StringProperty( name="String" ) + tipo: bpy.props.EnumProperty( name='Type', + items=[('0','visual',''), + ('1','event button',''), + ('2','page button',''), + ('3','toggle', ''), + ('4','slider',''), + ('5','page','')]) + + @staticmethod + def sr_inspector( layout, data ): + #{ + data = data[0] + box = layout.box() + box.prop( data, 'tipo' ) + + if data.tipo == '0':#{ + return + #} + elif data.tipo == '1':#{ + box.prop( data, 'string', text='Event' ) + #} + elif data.tipo == '2':#{ + box.prop( data, 'string', text='Page' ) + box.prop( data, 'newloc' ) + #} + elif data.tipo == '3':#{ + box.prop( data, 'string', text='Data (i32)' ) + box.prop( data, 'checkmark' ) + #} + elif data.tipo == '4':#{ + box.prop( data, 'string', text='Data (f32)' ) + box.prop( data, 'slider_minloc' ) + box.prop( data, 'slider_maxloc' ) + box.prop( data, 'slider_handle' ) + box = box.box() + box.label( text="Links" ) + box.prop( data, 'link0', text='v0' ) + box.prop( data, 'link1', text='v1' ) + return + #} + elif data.tipo == '5':#{ + box.prop( data, 'string', text='Page Name' ) + box.prop( data, 'newloc', text='Entry Point' ) + box.prop( data, 'camera', text='Viewpoint' ) + return + #} + + box = box.box() + box.label( text="Links" ) + box.prop( data, 'link0' ) + box.prop( data, 'link1' ) + box.prop( data, 'link2' ) + box.prop( data, 'link3' ) + #} +#} + class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup): #{ ent_gate: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_GATE) @@ -2678,6 +2900,7 @@ class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup): ent_skateshop: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_SKATESHOP) ent_swspreview: \ bpy.props.CollectionProperty(type=SR_OBJECT_ENT_WORKSHOP_PREVIEW) + ent_menuitem: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_MENU_ITEM) ent_type: bpy.props.EnumProperty( name="Type", @@ -3665,6 +3888,77 @@ def cv_draw(): if display1: cv_draw_ucube(display1.matrix_world, cc1, display_cu, display_co) #} + elif ent_type == 'ent_menuitem':#{ + for i,col in enumerate(obj.users_collection):#{ + colour32 = hash_djb2( col.name ) + r = pow(((colour32 ) & 0xff) / 255.0, 2.2 ) + g = pow(((colour32>>8 ) & 0xff) / 255.0, 2.2 ) + b = pow(((colour32>>16) & 0xff) / 255.0, 2.2 ) + cc = (r,g,b) + vs = [None for _ in range(8)] + scale = i*0.02 + for j in range(8):#{ + v0 = Vector([(obj.bound_box[j][z]+\ + ((-1.0 if obj.bound_box[j][z]<0.0 else 1.0)*scale)) \ + for z in range(3)]) + vs[j] = obj.matrix_world @ v0 + #} + indices = [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),\ + (0,4),(1,5),(2,6),(3,7)] + for l in indices:#{ + v0 = vs[l[0]] + v1 = vs[l[1]] + cv_view_verts += [(v0[0],v0[1],v0[2])] + cv_view_verts += [(v1[0],v1[1],v1[2])] + cv_view_colours += [cc,cc] + #} + #} + cv_draw_lines() + cc = (1.0,1.0,1.0) + data = obj.SR_data.ent_menuitem[0] + if data.tipo == '4':#{ + if data.slider_minloc and data.slider_maxloc:#{ + v0 = data.slider_minloc.location + v1 = data.slider_maxloc.location + cv_draw_line( v0, v1, cc ) + #} + #} + + colour32 = hash_djb2(obj.name) + r = ((colour32 ) & 0xff) / 255.0 + g = ((colour32>>8 ) & 0xff) / 255.0 + b = ((colour32>>16) & 0xff) / 255.0 + cc = (r,g,b) + origin = obj.location + (Vector((r,g,b))*2.0-Vector((1.0,1.0,1.0)))\ + * 0.04 + + size = 0.01 + + if data.tipo != '0':#{ + if data.tipo == '4':#{ + if data.link0:#{ + cv_draw_arrow( origin, data.link0.location, cc, size ) + #} + if data.link1:#{ + cv_draw_arrow( origin, data.link1.location, cc, size ) + #} + #} + else:#{ + if data.link0:#{ + cv_draw_arrow( origin, data.link0.location, cc, size ) + #} + if data.link1:#{ + cv_draw_arrow( origin, data.link1.location, cc, size ) + #} + if data.link2:#{ + cv_draw_arrow( origin, data.link2.location, cc, size ) + #} + if data.link3:#{ + cv_draw_arrow( origin, data.link3.location, cc, size ) + #} + #} + #} + #} #} #} @@ -3699,7 +3993,7 @@ classes = [ SR_INTERFACE, SR_MATERIAL_PANEL,\ SR_OBJECT_ENT_GLYPH_ENTRY,\ SR_UL_FONT_VARIANT_LIST,SR_UL_FONT_GLYPH_LIST,\ SR_OBJECT_ENT_FONT,SR_OBJECT_ENT_TRAFFIC,SR_OBJECT_ENT_SKATESHOP,\ - SR_OBJECT_ENT_WORKSHOP_PREVIEW,\ + SR_OBJECT_ENT_WORKSHOP_PREVIEW,SR_OBJECT_ENT_MENU_ITEM,\ \ SR_OBJECT_PROPERTIES, SR_LIGHT_PROPERTIES, SR_BONE_PROPERTIES, SR_MESH_PROPERTIES, SR_MATERIAL_PROPERTIES \