('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 ):
("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),
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
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' )
#}
#}
+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()
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)" )
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':#{
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' )
#}
#}
- sr_compile_fonts(collection)
+ sr_compile_menus( collection )
+ sr_compile_fonts( collection )
def _children( col ):#{
yield col
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)
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 )
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)
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",
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 )
+ #}
+ #}
+ #}
+ #}
#}
#}
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 \