new menu start
authorhgn <hgodden00@gmail.com>
Sat, 13 May 2023 02:11:32 +0000 (03:11 +0100)
committerhgn <hgodden00@gmail.com>
Sat, 13 May 2023 02:11:32 +0000 (03:11 +0100)
23 files changed:
blender_export.py
ent_skateshop.c
entity.h
maps_src/mp_gridmap.mdl
maps_src/mp_mtzero.mdl
maps_src/mp_spawn.mdl
menu.h
model.h
models_src/boards/hgn_mountain.mdl [new file with mode: 0644]
models_src/boards/skaterift_fish.mdl
models_src/boards/skaterift_striped.mdl
models_src/ch_jordan.mdl
models_src/ch_new.mdl
models_src/ch_outlaw.mdl
models_src/rs_font.mdl
models_src/rs_gate.mdl
models_src/rs_menu.mdl
models_src/rs_scoretext.mdl
models_src/rs_skydome.mdl
player_common.c
player_skate.c
skaterift.c
world.h

index 7c61247c67aa8d902c55f33b5e7245b6b5eb7d82..ede1106b484ec22db611381473a47cb9cb501395 100644 (file)
@@ -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 \
index aeeaf702f76a11f6be6a175f3a07b853c44bab71..92e7660255ef06f813b800bb0f4e6dd79e4f8c96 100644 (file)
@@ -8,6 +8,7 @@
 #include "world.h"
 #include "player.h"
 #include "gui.h"
+#include "menu.h"
 
 /*
  * Checks string equality but does a hash check first
@@ -205,68 +206,8 @@ VG_STATIC void workshop_async_reg_update( void *data, u32 size )
    global_skateshop.registry_count = global_skateshop.t1_registry_count;
 }
 
-/*
- * Async thread which scans local files for boards, as well as scheduling 
- * synchronous calls to the workshop
- */
-VG_STATIC void workshop_scan_thread( void *_args )
+VG_STATIC void workshop_steam_scan(void)
 {
-   vg_linear_clear( vg_mem.scratch );
-
-   for( u32 i=0; i<global_skateshop.t1_registry_count; i++ ){
-      struct registry_board *reg = &global_skateshop.registry[i];
-      reg->state = k_registry_board_state_indexed_absent;
-   }
-
-   /*
-    * Local disk scan
-    */
-   vg_info( "Scanning models/boards/*.mdl\n" );
-   tinydir_dir dir;
-   tinydir_open( &dir, "models/boards" );
-
-   while( dir.has_next ){
-      tinydir_file file;
-      tinydir_readfile( &dir, &file );
-      
-      if( file.is_reg ){
-         u32 hash = vg_strdjb2( file.name );
-
-         for( u32 i=0; i<global_skateshop.t1_registry_count; i++ ){
-            struct registry_board *reg = &global_skateshop.registry[i];
-
-            if( const_str_eq( hash, file.name, reg->filename ) ){
-               reg->state = k_registry_board_state_indexed;
-               goto next_file;
-            }
-         }
-
-         if( global_skateshop.t1_registry_count == SKATESHOP_REGISTRY_MAX ){
-            vg_error( "You have too many boards installed!\n" );
-            break;
-         }
-
-         vg_info( "new listing!: %s\n", file.name );
-
-         struct registry_board *reg = 
-            &global_skateshop.registry[global_skateshop.t1_registry_count ++];
-
-         reg->cache_ptr = NULL;
-         vg_strncpy( file.name, reg->filename, 64, k_strncpy_always_add_null );
-         vg_strncpy( file.name, reg->workshop.title,
-                     64, k_strncpy_always_add_null );
-         reg->filename_hash = hash;
-         reg->workshop_id = 0;
-         reg->state = k_registry_board_state_indexed;
-         reg->workshop.author = 0;
-         strcpy( reg->workshop.author_name, "custom" );
-      }
-
-next_file: tinydir_next( &dir );
-   }
-
-   tinydir_close(&dir);
-
    /*
     * Steam workshop scan
     */
@@ -331,6 +272,71 @@ next_file: tinydir_next( &dir );
 
 next_file_workshop:;
    }
+}
+
+/*
+ * Async thread which scans local files for boards, as well as scheduling 
+ * synchronous calls to the workshop
+ */
+VG_STATIC void workshop_scan_thread( void *_args )
+{
+   vg_linear_clear( vg_mem.scratch );
+
+   for( u32 i=0; i<global_skateshop.t1_registry_count; i++ ){
+      struct registry_board *reg = &global_skateshop.registry[i];
+      reg->state = k_registry_board_state_indexed_absent;
+   }
+
+   /*
+    * Local disk scan
+    */
+   vg_info( "Scanning models/boards/*.mdl\n" );
+   tinydir_dir dir;
+   tinydir_open( &dir, "models/boards" );
+
+   while( dir.has_next ){
+      tinydir_file file;
+      tinydir_readfile( &dir, &file );
+      
+      if( file.is_reg ){
+         u32 hash = vg_strdjb2( file.name );
+
+         for( u32 i=0; i<global_skateshop.t1_registry_count; i++ ){
+            struct registry_board *reg = &global_skateshop.registry[i];
+
+            if( const_str_eq( hash, file.name, reg->filename ) ){
+               reg->state = k_registry_board_state_indexed;
+               goto next_file;
+            }
+         }
+
+         if( global_skateshop.t1_registry_count == SKATESHOP_REGISTRY_MAX ){
+            vg_error( "You have too many boards installed!\n" );
+            break;
+         }
+
+         vg_info( "new listing!: %s\n", file.name );
+
+         struct registry_board *reg = 
+            &global_skateshop.registry[global_skateshop.t1_registry_count ++];
+
+         reg->cache_ptr = NULL;
+         vg_strncpy( file.name, reg->filename, 64, k_strncpy_always_add_null );
+         vg_strncpy( file.name, reg->workshop.title,
+                     64, k_strncpy_always_add_null );
+         reg->filename_hash = hash;
+         reg->workshop_id = 0;
+         reg->state = k_registry_board_state_indexed;
+         reg->workshop.author = 0;
+         strcpy( reg->workshop.author_name, "custom" );
+      }
+
+next_file: tinydir_next( &dir );
+   }
+
+   tinydir_close(&dir);
+
+   if( steam_ready ) workshop_steam_scan();
    
    vg_async_call( workshop_async_reg_update, NULL, 0 );
    vg_async_stall();
@@ -684,6 +690,8 @@ VG_STATIC void ent_skateshop_call( world_instance *world, ent_call *call )
    ent_skateshop *shop = mdl_arritm( &world->ent_skateshop, index );
    vg_info( "skateshop_call\n" );
 
+   if( menu.active ) return;
+
    if( call->function == k_ent_function_trigger ){
       if( localplayer.subsystem != k_player_subsystem_walk ){
          return;
@@ -692,6 +700,7 @@ VG_STATIC void ent_skateshop_call( world_instance *world, ent_call *call )
       vg_info( "Entering skateshop\n" );
 
       localplayer.immobile = 1;
+      menu.disable_open = 1;
       global_skateshop.active = 1;
 
       v3_zero( localplayer.rb.v );
@@ -712,6 +721,7 @@ VG_STATIC void global_skateshop_exit(void)
    vg_info( "exit skateshop\n" );
    localplayer.immobile = 0;
    global_skateshop.active = 0;
+   menu.disable_open = 0;
    srinput.ignore_input_frames = 2;
 }
 
index 56938ce0ce25ca87485d57b3378067e81445b60b..6e30ef219ec96a5b0080eec52fe2e9d7f18dec9f 100644 (file)
--- a/entity.h
+++ b/entity.h
@@ -40,7 +40,8 @@ enum entity_alias{
    k_ent_traffic     = 11,
    k_ent_skateshop   = 12,
    k_ent_camera      = 13,
-   k_ent_swspreview  = 14
+   k_ent_swspreview  = 14,
+   k_ent_menuitem    = 15
 };
 
 static u32 mdl_entity_id_type( u32 entity_id )
@@ -242,6 +243,52 @@ struct ent_camera{
    float fov;
 };
 
+enum ent_menuitem_type{
+   k_ent_menuitem_type_visual       = 0,
+   k_ent_menuitem_type_event_button = 1,
+   k_ent_menuitem_type_page_button  = 2,
+   k_ent_menuitem_type_toggle       = 3,
+   k_ent_menuitem_type_slider       = 4,
+   k_ent_menuitem_type_page         = 5
+};
+
+typedef struct ent_menuitem ent_menuitem;
+struct ent_menuitem{
+   u32 type, groups, 
+       id_links[4];  /* ent_menuitem */
+
+   mdl_transform transform;
+   u32 submesh_start, submesh_count;
+
+   union{
+      struct{
+         u32 id_min,    /* ent_marker */
+             id_max,    /* . */
+             id_handle, /* ent_menuitem */
+             pstr_data;
+      }
+      slider;
+
+      struct{
+         u32 pstr;
+      }
+      button;
+
+      struct{
+         u32 id_check, /* ent_menuitem */
+             pstr_data;
+      }
+      checkmark;
+
+      struct{
+         u32 pstr_name, 
+             id_entrypoint,  /* ent_menuitem */
+             id_viewpoint;   /* ent_camera */
+      }
+      page;
+   };
+};
+
 VG_STATIC ent_marker *ent_find_marker( mdl_context *mdl,
                                        mdl_array_ptr *arr, const char *alias )
 {
@@ -297,6 +344,4 @@ struct ent_call{
 
 #include "world.h"
 
-VG_STATIC void entity_call( world_instance *world, ent_call *call );
-
 #endif /* ENTITY_H */
index 557de7d79567e0d79e47df990d847786c5ae5ddb..84df95832e6e36da18fe234998287048b3c8eae0 100644 (file)
Binary files a/maps_src/mp_gridmap.mdl and b/maps_src/mp_gridmap.mdl differ
index e2f8b9e52654cd6ddfbc0a2ed9f4b03f0ea4f1a0..df5243b55c91adde011e716b487c183415260b78 100644 (file)
Binary files a/maps_src/mp_mtzero.mdl and b/maps_src/mp_mtzero.mdl differ
index ca63a882f6d3d65acdddc440553f22cd86dbcf0a..9cdba1b924db46b605a4750b33bc5b92cf46e5cf 100644 (file)
Binary files a/maps_src/mp_spawn.mdl and b/maps_src/mp_spawn.mdl differ
diff --git a/menu.h b/menu.h
index 6612494a8492a899c8733878b68d32a4599459ec..f15b26b76836a105718893d5affc79ceb27ecf07 100644 (file)
--- a/menu.h
+++ b/menu.h
@@ -1,6 +1,177 @@
 #ifndef MENU_H
 #define MENU_H
 
+#include "common.h"
+#include "model.h"
+#include "world_render.h"
+#include "player.h"
+#include "conf.h"
+#include "shaders/model_menu.h"
+
+struct {
+   int active;
+   f32 factive;
+   int disable_open;
+
+   u32 page; /* current page index */
+   ent_menuitem *loc;
+   ent_camera   *cam;
+   camera        view;
+
+   mdl_context model;
+   GLuint texture;
+   glmesh mesh;
+
+   mdl_array_ptr items, markers, cameras;
+}
+static menu;
+
+static void menu_init(void)
+{
+   void *alloc = vg_mem.rtmemory;
+
+   mdl_open( &menu.model, "models/rs_menu.mdl", alloc );
+   mdl_load_metadata_block( &menu.model, alloc );
+
+   vg_linear_clear( vg_mem.scratch );
+
+   mdl_load_array( &menu.model, &menu.items,   "ent_menuitem", alloc );
+   mdl_load_array( &menu.model, &menu.markers, "ent_marker", alloc );
+   mdl_load_array( &menu.model, &menu.cameras, "ent_camera", alloc );
+
+   vg_linear_clear( vg_mem.scratch );
+
+   if( !mdl_arrcount( &menu.model.textures ) )
+      vg_fatal_error( "No texture in menu file" );
+
+   mdl_texture *tex0 = mdl_arritm( &menu.model.textures, 0 );
+   void *data = vg_linear_alloc( vg_mem.scratch, tex0->file.pack_size );
+   mdl_fread_pack_file( &menu.model, &tex0->file, data );
+
+   mdl_async_load_glmesh( &menu.model, &menu.mesh );
+   vg_tex2d_load_qoi_async( data, tex0->file.pack_size, 
+                            VG_TEX2D_LINEAR|VG_TEX2D_CLAMP,
+                            &menu.texture );
+
+   mdl_close( &menu.model );
+   shader_model_menu_register();
+}
+
+static void menu_open_page( const char *name )
+{
+   u32 hash = vg_strdjb2( name );
+   for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
+      ent_menuitem *item = mdl_arritm( &menu.items, i );
+      
+      if( item->type == k_ent_menuitem_type_page ){
+         if( mdl_pstreq( &menu.model, item->page.pstr_name, name, hash ) ){
+            menu.page = __builtin_ctz( item->groups );
+            vg_info( "menu page: %u\n", menu.page );
+
+            if( item->page.id_entrypoint ){
+               u32 id = mdl_entity_id_id( item->page.id_entrypoint );
+               menu.loc = mdl_arritm( &menu.items, id );
+            }
+
+            if( item->page.id_viewpoint ){
+               u32 id = mdl_entity_id_id( item->page.id_viewpoint );
+               menu.cam = mdl_arritm( &menu.cameras, id );
+            }
+
+            return;
+         }
+      }
+   }
+}
+
+static void menu_update(void)
+{
+   if( button_down( k_srbind_mopen ) ){
+      if( menu.active ){
+         menu.active = 0;
+      }
+      else{
+         if( !menu.disable_open ){
+            menu.active = 1;
+            menu_open_page( "Main Menu" );
+         }
+      }
+   }
+
+   menu.factive = vg_lerpf( menu.factive, menu.active, 
+                            vg.time_frame_delta * 6.0f );
+
+   if( menu.factive > 0.01f ){
+      
+   }
+}
+
+VG_STATIC void menu_render_bg(void)
+{
+   glEnable(GL_BLEND);
+   glDisable(GL_DEPTH_TEST);
+   glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+   glBlendEquation(GL_FUNC_ADD);
+
+   shader_blitcolour_use();
+   shader_blitcolour_uColour( (v4f){ 0.1f, 0.1f, 0.3f, menu.factive*0.5f } );
+   render_fsquad();
+}
+
+VG_STATIC void menu_render_fg(void)
+{
+   glEnable( GL_DEPTH_TEST );
+   glDisable( GL_BLEND );
+
+   if( menu.cam ){
+      menu.view.fov = menu.cam->fov;
+      menu.view.farz = 150.0f;
+      menu.view.nearz = 0.01f;
+      v3_copy( menu.cam->transform.co, menu.view.pos );
+
+      v3f v0;
+      mdl_transform_vector( &menu.cam->transform, (v3f){0.0f,-1.0f,0.0f}, v0 );
+      player_vector_angles( menu.view.angles, v0, 1.0f, 0.0f );
+      camera_update_transform( &menu.view );
+      camera_update_view( &menu.view );
+      camera_update_projection( &menu.view );
+      camera_finalize( &menu.view );
+   }
+   else return;
+
+   shader_model_menu_use();
+   shader_model_menu_uColour( (v4f){ 1.0f,1.0f,1.0f,1.0f} );
+   shader_model_menu_uTexMain( 1 );
+   glActiveTexture( GL_TEXTURE1 );
+   glBindTexture( GL_TEXTURE_2D, menu.texture );
+   shader_model_menu_uPv( menu.view.mtx.pv );
+   shader_model_menu_uPvmPrev( menu.view.mtx_prev.pv );
+
+   mesh_bind( &menu.mesh );
+
+   for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
+      ent_menuitem *item = mdl_arritm( &menu.items, i );
+
+      if(   item->type == k_ent_menuitem_type_page ) continue;
+      if( !(item->groups & (0x1 << menu.page)) ) continue;
+
+      m4x3f mmdl;
+      mdl_transform_m4x3( &item->transform, mmdl );
+      shader_model_menu_uMdl( mmdl );
+
+      for( u32 j=0; j<item->submesh_count; j++ ){
+         u32 index = item->submesh_start + j;
+         mdl_draw_submesh( mdl_arritm( &menu.model.submeshs, index ));
+      }
+   }
+}
+
+#endif /* MENU_H */
+
+#if 0
+#ifndef MENU_H
+#define MENU_H
+
 #include "common.h"
 #include "model.h"
 #include "world_render.h"
@@ -875,3 +1046,4 @@ VG_STATIC void menu_render_fg( camera *cam )
 }
 
 #endif /* MENU_H */
+#endif
diff --git a/model.h b/model.h
index 664950fc0191b7bf6f9e7f95e3ce6d4cffd3bb25..e37e3239bd8ab173f94870dda2a8bdf8e23911ac 100644 (file)
--- a/model.h
+++ b/model.h
@@ -7,7 +7,7 @@
 
 #include "common.h"
 
-#define MDL_VERSION_NR 100
+#define MDL_VERSION_NR 101
 
 enum mdl_shader
 {
@@ -407,7 +407,7 @@ VG_STATIC void mdl_open( mdl_context *mdl, const char *path, void *lin_alloc )
    if( l != 1 )
       mdl_load_fatal_corrupt( mdl );
 
-   if( mdl->info.version != MDL_VERSION_NR ){
+   if( mdl->info.version < MDL_VERSION_NR ){
       vg_warn( "For model: %s\n", path );
       vg_warn( "  version: %u (current: %u)\n", mdl->info.version, 
                MDL_VERSION_NR );
@@ -444,7 +444,18 @@ VG_STATIC void mdl_transform_m4x3( mdl_transform *transform, m4x3f mtx )
 
 VG_STATIC const char *mdl_pstr( mdl_context *mdl, u32 pstr )
 {
-   return mdl_arritm( &mdl->strings, pstr );
+   return ((char *)mdl_arritm( &mdl->strings, pstr )) + 4;
+}
+
+VG_STATIC int 
+mdl_pstreq( mdl_context *mdl, u32 pstr, const char *str, u32 djb2 )
+{
+   u32 hash = *((u32 *)mdl_arritm( &mdl->strings, pstr ));
+   if( hash == djb2 ){
+      if( !strcmp( str, mdl_pstr( mdl, pstr ))) return 1;
+      else return 0;
+   }
+   else return 0;
 }
 
 /*
diff --git a/models_src/boards/hgn_mountain.mdl b/models_src/boards/hgn_mountain.mdl
new file mode 100644 (file)
index 0000000..f919a73
Binary files /dev/null and b/models_src/boards/hgn_mountain.mdl differ
index 33af54ed0d6e5e4bec8cdf6005bae4800794186b..f29acf109c4d5287e6d75aca7ebee36205c21c87 100644 (file)
Binary files a/models_src/boards/skaterift_fish.mdl and b/models_src/boards/skaterift_fish.mdl differ
index 24feb86620b02f3795f17a3e47290b5155cdbb81..f174b0099ffb866cd12f8e72a72ea575a5ea6a4d 100644 (file)
Binary files a/models_src/boards/skaterift_striped.mdl and b/models_src/boards/skaterift_striped.mdl differ
index c42eba6164df51ed9ea0fc6da201ef2fd51a14ba..f2bc80654fc896649d210fe5fb3b057626986cd6 100644 (file)
Binary files a/models_src/ch_jordan.mdl and b/models_src/ch_jordan.mdl differ
index 85845bb089a4318964777c2728837f215ace1cf1..086ffead7de019a39afb77e155d814310a903341 100644 (file)
Binary files a/models_src/ch_new.mdl and b/models_src/ch_new.mdl differ
index 211e447201a13ed42ebeac031f518fa7be3760ad..2e9eccde468d4da704845d37002bb32f5de0ab1d 100644 (file)
Binary files a/models_src/ch_outlaw.mdl and b/models_src/ch_outlaw.mdl differ
index bf167ad41c359b2b77924271478caf234545d6d8..00199821d9746e85f220dbddc9626ab13195ee3c 100644 (file)
Binary files a/models_src/rs_font.mdl and b/models_src/rs_font.mdl differ
index fda4b5e533891f8e8c2b3b0b65d17b2273b6db7d..9d22e2ccefee7b3d0fdc7f417490677ca7729a1d 100644 (file)
Binary files a/models_src/rs_gate.mdl and b/models_src/rs_gate.mdl differ
index 9c49da5d6a1732ee7e9f7b54d7ac0034ec89c22c..a01b026f3a16f286c515344a400dc4104cfc7c32 100644 (file)
Binary files a/models_src/rs_menu.mdl and b/models_src/rs_menu.mdl differ
index bf85fc4a99dfa77d2108fa35dbaf28f6fb69d47d..5731170c912a1d923a6edc68ec3b20dfb3d1b135 100644 (file)
Binary files a/models_src/rs_scoretext.mdl and b/models_src/rs_scoretext.mdl differ
index beb78ea7b68088eeb5eb4eb31c17f220f4c5a5c1..53980b142be1d98c70985d67d7cf05e730329c21 100644 (file)
Binary files a/models_src/rs_skydome.mdl and b/models_src/rs_skydome.mdl differ
index f807e3a580f2213b41700d96fc85b9c7e15d73ef..ee597d0271e4ba0c2cc3d65e310d62a6eb6da0ca 100644 (file)
@@ -5,6 +5,7 @@
 #include "player.h"
 #include "conf.h"
 #include "input.h"
+#include "menu.h"
 
 VG_STATIC float
    k_cam_spring            = 20.0f,
@@ -239,23 +240,23 @@ VG_STATIC void player_look( player_instance *player, v3f angles )
 {
    if( vg_ui.wants_mouse ) return;
 
+   float sensitivity = 1.0f-menu.factive;
+
    angles[2] = 0.0f;
 
    v2f mouse_input;
    v2_copy( vg.mouse_delta, mouse_input );
-   if( cl_invert_y )
-      mouse_input[1] *= -1.0f;
-   v2_muladds( angles, mouse_input, 0.0025f, angles );
+   if( cl_invert_y ) mouse_input[1] *= -1.0f;
+   v2_muladds( angles, mouse_input, 0.0025f * sensitivity, angles );
 
    v2f jlook;
    joystick_state( k_srjoystick_look, jlook );
 
-   angles[0] += jlook[0] * vg.time_delta * 4.0f;
+   angles[0] += jlook[0] * vg.time_delta * 4.0f * sensitivity;
    float input_y = jlook[1] * vg.time_delta * 4.0f;
-   if( cl_invert_y )
-      input_y *= -1.0f;
+   if( cl_invert_y ) input_y *= -1.0f;
 
-   angles[1] += input_y;
+   angles[1] += input_y * sensitivity;
    angles[1] = vg_clampf( angles[1], -VG_PIf*0.5f, VG_PIf*0.5f );
 }
 
index e1971b2000725198264cf07b6d7ec5f65e675d40..ae3272cfbb097c1f3e43dcb46439d8e0e6ac787a 100644 (file)
@@ -1192,13 +1192,10 @@ VG_STATIC void player__skate_post_update( player_instance *player )
       slide = 0.0f;
    }
 
-   static float menu_gate = 1.0f;
-   menu_gate = vg_lerpf( menu_gate, 1-cl_menu, vg.time_frame_delta*4.0f );
-
-   float
-         vol_main    = sqrtf( (1.0f-air)*attn*(1.0f-slide) * 0.4f ) * menu_gate,
-         vol_air     = sqrtf(       air *attn * 0.5f )              * menu_gate,
-         vol_slide   = sqrtf( (1.0f-air)*attn*slide * 0.25f )       * menu_gate;
+   f32 gate        = 1.0f-menu.factive,
+       vol_main    = sqrtf( (1.0f-air)*attn*(1.0f-slide) * 0.4f ) * gate,
+       vol_air     = sqrtf(       air *attn * 0.5f )              * gate,
+       vol_slide   = sqrtf( (1.0f-air)*attn*slide * 0.25f )       * gate;
 
    const u32 flags = AUDIO_FLAG_SPACIAL_3D|AUDIO_FLAG_LOOP;
 
index fedaa3d8728b6b17dbf563784744c2d57c175e0f..742bd5905150399a50ecf64a30843647938fa890 100644 (file)
@@ -35,14 +35,6 @@ VG_STATIC int skaterift_status = 0;
 #include "menu.h"
 #include "vehicle.h"
 
-#define DEV_AARON
-#ifdef DEV_AARON
-static rb_object aaron={
-   .type=k_rb_shape_box,
-   .rb.bbx = {{ -2.0f, -1.0f, -1.0f }, { 2.0f, 1.0f, 1.0f }}
-};
-#endif
-
 int main( int argc, char *argv[] )
 {
    vg_mem.use_libc_malloc = 0;
@@ -81,14 +73,6 @@ vg_info("            '        ' '--' [] '----- '----- '     ' '---'  "
    steam_init();
    vg_loader_step( NULL, steam_end );
    vg_loader_step( network_init, network_end );
-
-#ifdef DEV_AARON
-   q_identity( aaron.rb.q );
-   v3_zero( aaron.rb.w );
-   v3_zero( aaron.rb.co );
-   v3_zero( aaron.rb.v );
-   rb_init_object( &aaron );
-#endif
 }
 
 VG_STATIC void load_playermodels(void)
@@ -153,7 +137,6 @@ VG_STATIC void vg_load(void)
    vg_loader_step( audio_init, audio_free );
 
    /* 'systems' are completely loaded now */
-
    /* load home world */
 
 #if 1
@@ -207,29 +190,6 @@ VG_STATIC void vg_update_fixed(void)
 
       player__update( &localplayer );
       vehicle_update_fixed();
-
-#ifdef DEV_AARON
-      world_instance *world = get_active_world();
-      rb_solver_reset();
-      rb_ct *buf = rb_global_buffer();
-
-      int l = rb_box__scene( aaron.rb.to_world, aaron.rb.bbx,
-                             NULL, &world->rb_geo.inf.scene, buf );
-      for( int j=0; j<l; j++ ){
-         buf[j].rba = &aaron.rb;
-         buf[j].rbb = &world->rb_geo.rb;
-      }
-      rb_contact_count += l;
-      rb_presolve_contacts( rb_contact_buffer, rb_contact_count );
-
-      for( int j=0; j<8; j++ ){
-         rb_solve_contacts( rb_contact_buffer, rb_contact_count );
-      }
-
-      rb_iter( &aaron.rb );
-      rb_update_transform( &aaron.rb );
-#endif
-
    }
 }
 
@@ -260,21 +220,8 @@ VG_STATIC void vg_update_post(void)
       audio_unlock();
 
       menu_update();
+      vg.time_rate = 1.0f-menu.factive;
       vehicle_update_post();
-
-#ifdef DEV_AARON
-      SDL_Scancode sc = SDL_GetScancodeFromKey( SDLK_q );
-      if( vg_input.sdl_keys[sc] ){
-         m4x3_mulv( main_camera.transform, (v3f){0.0f,0.0f,-3.0f}, 
-                    aaron.rb.co );
-
-         v3_zero( aaron.rb.v );
-         v3_zero( aaron.rb.w );
-         rb_update_transform( &aaron.rb );
-      }
-
-      rb_object_debug( &aaron, VG__PINK );
-#endif
    }
 }
 
@@ -305,7 +252,7 @@ VG_STATIC void present_view_with_post_processing(void)
       shader_blitblur_uInverseRatio( inverse );
 
       v2f menu_blurring;
-      v2_muls( (v2f){ 0.04f, 0.001f }, menu_opacity, menu_blurring );
+      v2_muls( (v2f){ 0.04f, 0.001f }, menu.factive, menu_blurring );
       shader_blitblur_uOverrideDir( menu_blurring );
 
       render_fb_bind_texture( gpipeline.fb_main, 0, 0 );
@@ -379,34 +326,10 @@ VG_STATIC void render_scene_gate_subview(void)
 
 VG_STATIC void render_main_game(void)
 {
-#if 0
-   static float fov = 60.0f;
-   float fov_target = vg_lerpf( 90.0f, 110.0f, cl_fov );
-
-   if( player.controller == k_player_controller_skate )
-      fov_target = vg_lerpf( 97.0f, 135.0f, cl_fov );
-
-   if( cl_menu )
-      fov_target = menu_fov_target;
-   fov = vg_lerpf( fov, fov_target, vg.frame_delta * 2.0f );
-   fov = freecam? 60.0f: fov;
-
-   main_camera.fov   = fov;
-#endif
-
    player__pre_render( &localplayer );
-
-   v3_lerp( localplayer.cam.pos, menu_camera_pos, menu_opacity, 
-            main_camera.pos );
-   main_camera.angles[0] = 
-      vg_alerpf(  localplayer.cam.angles[0], menu_camera_angles[0], 
-                  menu_opacity );
-   main_camera.angles[1] = 
-      vg_lerpf ( localplayer.cam.angles[1], menu_camera_angles[1], 
-                 menu_opacity );
-
-   main_camera.fov = vg_lerpf( localplayer.cam.fov, menu_smooth_fov,
-                               menu_opacity );
+   main_camera.fov = localplayer.cam.fov;
+   v3_copy( localplayer.cam.pos, main_camera.pos );
+   v3_copy( localplayer.cam.angles, main_camera.angles );
 
    main_camera.nearz = 0.1f;
    main_camera.farz  = 2100.0f;
@@ -430,19 +353,15 @@ VG_STATIC void render_main_game(void)
 
    render_scene();
 
-   if( cl_menu ) {
-      //glClear( GL_DEPTH_BUFFER_BIT );
-      menu_render_bg();
-      glEnable( GL_DEPTH_TEST );
-   }
+   if( menu.active ) menu_render_bg();
+   glEnable( GL_DEPTH_TEST );
 
    render_player_transparent();
    render_scene_gate_subview();
 
    present_view_with_post_processing();
 
-   if( cl_menu )
-      menu_render_fg( &main_camera );
+   if( menu.active ) menu_render_fg();
 
    /* =========== End Frame =========== */
 }
@@ -484,10 +403,8 @@ VG_STATIC void vg_gui(void)
    player__im_gui( &localplayer );
 #endif
    world_instance *world = get_active_world();
-   menu_crap_ui();
 
    workshop_form_gui();
-   
    render_view_framebuffer_ui();
 }
 
diff --git a/world.h b/world.h
index 010364ce7b7b0c25e87f1fcf6bf8c6d02619a305..962b96405c87ccb076122ee2eb89d6a82bfbc90a 100644 (file)
--- a/world.h
+++ b/world.h
@@ -265,6 +265,7 @@ struct world_global{
    u32 text_particle_count;
 }
 static world_global;
+VG_STATIC void entity_call( world_instance *world, ent_call *call );
 
 VG_STATIC world_instance *get_active_world( void )
 {