X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=blender_export.py;h=1646d83a252a3e5f6469ca05a407b080c831e521;hb=137d40d96fe923600d8378b8e138e3c276f27ff4;hp=70bb5ef494d9db15433bd6159e945fde98a4bdb5;hpb=8a31c1ffcb632b9b6d1702332f0d75d609c0a87b;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/blender_export.py b/blender_export.py index 70bb5ef..1646d83 100644 --- a/blender_export.py +++ b/blender_export.py @@ -37,14 +37,14 @@ sr_entity_list = [ ('ent_menuitem', 'Menu Item', '', 15 ), ('ent_worldinfo', 'World Info', '', 16 ), ('ent_ccmd', 'CCmd', '', 17 ), - ('ent_challenge', 'Challenge', '', 18 ), - ('ent_unlock', 'Unlockable', '', 19 ), + ('ent_objective', 'Objective', '', 18 ), + ('ent_challenge', 'Challenge', '', 19 ), ('ent_relay', 'Relay', '', 20 ) ] -MDL_VERSION_NR = 102 -SR_TRIGGERABLE = [ 'ent_audio', 'ent_ccmd', 'ent_gate', 'ent_unlock', \ - 'ent_relay', 'ent_skateshop', 'ent_challenge' ] +MDL_VERSION_NR = 103 +SR_TRIGGERABLE = [ 'ent_audio', 'ent_ccmd', 'ent_gate', 'ent_challenge', \ + 'ent_relay', 'ent_skateshop', 'ent_objective', 'ent_route' ] def get_entity_enum_id( alias ): #{ @@ -263,7 +263,11 @@ class ent_route(Structure): ("factive",c_float), ("board_transform",(c_float*3)*4), ("sm",mdl_submesh), - ("latest_pass",c_double)] + ("latest_pass",c_double), + ("id_camera",c_uint32), # v103+ + ] + + sr_functions = { 0: 'view' } #} class ent_water(Structure): @@ -397,6 +401,10 @@ class ent_swspreview(Structure): # Menu # ----------------------------------------------------------------- +class ent_menuitem_visual(Structure): +#{ + _fields_ = [("pstr_name",c_uint32)] +#} class ent_menuitem_slider(Structure): #{ _fields_ = [("id_min",c_uint32), @@ -406,7 +414,8 @@ class ent_menuitem_slider(Structure): #} class ent_menuitem_button(Structure): #{ - _fields_ = [("pstr",c_uint32)] + _fields_ = [("pstr",c_uint32), + ("stack_behaviour",c_uint32)] #} class ent_menuitem_checkmark(Structure): #{ @@ -420,12 +429,19 @@ class ent_menuitem_page(Structure): ("id_entrypoint",c_uint32), ("id_viewpoint",c_uint32)] #} +class ent_menuitem_binding(Structure): +#{ + _fields_ = [("pstr_bind",c_uint32), + ("font_variant",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)] + ("page",ent_menuitem_page), + ("visual",ent_menuitem_visual), + ("binding",ent_menuitem_binding)] #} class ent_menuitem(Structure): #{ @@ -459,7 +475,7 @@ class ent_ccmd(Structure): _fields_ = [("pstr_command",c_uint32)] #} -class ent_challenge(Structure):#{ +class ent_objective(Structure):#{ _fields_ = [("transform",mdl_transform), ("submesh_start",c_uint32), ("submesh_count",c_uint32), ("flags",c_uint32), @@ -470,17 +486,23 @@ class ent_challenge(Structure):#{ ("time_limit",c_float)] sr_functions = { 0: 'trigger', - 1: 'start_challenge', 2: 'show', 3: 'hide' } #} -class ent_unlock(Structure):#{ - _fields_ = [("pstr_alias",c_uint32), +class ent_challenge(Structure):#{ + _fields_ = [("transform",mdl_transform), + ("pstr_alias",c_uint32), + ("flags",c_uint32), ("target",c_uint32), ("target_event",c_uint32), - ("status",c_uint32)] - sr_functions = { 0: 'unlock' } + ("reset",c_uint32), + ("reset_event",c_uint32), + ("first",c_uint32), + ("camera",c_uint32), + ("status",c_uint32)] #runtime + sr_functions = { 0: 'unlock', + 1: 'view/reset' } #} class ent_relay(Structure):#{ @@ -1310,9 +1332,14 @@ def sr_compile_menus( collection ): sr_compile_mesh_internal( obj ) #} - if item.type == 1 or item.type == 2:#{ + if item.type == 1 or item.type == 2 or item.type == 7:#{ item_button = item._anonymous_union.button item_button.pstr = sr_compile_string( obj_data.string ) + item_button.stack_behaviour = int( obj_data.stack_behaviour ) + #} + elif item.type == 0:#{ + item_visual = item._anonymous_union.visual + item_visual.pstr_name = sr_compile_string( obj_data.string ) #} elif item.type == 3:#{ item_checkmark = item._anonymous_union.checkmark @@ -1336,6 +1363,11 @@ def sr_compile_menus( collection ): item_page.id_entrypoint = sr_entity_id( obj_data.newloc ) item_page.id_viewpoint = sr_entity_id( obj_data.camera ) #} + elif item.type == 6:#{ + item_binding = item._anonymous_union.binding + item_binding.pstr_bind = sr_compile_string( obj_data.string ) + item_binding.font_variant = obj_data.font_variant + #} if obj_data.link0: item.id_links[0] = sr_entity_id( obj_data.link0 ) @@ -1625,7 +1657,7 @@ def sr_compile( collection ): if ent_type == 'ent_font': continue if ent_type == 'ent_font_variant': continue if ent_type == 'ent_menuitem': continue - if ent_type == 'ent_challenge': continue + if ent_type == 'ent_objective': continue #TODO: This is messy. if ent_type == 'ent_gate':#{ @@ -1855,31 +1887,38 @@ def sr_compile( collection ): ccmd.pstr_command = sr_compile_string( obj_data.command ) sr_ent_push( ccmd ) #} + elif ent_type == 'ent_objective':#{ + objective = ent_objective() + obj_data = obj.SR_data.ent_objective[0] + objective.id_next = sr_entity_id( obj_data.proxima ) + objective.id_win = sr_entity_id( obj_data.target ) + objective.win_event = obj_data.target_event + objective.filter = int(obj_data.filtrar) + objective.filter2 = 0 + objective.time_limit = obj_data.time_limit + + compile_obj_transform( obj, objective.transform ) + objective.submesh_start, objective.submesh_count, _ = \ + sr_compile_mesh_internal( obj ) + + sr_ent_push( objective ) + #} elif ent_type == 'ent_challenge':#{ challenge = ent_challenge() obj_data = obj.SR_data.ent_challenge[0] - challenge.id_next = sr_entity_id( obj_data.proxima ) - challenge.id_win = sr_entity_id( obj_data.target ) - challenge.win_event = obj_data.target_event - challenge.filter = int(obj_data.filtrar) - challenge.filter2 = 0 - challenge.time_limit = obj_data.time_limit - compile_obj_transform( obj, challenge.transform ) - challenge.submesh_start, challenge.submesh_count, _ = \ - sr_compile_mesh_internal( obj ) - + challenge.pstr_alias = sr_compile_string( obj_data.alias ) + challenge.target = sr_entity_id( obj_data.target ) + challenge.target_event = obj_data.target_event + challenge.reset = sr_entity_id( obj_data.reset ) + challenge.reset_event = obj_data.reset_event + challenge.first = sr_entity_id( obj_data.first ) + challenge.flags = 0x00 + challenge.camera = sr_entity_id( obj_data.camera ) + if obj_data.time_limit: challenge.flags |= 0x01 + challenge.status = 0 sr_ent_push( challenge ) #} - elif ent_type == 'ent_unlock':#{ - unlock = ent_unlock() - obj_data = obj.SR_data.ent_unlock[0] - unlock.pstr_alias = sr_compile_string( obj_data.alias ) - unlock.target = sr_entity_id( obj_data.target ) - unlock.target_event = obj_data.target_event - unlock.status = 0 - sr_ent_push( unlock ) - #} elif ent_type == 'ent_relay':#{ relay = ent_relay() obj_data = obj.SR_data.ent_relay[0] @@ -1954,6 +1993,7 @@ def sr_compile( collection ): route.pstr_name = sr_compile_string( obj_data.alias ) route.checkpoints_start = checkpoint_count route.checkpoints_count = 0 + route.id_camera = sr_entity_id( obj_data.cam ) for ci in range(3): route.colour[ci] = obj_data.colour[ci] @@ -2135,7 +2175,7 @@ class SR_SCENE_SETTINGS(bpy.types.PropertyGroup): #{ use_hidden: bpy.props.BoolProperty( name="use hidden", default=False ) export_dir: bpy.props.StringProperty( name="Export Dir", subtype='DIR_PATH' ) - gizmos: bpy.props.BoolProperty( name="Draw Gizmos", default=True ) + gizmos: bpy.props.BoolProperty( name="Draw Gizmos", default=False ) panel: bpy.props.EnumProperty( name='Panel', @@ -2854,11 +2894,16 @@ class SR_OBJECT_ENT_ROUTE(bpy.types.PropertyGroup): name="Alias",\ default="Untitled Course") + cam: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="Viewpoint", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_camera'])) + @staticmethod def sr_inspector( layout, data ): #{ layout.prop( data[0], 'alias' ) layout.prop( data[0], 'colour' ) + layout.prop( data[0], 'cam' ) layout.label( text='Checkpoints' ) layout.template_list('SR_UL_ROUTE_NODE_LIST', 'Checkpoints', \ @@ -3107,6 +3152,10 @@ class SR_OBJECT_ENT_MENU_ITEM(bpy.types.PropertyGroup): newloc: bpy.props.PointerProperty( \ type=bpy.types.Object, name="New location", \ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem'])) + stack_behaviour: bpy.props.EnumProperty( name='Stack Behaviour', + items=[('0','append',''), + ('1','replace','')]) + camera: bpy.props.PointerProperty( \ type=bpy.types.Object, name="Camera", \ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_camera'])) @@ -3125,6 +3174,8 @@ class SR_OBJECT_ENT_MENU_ITEM(bpy.types.PropertyGroup): type=bpy.types.Object, name="Checked", \ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_menuitem'])) + font_variant: bpy.props.IntProperty( name="Font Variant" ) + string: bpy.props.StringProperty( name="String" ) tipo: bpy.props.EnumProperty( name='Type', items=[('0','visual',''), @@ -3132,7 +3183,9 @@ class SR_OBJECT_ENT_MENU_ITEM(bpy.types.PropertyGroup): ('2','page button',''), ('3','toggle', ''), ('4','slider',''), - ('5','page','')]) + ('5','page',''), + ('6','binding',''), + ('7','visual(no colourize)','')]) @staticmethod def sr_inspector( layout, data ): @@ -3141,7 +3194,8 @@ class SR_OBJECT_ENT_MENU_ITEM(bpy.types.PropertyGroup): box = layout.box() box.prop( data, 'tipo' ) - if data.tipo == '0':#{ + if data.tipo == '0' or data.tipo == '7':#{ + box.prop( data, 'string', text='Name' ) return #} elif data.tipo == '1':#{ @@ -3149,7 +3203,7 @@ class SR_OBJECT_ENT_MENU_ITEM(bpy.types.PropertyGroup): #} elif data.tipo == '2':#{ box.prop( data, 'string', text='Page' ) - box.prop( data, 'newloc' ) + box.prop( data, 'stack_behaviour' ) #} elif data.tipo == '3':#{ box.prop( data, 'string', text='Data (i32)' ) @@ -3172,6 +3226,11 @@ class SR_OBJECT_ENT_MENU_ITEM(bpy.types.PropertyGroup): box.prop( data, 'camera', text='Viewpoint' ) return #} + elif data.tipo == '6':#{ + box.prop( data, 'string', text='ID' ) + box.prop( data, 'font_variant' ) + return + #} box = box.box() box.label( text="Links" ) @@ -3195,10 +3254,10 @@ class SR_OBJECT_ENT_CCMD(bpy.types.PropertyGroup): command: bpy.props.StringProperty(name="Command Line") #} -class SR_OBJECT_ENT_CHALLENGE(bpy.types.PropertyGroup):#{ +class SR_OBJECT_ENT_OBJECTIVE(bpy.types.PropertyGroup):#{ proxima: bpy.props.PointerProperty( \ type=bpy.types.Object, name="Next", \ - poll=lambda self,obj: sr_filter_ent_type(obj,['ent_challenge'])) + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_objective'])) target: bpy.props.PointerProperty( \ type=bpy.types.Object, name="Win", \ poll=lambda self,obj: sr_filter_ent_type(obj,SR_TRIGGERABLE)) @@ -3216,7 +3275,8 @@ class SR_OBJECT_ENT_CHALLENGE(bpy.types.PropertyGroup):#{ (str(0x20),'grind_truck_any',''), (str(0x40),'grind_board_any',''), (str(0x20|0x40),'grind_any',''), - (str(0x80),'footplant','') + (str(0x80),'footplant',''), + (str(0x100),'passthrough',''), ]) @staticmethod @@ -3228,17 +3288,37 @@ class SR_OBJECT_ENT_CHALLENGE(bpy.types.PropertyGroup):#{ #} #} -class SR_OBJECT_ENT_UNLOCK(bpy.types.PropertyGroup):#{ +class SR_OBJECT_ENT_CHALLENGE(bpy.types.PropertyGroup):#{ alias: bpy.props.StringProperty( name="Alias" ) + target: bpy.props.PointerProperty( \ - type=bpy.types.Object, name="Target", \ + type=bpy.types.Object, name="On Complete", \ poll=lambda self,obj: sr_filter_ent_type(obj,SR_TRIGGERABLE)) target_event: bpy.props.IntProperty( name="Event/Method" ) + reset: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="On Reset", \ + poll=lambda self,obj: sr_filter_ent_type(obj,SR_TRIGGERABLE)) + reset_event: bpy.props.IntProperty( name="Event/Method" ) + + time_limit: bpy.props.BoolProperty( name="Time Limit" ) + + first: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="First Objective", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_objective'])) + + camera: bpy.props.PointerProperty( \ + type=bpy.types.Object, name="Camera", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_camera'])) + @staticmethod def sr_inspector( layout, data ):#{ layout.prop( data[0], 'alias' ) + layout.prop( data[0], 'camera' ) + layout.prop( data[0], 'first' ) + layout.prop( data[0], 'time_limit' ) SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target' ) + SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'reset' ) #} #} @@ -3287,8 +3367,8 @@ class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup): ent_menuitem: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_MENU_ITEM) ent_worldinfo: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_WORLD_INFO) ent_ccmd: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_CCMD) + ent_objective: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_OBJECTIVE) ent_challenge: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_CHALLENGE) - ent_unlock: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_UNLOCK) ent_relay: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_RELAY) ent_type: bpy.props.EnumProperty( @@ -3610,7 +3690,7 @@ def cv_tangent_basis( n, tx, ty ): # Draw coloured arrow # -def cv_draw_arrow( p0, p1, c0, size=0.25 ): +def cv_draw_arrow( p0, p1, c0, size=0.25, outline=True ): #{ global cv_view_verts, cv_view_colours @@ -3621,10 +3701,26 @@ def cv_draw_arrow( p0, p1, c0, size=0.25 ): tx = Vector((1,0,0)) ty = Vector((1,0,0)) cv_tangent_basis( n, tx, ty ) - + tx *= 0.5 + ty *= 0.5 + + if outline:#{ + cv_draw_lines() + gpu.state.line_width_set(1.0) + #} + cv_view_verts += [p0,p1, midpt+(tx-n)*size,midpt, midpt+(-tx-n)*size,midpt ] cv_view_colours += [c0,c0,c0,c0,c0,c0] - #cv_draw_lines() + cv_draw_lines() + + if outline:#{ + gpu.state.line_width_set(3.0) + cv_view_verts += [p0,p1,midpt+(tx-n)*size,midpt,midpt+(-tx-n)*size,midpt] + b0 = (0,0,0) + cv_view_colours += [b0,b0,b0,b0,b0,b0] + cv_draw_lines() + gpu.state.line_width_set(2.0) + #} #} def cv_draw_line_dotted( p0, p1, c0, dots=10 ): @@ -3947,17 +4043,17 @@ def cv_ent_volume( obj ): data = obj.SR_data.ent_volume[0] if data.subtype == '0':#{ - cv_draw_ucube( obj.matrix_world, (0,1,0) ) + cv_draw_ucube( obj.matrix_world, (0,1,0), Vector((0.99,0.99,0.99)) ) if data.target:#{ - cv_draw_arrow( obj.location, data.target.location, (0,1,0) ) + cv_draw_arrow( obj.location, data.target.location, (1,1,1) ) #} #} elif data.subtype == '1':#{ cv_draw_ucube( obj.matrix_world, (1,1,0) ) if data.target:#{ - cv_draw_arrow( obj.location, data.target.location, (1,1,0) ) + cv_draw_arrow( obj.location, data.target.location, (1,1,1) ) #} #} #} @@ -4176,14 +4272,14 @@ def cv_draw_route( route, dij ): path = solve_graph( dij, gi.name, gj.name ) if path:#{ - cv_draw_arrow(gi.location,dij.points[path[0]],cc,1.5) - cv_draw_arrow(dij.points[path[len(path)-1]],gj.location,cc,1.5) + cv_draw_arrow(gi.location,dij.points[path[0]],cc,1.5,False) + cv_draw_arrow(dij.points[path[len(path)-1]],gj.location,cc,1.5,False) for j in range(len(path)-1):#{ i0 = path[j] i1 = path[j+1] o0 = dij.points[ i0 ] o1 = dij.points[ i1 ] - cv_draw_arrow(o0,o1,cc,1.5) + cv_draw_arrow(o0,o1,cc,1.5,False) #} #} else:#{ @@ -4203,7 +4299,7 @@ def cv_draw():#{ cv_view_colours = [] cv_view_shader.bind() - gpu.state.depth_mask_set(False) + gpu.state.depth_mask_set(True) gpu.state.line_width_set(2.0) gpu.state.face_culling_set('BACK') gpu.state.depth_test_set('LESS') @@ -4235,29 +4331,50 @@ def cv_draw():#{ elif ent_type == 'ent_volume':#{ cv_ent_volume( obj ) #} - elif ent_type == 'ent_challenge':#{ - data = obj.SR_data.ent_challenge[0] + elif ent_type == 'ent_objective':#{ + data = obj.SR_data.ent_objective[0] if data.proxima:#{ - cv_draw_arrow( obj.location, data.proxima.location, (0,0.2,1.0) ) + cv_draw_arrow( obj.location, data.proxima.location, (1,0.6,0.2) ) #} if data.target: - cv_draw_arrow( obj.location, data.target.location, (0,1.0,0.0) ) + cv_draw_arrow( obj.location, data.target.location, (1,1,1) ) #} elif ent_type == 'ent_relay':#{ data = obj.SR_data.ent_relay[0] if data.target0: - cv_draw_arrow( obj.location, data.target0.location, (0,1,0) ) + cv_draw_arrow( obj.location, data.target0.location, (1,1,1) ) if data.target1: - cv_draw_arrow( obj.location, data.target1.location, (0,1,0) ) + cv_draw_arrow( obj.location, data.target1.location, (1,1,1) ) if data.target2: - cv_draw_arrow( obj.location, data.target2.location, (0,1,0) ) + cv_draw_arrow( obj.location, data.target2.location, (1,1,1) ) if data.target3: - cv_draw_arrow( obj.location, data.target3.location, (0,1,0) ) + cv_draw_arrow( obj.location, data.target3.location, (1,1,1) ) #} - elif ent_type == 'ent_unlock':#{ - data = obj.SR_data.ent_unlock[0] + elif ent_type == 'ent_challenge':#{ + data = obj.SR_data.ent_challenge[0] if data.target: - cv_draw_arrow( obj.location, data.target.location, (0,1.0,0.0) ) + cv_draw_arrow( obj.location, data.target.location, (1,1,1) ) + if data.reset: + cv_draw_arrow( obj.location, data.reset.location, (0.9,0,0) ) + if data.first: + cv_draw_arrow( obj.location, data.first.location, (1,0.6,0.2) ) + + cc1 = (0.4,0.3,0.2) + info_cu = Vector((1.2,0.01,0.72))*0.5 + info_co = Vector((0.0,0.0,0.72))*0.5 + cv_draw_ucube( obj.matrix_world, cc1, info_cu, info_co) + if data.camera: + cv_draw_line_dotted( obj.location, data.camera.location, (1,1,1)) + + vs = [Vector((-0.2,0.0,0.10)),Vector((-0.2,0.0,0.62)),\ + Vector(( 0.2,0.0,0.62)),Vector((-0.2,0.0,0.30)),\ + Vector(( 0.1,0.0,0.30))] + for v in range(len(vs)):#{ + vs[v] = obj.matrix_world @ vs[v] + #} + + cv_view_verts += [vs[0],vs[1],vs[1],vs[2],vs[3],vs[4]] + cv_view_colours += [cc1,cc1,cc1,cc1,cc1,cc1] #} elif ent_type == 'ent_audio':#{ if obj.SR_data.ent_audio[0].flag_3d: @@ -4323,6 +4440,11 @@ def cv_draw():#{ info_cu = Vector((1.2,0.01,0.3))*0.5 info_co = Vector((0.0,0.0,0.0))*0.5 #} + elif data.tipo == '3':#{ + rack = None + display = None + info = None + #} if rack: cv_draw_ucube( rack.matrix_world, cc, rack_cu, rack_co ) @@ -4474,7 +4596,8 @@ classes = [ SR_INTERFACE, SR_MATERIAL_PANEL,\ SR_OBJECT_ENT_FONT,SR_OBJECT_ENT_TRAFFIC,SR_OBJECT_ENT_SKATESHOP,\ SR_OBJECT_ENT_WORKSHOP_PREVIEW,SR_OBJECT_ENT_MENU_ITEM,\ SR_OBJECT_ENT_WORLD_INFO,SR_OBJECT_ENT_CCMD,\ - SR_OBJECT_ENT_CHALLENGE,SR_OBJECT_ENT_UNLOCK,SR_OBJECT_ENT_RELAY,\ + SR_OBJECT_ENT_OBJECTIVE,SR_OBJECT_ENT_CHALLENGE,\ + SR_OBJECT_ENT_RELAY,\ \ SR_OBJECT_PROPERTIES, SR_LIGHT_PROPERTIES, SR_BONE_PROPERTIES, SR_MESH_PROPERTIES, SR_MATERIAL_PROPERTIES \