('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 \
#include "world.h"
#include "player.h"
#include "gui.h"
+#include "menu.h"
/*
* Checks string equality but does a hash check first
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
*/
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();
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;
vg_info( "Entering skateshop\n" );
localplayer.immobile = 1;
+ menu.disable_open = 1;
global_skateshop.active = 1;
v3_zero( localplayer.rb.v );
vg_info( "exit skateshop\n" );
localplayer.immobile = 0;
global_skateshop.active = 0;
+ menu.disable_open = 0;
srinput.ignore_input_frames = 2;
}
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 )
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 )
{
#include "world.h"
-VG_STATIC void entity_call( world_instance *world, ent_call *call );
-
#endif /* ENTITY_H */
#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"
}
#endif /* MENU_H */
+#endif
#include "common.h"
-#define MDL_VERSION_NR 100
+#define MDL_VERSION_NR 101
enum mdl_shader
{
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 );
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;
}
/*
#include "player.h"
#include "conf.h"
#include "input.h"
+#include "menu.h"
VG_STATIC float
k_cam_spring = 20.0f,
{
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 );
}
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;
#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;
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)
vg_loader_step( audio_init, audio_free );
/* 'systems' are completely loaded now */
-
/* load home world */
#if 1
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
-
}
}
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
}
}
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 );
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;
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 =========== */
}
player__im_gui( &localplayer );
#endif
world_instance *world = get_active_world();
- menu_crap_ui();
workshop_form_gui();
-
render_view_framebuffer_ui();
}
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 )
{