From: hgn Date: Sat, 25 Nov 2023 05:13:26 +0000 (+0000) Subject: world regions X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;h=23ba25574349652d86979fc787ec4b0214001333;p=carveJwlIkooP6JGAAIwe30JlM.git world regions --- diff --git a/blender_export.py b/blender_export.py index 8b0bd10..b49bf48 100644 --- a/blender_export.py +++ b/blender_export.py @@ -41,13 +41,15 @@ sr_entity_list = [ ('ent_challenge', 'Challenge', '', 19 ), ('ent_relay', 'Relay', '', 20 ), ('ent_miniworld', 'Mini World', '', 22 ), - ('ent_prop', 'Prop', '', 23 ) + ('ent_prop', 'Prop', '', 23 ), + ('ent_list', 'Entity List', '', 24 ), + ('ent_region', 'Region', '', 25 ) ] MDL_VERSION_NR = 104 SR_TRIGGERABLE = [ 'ent_audio', 'ent_ccmd', 'ent_gate', 'ent_challenge', \ 'ent_relay', 'ent_skateshop', 'ent_objective', 'ent_route',\ - 'ent_miniworld' ] + 'ent_miniworld', 'ent_region' ] def get_entity_enum_id( alias ): #{ @@ -273,6 +275,10 @@ class ent_route(Structure): sr_functions = { 0: 'view' } #} +class ent_list(Structure):#{ + _fields_ = [("start",c_uint16),("count",c_uint16)] +#} + class ent_water(Structure): #{ _fields_ = [("transform",mdl_transform), @@ -516,6 +522,15 @@ class ent_challenge(Structure):#{ 1: 'view/reset' } #} +class ent_region(Structure):#{ + _fields_ = [("transform",mdl_transform), + ("submesh_start",c_uint32), ("submesh_count",c_uint32), + ("pstr_title",c_uint32), + ("flags",c_uint32), + ("zone_volume",c_uint32)] + sr_functions = { 0: 'enter', 1: 'leave' } +#} + class ent_relay(Structure):#{ _fields_ = [("targets",(c_uint32*2)*4), ("targets_events",c_uint32*4)] @@ -1690,6 +1705,7 @@ def sr_compile( collection ): if ent_type == 'ent_font_variant': continue if ent_type == 'ent_menuitem': continue if ent_type == 'ent_objective': continue + if ent_type == 'ent_region': continue #TODO: This is messy. if ent_type == 'ent_gate':#{ @@ -1960,6 +1976,16 @@ def sr_compile( collection ): challenge.status = 0 sr_ent_push( challenge ) #} + elif ent_type == 'ent_region':#{ + region = ent_region() + obj_data = obj.SR_data.ent_region[0] + compile_obj_transform( obj, region.transform ) + region.submesh_start, region.submesh_count, _ = \ + sr_compile_mesh_internal( obj ) + region.pstr_title = sr_compile_string( obj_data.title ) + region.zone_volume = sr_entity_id( obj_data.zone_volume ) + sr_ent_push( region ) + #} elif ent_type == 'ent_relay':#{ relay = ent_relay() obj_data = obj.SR_data.ent_relay[0] @@ -2986,6 +3012,66 @@ class SR_OBJECT_ENT_ROUTE(bpy.types.PropertyGroup): #} #} + +class SR_OT_ENT_LIST_NEW_ITEM(bpy.types.Operator):#{ + bl_idname = "skaterift.ent_list_new_entry" + bl_label = "Add entity" + + def execute(self, context):#{ + return internal_listadd_execute(self,context,'ent_list','entities') + #} +#} + +class SR_OT_ENT_LIST_DEL_ITEM(bpy.types.Operator):#{ + bl_idname = "skaterift.ent_list_del_entry" + bl_label = "Remove entity" + + @classmethod + def poll(cls, context):#{ + active_object = context.active_object + if obj_ent_type(active_object) == 'ent_list':#{ + return active_object.SR_data.ent_list[0].entities + #} + else: return False + #} + + def execute(self, context):#{ + return internal_listdel_execute(self,context,'ent_list','entities') + #} +#} + +class SR_OBJECT_ENT_LIST_ENTRY(bpy.types.PropertyGroup): +#{ + target: bpy.props.PointerProperty( \ + type=bpy.types.Object, name='target' ) +#} + +class SR_UL_ENT_LIST(bpy.types.UIList):#{ + bl_idname = 'SR_UL_ENT_LIST' + + def draw_item(_,context,layout,data,item,icon,active_data,active_propname):#{ + layout.prop( item, 'target', text='', emboss=False ) + #} +#} + +class SR_OBJECT_ENT_LIST(bpy.types.PropertyGroup):#{ + entities: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_LIST_ENTRY) + entities_index: bpy.props.IntProperty() + + @staticmethod + def sr_inspector( layout, data ):#{ + layout.label( text='Entities' ) + layout.template_list('SR_UL_ENT_LIST', 'Entities', \ + data[0], 'entities', data[0], \ + 'entities_index', rows=5) + + row = layout.row() + row.operator( 'skaterift.ent_list_new_entry', text='Add' ) + row.operator( 'skaterift.ent_list_del_entry', text='Remove' ) + #} +#} + + class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):#{ subtype: bpy.props.EnumProperty( name="Subtype", @@ -3400,6 +3486,13 @@ class SR_OBJECT_ENT_CHALLENGE(bpy.types.PropertyGroup):#{ #} #} +class SR_OBJECT_ENT_REGION(bpy.types.PropertyGroup):#{ + title: bpy.props.StringProperty( name="Title" ) + zone_volume: bpy.props.PointerProperty( + type=bpy.types.Object, name="Zone Volume", \ + poll=lambda self,obj: sr_filter_ent_type(obj,['ent_volume'])) +#} + class SR_OBJECT_ENT_RELAY(bpy.types.PropertyGroup):#{ target0: bpy.props.PointerProperty( \ type=bpy.types.Object, name="Target 0", \ @@ -3447,8 +3540,10 @@ class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup): 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_region: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_REGION) ent_relay: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_RELAY) ent_miniworld: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_MINIWORLD) + ent_list: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_LIST) ent_type: bpy.props.EnumProperty( name="Type", @@ -4683,7 +4778,10 @@ classes = [ SR_INTERFACE, SR_MATERIAL_PANEL,\ SR_OBJECT_ENT_WORKSHOP_PREVIEW,SR_OBJECT_ENT_MENU_ITEM,\ SR_OBJECT_ENT_WORLD_INFO,SR_OBJECT_ENT_CCMD,\ SR_OBJECT_ENT_OBJECTIVE,SR_OBJECT_ENT_CHALLENGE,\ + SR_OBJECT_ENT_REGION,\ SR_OBJECT_ENT_RELAY,SR_OBJECT_ENT_MINIWORLD,\ + SR_OBJECT_ENT_LIST_ENTRY, SR_UL_ENT_LIST, SR_OBJECT_ENT_LIST, \ + SR_OT_ENT_LIST_NEW_ITEM, SR_OT_ENT_LIST_DEL_ITEM,\ \ SR_OBJECT_PROPERTIES, SR_LIGHT_PROPERTIES, SR_BONE_PROPERTIES, SR_MESH_PROPERTIES, SR_MATERIAL_PROPERTIES \ diff --git a/ent_miniworld.c b/ent_miniworld.c index 497e9d0..024fa6c 100644 --- a/ent_miniworld.c +++ b/ent_miniworld.c @@ -117,11 +117,11 @@ static void ent_miniworld_render( world_instance *host_world, camera *cam ){ for( u32 i=0; ient_route); i++ ){ ent_route *route = mdl_arritm( &dest_world->ent_route, i ); - if( route->achievment_status & 0x2 ){ + if( route->flags & k_ent_route_flag_achieve_gold ){ miniworld_icon( cam, k_gui_icon_rift_run_gold, route->board_transform[3],1.0f); } - else if( route->achievment_status & 0x1 ){ + else if( route->flags & k_ent_route_flag_achieve_silver ){ miniworld_icon( cam, k_gui_icon_rift_run_silver, route->board_transform[3],1.0f); } diff --git a/ent_region.c b/ent_region.c new file mode 100644 index 0000000..720cb3c --- /dev/null +++ b/ent_region.c @@ -0,0 +1,75 @@ +#include "ent_region.h" +#include "gui.h" + +static void ent_region_call( world_instance *world, ent_call *call ){ + ent_region *region = + mdl_arritm( &world->ent_region, mdl_entity_id_id(call->id) ); + + if( !region->zone_volume ) + return; + + ent_volume *volume = + mdl_arritm( &world->ent_volume, mdl_entity_id_id(region->zone_volume) ); + + if( call->function == 0 ){ /* enter */ + for( u32 i=0; ient_route); i ++ ){ + ent_route *route = mdl_arritm( &world->ent_route, i ); + + v3f local; + m4x3_mulv( volume->to_local, route->board_transform[3], local ); + if( (fabsf(local[0]) <= 1.0f) && + (fabsf(local[1]) <= 1.0f) && + (fabsf(local[2]) <= 1.0f) ){ + route->flags &= ~k_ent_route_flag_out_of_zone; + } + else { + route->flags |= k_ent_route_flag_out_of_zone; + } + } + + gui_location_print_ccmd( 1, (const char *[]){ + mdl_pstr(&world->meta,region->pstr_title)} ); + } + else if( call->function == 1 ){ /* leave */ + for( u32 i=0; ient_route); i ++ ){ + ent_route *route = mdl_arritm( &world->ent_route, i ); + route->flags |= k_ent_route_flag_out_of_zone; + } + } +} + +/* + * reevaluate all achievements to calculate the compiled achievement + */ +static void ent_region_re_eval( world_instance *world ){ + for( u32 i=0; ient_region); i ++ ){ + ent_region *region = mdl_arritm(&world->ent_region, i); + + if( !region->zone_volume ) + continue; + + ent_volume *volume = mdl_arritm(&world->ent_volume, + mdl_entity_id_id(region->zone_volume)); + + u32 combined = k_ent_route_flag_achieve_gold | + k_ent_route_flag_achieve_silver; + + for( u32 j=0; jent_route); j ++ ){ + ent_route *route = mdl_arritm(&world->ent_route, j ); + + v3f local; + m4x3_mulv( volume->to_local, route->board_transform[3], local ); + if( !((fabsf(local[0]) <= 1.0f) && + (fabsf(local[1]) <= 1.0f) && + (fabsf(local[2]) <= 1.0f)) ){ + continue; + } + + combined &= route->flags; + } + + region->flags = combined; + + /* TODO: Challenges */ + } +} diff --git a/ent_region.h b/ent_region.h new file mode 100644 index 0000000..9a1fb3c --- /dev/null +++ b/ent_region.h @@ -0,0 +1,6 @@ +#ifndef ENT_REGION_H +#define ENT_REGION_H + +#include "world_entity.h" + +#endif /* ENT_REGION_H */ diff --git a/entity.c b/entity.c index 85557b1..59e9219 100644 --- a/entity.c +++ b/entity.c @@ -12,6 +12,7 @@ #include "ent_route.c" #include "ent_portal.c" #include "ent_miniworld.c" +#include "ent_region.c" typedef void (*fn_entity_call_handler)( world_instance *, ent_call *); @@ -28,7 +29,8 @@ static void entity_call( world_instance *world, ent_call *call ){ [k_ent_relay] = ent_relay_call, [k_ent_challenge] = ent_challenge_call, [k_ent_route] = ent_route_call, - [k_ent_miniworld] = ent_miniworld_call + [k_ent_miniworld] = ent_miniworld_call, + [k_ent_region] = ent_region_call }; if( type >= vg_list_size(table) ){ diff --git a/entity.h b/entity.h index 3fd3508..0e65c26 100644 --- a/entity.h +++ b/entity.h @@ -32,6 +32,7 @@ typedef struct ent_relay ent_relay; typedef struct ent_cubemap ent_cubemap; typedef struct ent_miniworld ent_miniworld; typedef struct ent_prop ent_prop; +typedef struct ent_region ent_region; enum entity_alias{ k_ent_none = 0, @@ -56,7 +57,10 @@ enum entity_alias{ k_ent_challenge = 19, k_ent_relay = 20, k_ent_cubemap = 21, - k_ent_miniworld = 22 + k_ent_miniworld = 22, + k_ent_prop = 23, + k_ent_list = 24, + k_ent_region = 25 }; static u32 mdl_entity_id_type( u32 entity_id ){ @@ -166,10 +170,17 @@ struct ent_checkpoint{ path_count; }; +enum ent_route_flag { + k_ent_route_flag_achieve_silver = 0x1, + k_ent_route_flag_achieve_gold = 0x2, + + k_ent_route_flag_out_of_zone = 0x10 +}; + struct ent_route{ union{ mdl_transform transform; - u32 official_track_id; + u32 official_track_id; /* TODO: remove this */ } anon; @@ -191,7 +202,7 @@ struct ent_route{ u32 id_camera; /* v103+ */ /* v104+, but always accessible */ - u32 achievment_status; + u32 flags; f64 best_laptime; }; @@ -526,6 +537,11 @@ struct ent_prop { u32 submesh_start, submesh_count, flags; }; +struct ent_region { + mdl_transform transform; + u32 submesh_start, submesh_count, pstr_title, flags, zone_volume; +}; + #include "world.h" static void entity_call( world_instance *world, ent_call *call ); diff --git a/maps_src/mp_mtzero/main.mdl b/maps_src/mp_mtzero/main.mdl index 40e488e..3f7148d 100644 Binary files a/maps_src/mp_mtzero/main.mdl and b/maps_src/mp_mtzero/main.mdl differ diff --git a/world.h b/world.h index ebf18c6..9d8cd49 100644 --- a/world.h +++ b/world.h @@ -183,7 +183,8 @@ struct world_instance { ent_relay, ent_cubemap, ent_miniworld, - ent_prop; + ent_prop, + ent_region; enum skybox { k_skybox_default, diff --git a/world_entity.c b/world_entity.c index 0e484ed..3fd7ac6 100644 --- a/world_entity.c +++ b/world_entity.c @@ -618,12 +618,6 @@ static void world_entity_start( world_instance *world, vg_msg *sav ){ } } - for( u32 i=0; ient_route); i++ ){ - ent_route *route = mdl_arritm( &world->ent_route, i ); - route->achievment_status = 0; - route->best_laptime = 0.0; - } - vg_msg routes_block = *sav; if( vg_msg_seekframe( &routes_block, "routes" ) ){ for( u32 i=0; ient_route); i++ ){ @@ -632,13 +626,14 @@ static void world_entity_start( world_instance *world, vg_msg *sav ){ vg_msg route_info = routes_block; if( vg_msg_seekframe( &route_info, mdl_pstr(&world->meta,route->pstr_name) ) ){ - route->achievment_status = - vg_msg_getkvu32( &route_info, "achivement_status", 0 ); + route->flags |= vg_msg_getkvu32( &route_info, "flags", 0 ); route->best_laptime = vg_msg_getkvf64( &route_info, "best_laptime", 0.0 ); } } } + + ent_region_re_eval( world ); } static void world_entity_serialize( world_instance *world, vg_msg *sav ){ @@ -656,7 +651,7 @@ static void world_entity_serialize( world_instance *world, vg_msg *sav ){ vg_msg_frame( sav, mdl_pstr( &world->meta, route->pstr_name ) ); { - vg_msg_wkvu32( sav, "achivement_status", route->achievment_status ); + vg_msg_wkvu32( sav, "flags", route->flags ); vg_msg_wkvf64( sav, "best_laptime", route->best_laptime ); } vg_msg_end_frame( sav ); diff --git a/world_gen.c b/world_gen.c index 51d0302..4e01de3 100644 --- a/world_gen.c +++ b/world_gen.c @@ -287,6 +287,17 @@ static void world_gen_generate_meshes( world_instance *world ){ } } + /* unpack region models */ + for( u32 i=0; ient_region ); i++ ){ + ent_region *region = mdl_arritm( &world->ent_region, i ); + + for( u32 j=0; jsubmesh_count; j ++ ){ + mdl_submesh *sm = mdl_arritm( &world->meta.submeshs, + region->submesh_start+j ); + world_unpack_submesh_dynamic( world, &world->scene_no_collide, sm ); + } + } + /* unpack gate models */ for( u32 i=0; ient_gate ); i++ ){ ent_gate *gate = mdl_arritm( &world->ent_gate, i ); diff --git a/world_load.c b/world_load.c index 379a7de..586b804 100644 --- a/world_load.c +++ b/world_load.c @@ -68,6 +68,7 @@ static void world_instance_load_mdl( u32 instance_id, const char *path ){ MDL_LOAD_ARRAY( meta, &world->ent_cubemap, ent_cubemap, heap ); MDL_LOAD_ARRAY( meta, &world->ent_miniworld, ent_miniworld, heap ); MDL_LOAD_ARRAY( meta, &world->ent_prop, ent_prop, heap ); + MDL_LOAD_ARRAY( meta, &world->ent_region, ent_region, heap ); mdl_array_ptr infos; MDL_LOAD_ARRAY( meta, &infos, ent_worldinfo, vg_mem.scratch ); diff --git a/world_render.c b/world_render.c index 096de9a..4d5321b 100644 --- a/world_render.c +++ b/world_render.c @@ -453,9 +453,8 @@ static void render_world_alphatest( world_instance *world, camera *cam ){ glEnable(GL_CULL_FACE); } -static -void world_render_challenges( world_instance *world, struct world_pass *pass, - v3f pos ){ +static void world_render_challenges( world_instance *world, + struct world_pass *pass, v3f pos ){ if( !world ) return; if( skaterift.activity == k_skaterift_replay ) return; if( world != world_current_instance() ) return; @@ -615,18 +614,21 @@ void world_render_challenges( world_instance *world, struct world_pass *pass, } } -static void render_world_fxglow( world_instance *world, camera *cam ){ +static void render_world_fxglow( world_instance *host_world, + world_instance *world, camera *cam, + m4x3f world_mmdl, + int generic, int challenges, int regions ){ shader_scene_fxglow_use(); shader_scene_fxglow_uUvOffset( (v2f){ 0.0f, 0.0f } ); shader_scene_fxglow_uTexMain(1); shader_scene_fxglow_uPv( cam->mtx.pv ); - world_link_lighting_ub( world, _shader_scene_fxglow.id ); - world_bind_position_texture( world, _shader_scene_fxglow.id, + world_link_lighting_ub( host_world, _shader_scene_fxglow.id ); + world_bind_position_texture( host_world, _shader_scene_fxglow.id, _uniform_scene_fxglow_g_world_depth, 2 ); - world_bind_light_array( world, _shader_scene_fxglow.id, + world_bind_light_array( host_world, _shader_scene_fxglow.id, _uniform_scene_fxglow_uLightsArray, 3 ); - world_bind_light_index( world, _shader_scene_fxglow.id, + world_bind_light_index( host_world, _shader_scene_fxglow.id, _uniform_scene_fxglow_uLightsIndex, 4 ); shader_scene_fxglow_uCamera( cam->transform[3] ); @@ -640,8 +642,45 @@ static void render_world_fxglow( world_instance *world, camera *cam ){ .fn_set_uPvmPrev = shader_scene_fxglow_uPvmPrev, }; - world_render_both_stages( world, &pass ); - world_render_challenges( world, &pass, cam->pos ); + if( generic ) + world_render_both_stages( world, &pass ); + + if( regions ){ + mesh_bind( &world->mesh_no_collide ); + + u32 last_material = 0; + for( u32 i=0; ient_region); i ++ ){ + shader_scene_fxglow_uUvOffset( (v2f){ 0.0f, 0.0f } ); + ent_region *region = mdl_arritm( &world->ent_region, i ); + + f32 offset = 0.0f; + if( region->flags & k_ent_route_flag_achieve_gold ) + offset = 2.0f; + else if( region->flags & k_ent_route_flag_achieve_silver ) + offset = 1.0f; + + shader_scene_fxglow_uUvOffset( (v2f){ (8.0f/256.0f)*offset, 0.0f } ); + + m4x3f mmdl; + mdl_transform_m4x3( ®ion->transform, mmdl ); + m4x3_mul( world_mmdl, mmdl, mmdl ); + shader_scene_fxglow_uMdl( mmdl ); + + for( u32 j=0; jsubmesh_count; j++ ){ + mdl_submesh *sm = mdl_arritm( &world->meta.submeshs, + region->submesh_start + j ); + + if( sm->material_id != last_material ){ + last_material = sm->material_id; + pass.fn_bind_textures(world,&world->surfaces[sm->material_id]); + } + mdl_draw_submesh( sm ); + } + } + } + + if( challenges ) + world_render_challenges( world, &pass, cam->pos ); glEnable(GL_CULL_FACE); } @@ -922,7 +961,7 @@ static void render_world( world_instance *world, camera *cam, GL_COLOR_ATTACHMENT1 } ); } - render_world_fxglow( world, cam ); + render_world_fxglow( world, world, cam, NULL, 1, 1, 0 ); } if( with_water ){ @@ -1040,6 +1079,8 @@ static void render_world_override( world_instance *world, pass.geo_type = k_world_geo_type_nonsolid; render_world_override_pass( world, &pass, mmdl, mnormal, mpvm_prev ); glEnable( GL_CULL_FACE ); + + render_world_fxglow( world, world, cam, mmdl, 0, 0, 1 ); } static void render_cubemap_side( world_instance *world, ent_cubemap *cm, diff --git a/world_routes.c b/world_routes.c index 4deccaa..d81419f 100644 --- a/world_routes.c +++ b/world_routes.c @@ -21,6 +21,7 @@ #include "shaders/scene_route.h" #include "shaders/routeui.h" +#include "ent_region.h" static void world_routes_clear( world_instance *world ) { @@ -96,12 +97,12 @@ static void world_routes_time_lap( world_instance *world, ent_route *route ){ if( (route->best_laptime == 0.0) || (lap_time < route->best_laptime) ){ route->best_laptime = lap_time; - route->achievment_status |= 0x1; - - if( clean ) - route->achievment_status |= 0x2; } + route->flags |= k_ent_route_flag_achieve_silver; + if( clean ) route->flags |= k_ent_route_flag_achieve_gold; + ent_region_re_eval( world ); + /* for steam achievements. */ if( route->anon.official_track_id != 0xffffffff ){ struct track_info *ti = &track_infos[ route->anon.official_track_id ]; @@ -542,6 +543,12 @@ static void world_gen_routes_ent_init( world_instance *world ){ ent_route *route = mdl_arritm(&world->ent_route,i); mdl_transform_m4x3( &route->anon.transform, route->board_transform ); + route->flags = 0x00; + route->best_laptime = 0.0; + + if( mdl_arrcount(&world->ent_region) ) + route->flags |= k_ent_route_flag_out_of_zone; + route->anon.official_track_id = 0xffffffff; for( u32 j=0; jflags & k_ent_route_flag_out_of_zone ) + return; + u32 last_version=0; f64 last_time = 0.0; @@ -59,7 +62,7 @@ static void ent_route_imgui( world_instance *world, ent_route *route, for( u32 i=0; ilength * 2.0f; + ui_px w = block->length * 6.0f; ui_rect rect = { x, inout_cursor[1], w, h }; ui_fill( rect, colour ); diff --git a/world_routes_ui.h b/world_routes_ui.h index 318e124..00bfe42 100644 --- a/world_routes_ui.h +++ b/world_routes_ui.h @@ -6,4 +6,5 @@ struct route_ui{ }; +static void ent_region_re_eval( world_instance *world ); #endif /* WORLD_ROUTES_UI_H */