Board exporter dialogue
authorhgn <hgodden00@gmail.com>
Sat, 22 Mar 2025 16:28:06 +0000 (16:28 +0000)
committerhgn <hgodden00@gmail.com>
Sat, 22 Mar 2025 16:28:06 +0000 (16:28 +0000)
build.c
content_skaterift/playermodels/skaterift_john/addon.inf [new file with mode: 0644]
src/addon.c
src/board_maker.c
src/board_maker.h
src/ent_skateshop.c
src/workshop.c

diff --git a/build.c b/build.c
index 8024a3b3d651a56126d4309e6263884a6c57bea4..634262a54018386e6adfe08626f85724c24f29e8 100644 (file)
--- a/build.c
+++ b/build.c
@@ -89,8 +89,8 @@ void build_game_metadata(void)
                             "Aaron", "ch_aaron.mdl",
                             "content_skaterift/playermodels/skaterift_aaron/addon.inf", 0 );
    write_generic_addon_inf( k_addon_type_player,
-                            "J", "ch_j.mdl",
-                            "content_skaterift/playermodels/skaterift_j/addon.inf", 0 );
+                            "JC", "ch_john.mdl",
+                            "content_skaterift/playermodels/skaterift_john/addon.inf", 0 );
    write_generic_addon_inf( k_addon_type_player,
                             "Ela", "ch_ela.mdl",
                             "content_skaterift/playermodels/skaterift_ela/addon.inf", 0 );
diff --git a/content_skaterift/playermodels/skaterift_john/addon.inf b/content_skaterift/playermodels/skaterift_john/addon.inf
new file mode 100644 (file)
index 0000000..bb48fd9
Binary files /dev/null and b/content_skaterift/playermodels/skaterift_john/addon.inf differ
index 164699b021a46e956ce8031c6a675fc4514f1186..eac4fcb4429b2a2fd021eee2de79ef2ada980c5d 100644 (file)
@@ -451,15 +451,9 @@ addon_reg *addon_mount_local_addon( const char *folder, enum addon_type type, co
    }
    else
    {
-      /* create our own content commands */
-      vg_msg msg;
-      vg_msg_init( &msg, reg->metadata, sizeof(reg->metadata) );
-
-      u32 content_count = 0;
-
-      vg_strcat( &folder_path, "" );
-      vg_warn( "Creating own metadata for: %s\n", folder_path.buffer );
-
+      vg_strcat( &folder_path, "" ); /* NOTE: this looks fucky because try_load_metadata edits the buffer, this sets it 
+                                              back. to remove the addon.inf which it appened to that buffer (but not
+                                              edit the vg_str)....... */
       vg_dir subdir;
       enum dir_open_result result = vg_dir_open(&subdir, folder_path.buffer);
       if( result != k_dir_open_ok )
@@ -468,6 +462,18 @@ addon_reg *addon_mount_local_addon( const char *folder, enum addon_type type, co
          return NULL;
       }
 
+      /* create our own content commands */
+      vg_msg msg;
+      vg_msg_init( &msg, reg->metadata, sizeof(reg->metadata) );
+      vg_msg_frame( &msg, "workshop" );
+      {
+         vg_msg_wkvstr( &msg, "title", reg->alias.foldername );
+         vg_msg_wkvstr( &msg, "author", "Custom Mod" );
+      }
+      vg_msg_end_frame( &msg );
+
+      u32 content_count = 0;
+
       while( vg_dir_next_entry(&subdir) )
       {
          if( vg_dir_entry_type(&subdir) == k_vg_entry_type_file )
@@ -488,7 +494,9 @@ addon_reg *addon_mount_local_addon( const char *folder, enum addon_type type, co
       }
       vg_dir_close(&subdir);
 
-      if( !content_count ) return NULL;
+      if( !content_count ) 
+         return NULL;
+
       if( msg.error == k_vg_msg_error_OK )
          reg->metadata_len = msg.cur.co;
       else
index af05a514c517d30da322fdb641849158152d9c15..77c6eb3132464a1930a24ad44285245ea9c16cbe 100644 (file)
@@ -134,6 +134,22 @@ static void _board_maker_init_thread( void *_ )
 
 static void _board_maker_export(void)
 {
+   char folder[ 128 ];
+   vg_str folder_str;
+   vg_strnull( &folder_str, folder, sizeof(folder) );
+   vg_strcat( &folder_str, _board_maker.export_path );
+   char *slash = vg_strch( &folder_str, '/' );
+   if( slash )
+      slash[0] = '\0';
+   else 
+   {
+      _board_maker.export_success = 0;
+      _board_maker.export_message = "???";
+      _board_maker.ui_state = k_board_maker_ui_state_export_signal_done;
+      return;
+   }
+   vg_make_directory( folder );
+
    mdl_compiler compiler;
    mdl_compiler_init( &compiler );
 
@@ -156,6 +172,10 @@ static void _board_maker_export(void)
    {
       free( raw_data );
       free( qoi_data );
+
+      _board_maker.export_success = 0;
+      _board_maker.export_message = "Texture failed to compress";
+      _board_maker.ui_state = k_board_maker_ui_state_export_signal_done;
       return;
    }
 
@@ -197,8 +217,12 @@ static void _board_maker_export(void)
                                              ref_submesh->indice_count );
    }
 
-   af_write( &compiler.af, "/tmp/hello.mdl", MDL_VERSION_NR );
+   af_write( &compiler.af, _board_maker.export_path, MDL_VERSION_NR );
    mdl_compiler_free( &compiler );
+
+   _board_maker.export_success = 1;
+   _board_maker.export_message = "Export done!";
+   _board_maker.ui_state = k_board_maker_ui_state_export_signal_done;
 }
 
 /* update loop */
@@ -470,6 +494,45 @@ struct ui_enum_opt _board_maker_wrap_opts[] =
    { 1, "Repeat" }
 };
 
+static void _board_maker_exit_modal_close( u32 args )
+{
+   if( args & UI_MODAL_CANCEL ) {}
+   else
+   {
+      if( world_clear_event( k_world_event_board_maker ) )
+         _board_maker_close();
+   }
+}
+
+static void _board_maker_confirm_overwrite( u32 args )
+{
+   if( args & UI_MODAL_CANCEL ) {}
+   else
+   {
+      _board_maker.state = k_board_maker_state_export;
+   }
+}
+
+static void _board_maker_export_path_changed( ui_context *ctx, char *buf, u32 len, void *userdata )
+{
+   if( strlen(buf) < 3 )
+      _board_maker.can_export = 0;
+   else
+      _board_maker.can_export = 1;
+
+   for( u32 i=0; i<len; i ++ )
+   {
+      if( buf[i] == '\0' ) 
+         break;
+
+      if( buf[i] == '/' || buf[i] == '\\' ) 
+      {
+         _board_maker.can_export = 0;
+         break;
+      }
+   }
+}
+
 void _board_maker_ui( ui_context *ctx )
 {
    if( _world.event != k_world_event_board_maker )
@@ -477,6 +540,85 @@ void _board_maker_ui( ui_context *ctx )
 
    ui_capture_mouse( ctx, 1 );
 
+   if( _board_maker.ui_state == k_board_maker_ui_state_export_signal_done )
+   {
+      if( _board_maker.export_success )
+         ui_start_modal( ctx, _board_maker.export_message, NULL, UI_MODAL_GOOD, NULL );
+      else
+         ui_start_modal( ctx, _board_maker.export_message, NULL, UI_MODAL_BAD, NULL );
+
+      _board_maker.ui_state = k_board_maker_ui_state_default;
+      return;
+   }
+
+   if( _board_maker.ui_state == k_board_maker_ui_state_export )
+   {
+      ui_rect export_rect = { 0,0, 400, 300 };
+      ui_rect_center( (ui_rect){0,0,vg.window_x,vg.window_y}, export_rect );
+      ui_panel( ctx, export_rect, export_rect );
+
+      /* title */
+      ui_rect title_row;
+      ctx->font = &vgf_default_large;
+      ui_standard_widget( ctx, export_rect, title_row, 1 );
+      ui_text( ctx, title_row, "Export board", 1, k_ui_align_middle_center, 0 );
+      ctx->font = &vgf_default_small;
+      ui_info( ctx, export_rect, "This will export your board to disk." );
+      ui_info( ctx, export_rect, "It will appear to use in skate shops!" );
+
+      /* export name */
+      struct ui_textbox_callbacks callbacks = 
+      {
+         .change = _board_maker_export_path_changed
+      };
+      ui_textbox( ctx, export_rect, "File name:", 
+                       _board_maker.export_name, sizeof(_board_maker.export_name), 1, 0, &callbacks );
+
+      /* options buttons */
+      ui_rect bottom_row;
+      ui_split( export_rect, k_ui_axis_h, -32, 8, export_rect, bottom_row );
+
+      ui_rect ok_box, cancel_box;
+      ui_split( bottom_row, k_ui_axis_v, -120, 8, bottom_row, ok_box );
+      ui_split( bottom_row, k_ui_axis_v, -120, 8, bottom_row, cancel_box );
+
+      if( _board_maker.can_export )
+      {
+         if( ui_button_text( ctx, ok_box, "Export", 1 ) == k_ui_button_click )
+         {
+            strcpy( _board_maker.export_path, "boards/" );
+            strcat( _board_maker.export_path, _board_maker.export_name );
+            strcat( _board_maker.export_path, "/board.mdl" );
+
+            if( vg_path_exists( _board_maker.export_path ) )
+            {
+               const struct ui_modal_callbacks callbacks = 
+               {
+                  .close = _board_maker_confirm_overwrite
+               };
+               ui_start_modal( ctx, "Overwrite existing file?", "Overwrite", UI_MODAL_OK|UI_MODAL_CANCEL, &callbacks );
+            }
+            else
+            {
+               _board_maker.state = k_board_maker_state_export;
+            }
+         }
+      }
+      else
+      {
+         // TODO: standardize me
+         ui_fill( ctx, ok_box, ui_colour( ctx, k_ui_bg ) );
+         ui_text( ctx, ok_box, "Export", 1, k_ui_align_middle_center, ui_colour( ctx, k_ui_bg+3 ) );
+      }
+
+      if( ui_button_text( ctx, cancel_box, "Cancel", 1 ) == k_ui_button_click )
+      {
+         _board_maker.ui_state = k_board_maker_ui_state_default;
+      }
+
+      return;
+   }
+
    ui_rect root = { 8, 8, 200, 600 }, panel;
    ui_panel( ctx, root, panel );
 
@@ -489,11 +631,6 @@ void _board_maker_ui( ui_context *ctx )
 
    bool main_clickable = clickable;
 
-#if 0
-   if( _board_maker.ui_state != k_board_maker_ui_state_default )
-      main_clickable = 0;
-#endif
-
    ui_info( ctx, panel, "Wheels" );
    ui_rect w1, w2, w3, w4, wheel_row;
    ui_standard_widget( ctx, panel, wheel_row, 1 );
@@ -535,6 +672,13 @@ void _board_maker_ui( ui_context *ctx )
       ui_fill( ctx, bib, colour );
    }
 
+   ui_rect export_box;
+   ui_standard_widget( ctx, panel, export_box, 2 );
+   if( ui_button_text( ctx, export_box, "Export", 1 ) == k_ui_button_click )
+   {
+      _board_maker.ui_state = k_board_maker_ui_state_export;
+   }
+
    ui_rect quit_box;
    ui_split( panel, k_ui_axis_h, -24, 0, panel, quit_box );
 
@@ -689,10 +833,11 @@ void _board_maker_ui( ui_context *ctx )
 
    if( quit_me )
    {
-      _board_maker.state = k_board_maker_state_export;
-   
-      //if( world_clear_event( k_world_event_board_maker ) )
-      //   _board_maker_close();
+      const struct ui_modal_callbacks callbacks = 
+      {
+         .close = _board_maker_exit_modal_close
+      };
+      ui_start_modal( ctx, "Exit board maker?", "EXIT", UI_MODAL_OK|UI_MODAL_CANCEL, &callbacks );
    }
 }
 
index c8c0ef3c8846ae27ea232ad88e386132e3d4602d..049471521a5cc71890dae883a75895a8279fa580 100644 (file)
@@ -81,12 +81,19 @@ struct _board_maker
       k_board_maker_ui_state_default,
       k_board_maker_ui_state_pick_colour,
       k_board_maker_ui_state_edit_decal,
-      k_board_maker_ui_state_pick_image
+      k_board_maker_ui_state_pick_image,
+      k_board_maker_ui_state_export,
+      k_board_maker_ui_state_export_signal_done,
    }
    ui_state;
    enum board_maker_ui_state ui_image_picker_return_state;
 
    struct vg_filebrowser *browser;
+   char export_name[100];
+   char export_path[128];
+   bool can_export;
+   bool export_success;
+   const char *export_message;
 }
 extern _board_maker;
 
index 74308ce9396b1ccb1a3fafb22ae373646ba431af..d82c6213e4ace4bbf6751bc2402c73481e34421e 100644 (file)
@@ -606,7 +606,8 @@ fade_out:;
       vg_msg msg;
       vg_msg_init( &msg, reg->metadata, reg->metadata_len );
 
-      if( vg_msg_seekframe( &msg, "workshop" ) ){
+      if( vg_msg_seekframe( &msg, "workshop" ) )
+      {
          const char *title = vg_msg_getkvstr( &msg, "title" );
          if( title ) _skateshop.render.item_title = title;
 
index 6c3e7ebe52e0a7120c22bc7d22a96b584e4ee36b..16b6d7fb51833a0602790ca33805bf59df84c0d6 100644 (file)
@@ -57,12 +57,9 @@ static void workshop_reset_submission_data(void)
    workshop_form.submission.description[0] = '\0';
    workshop_form.submission.title[0] = '\0';
    workshop_form.submission.author[0] = '\0';
-   workshop_form.submission.submission_type_selection = 
-      k_addon_type_none;
+   workshop_form.submission.submission_type_selection = k_addon_type_none;
    workshop_form.submission.type = k_addon_type_none;
-
-   workshop_form.submission.visibility =
-      k_ERemoteStoragePublishedFileVisibilityPublic;
+   workshop_form.submission.visibility = k_ERemoteStoragePublishedFileVisibilityPublic;
 
    workshop_form.addon_folder[0] = '\0';
    player_board_unload( &workshop_form.board_model );
@@ -413,8 +410,7 @@ static void workshop_op_submit( ui_context *ctx )
    {
       if( !workshop_form.submission.title[0] )
       {
-         ui_start_modal( ctx, "Cannot submit because a title is required\n",
-                         UI_MODAL_WARN );
+         ui_start_modal( ctx, "Cannot submit because a title is required\n", NULL, UI_MODAL_WARN, NULL );
          workshop_form.op = k_workshop_op_none;
          return;
       }
@@ -424,9 +420,7 @@ static void workshop_op_submit( ui_context *ctx )
    {
       if( !workshop_form.submission.description[0] )
       {
-         ui_start_modal( ctx, 
-                         "Cannot submit because a description is required\n",
-                         UI_MODAL_WARN );
+         ui_start_modal( ctx, "Cannot submit because a description is required\n", NULL, UI_MODAL_WARN, NULL );
          workshop_form.op = k_workshop_op_none;
          return;
       }
@@ -436,8 +430,7 @@ static void workshop_op_submit( ui_context *ctx )
    {
       if( workshop_form.file_intent == k_workshop_form_file_intent_none )
       {
-         ui_start_modal( ctx, "Cannot submit because the file is "
-                         "empty or unspecified\n", UI_MODAL_WARN );
+         ui_start_modal( ctx, "Cannot submit because the file is empty or unspecified\n", NULL, UI_MODAL_WARN, NULL );
          workshop_form.op = k_workshop_op_none;
          return;
       }
@@ -570,7 +563,7 @@ static void workshop_op_load_model( ui_context *ctx )
       else
       {
          ui_start_modal( ctx, "There is no ent_swspreview in the level. \n"
-                         "Cannot publish here\n", UI_MODAL_BAD );
+                              "Cannot publish here\n", NULL, UI_MODAL_BAD, NULL );
          workshop_form.op = k_workshop_op_none;
          return;
       }
@@ -579,7 +572,7 @@ static void workshop_op_load_model( ui_context *ctx )
    else 
    {
       ui_start_modal( ctx, "Don't know how to prepare for this item type. \n"
-                      "Please contact the developers.\n", UI_MODAL_BAD );
+                           "Please contact the developers.\n", NULL, UI_MODAL_BAD, NULL );
       workshop_form.op = k_workshop_op_none;
       return;
    }
@@ -615,7 +608,7 @@ static void workshop_form_async_imageload( void *data, u32 len )
       snprintf( workshop_form.error_msg, sizeof(workshop_form.error_msg),
                "Preview image could not be loaded. Reason: %s\n",
                 stbi_failure_reason() );
-      ui_start_modal( &vg_ui.ctx, workshop_form.error_msg, UI_MODAL_BAD );
+      ui_start_modal( &vg_ui.ctx, workshop_form.error_msg, NULL, UI_MODAL_BAD, NULL );
    }
    workshop_form.op = k_workshop_op_none;
 }
@@ -862,8 +855,7 @@ int workshop_submit_command( int argc, const char *argv[] )
 {
    if( !steam_ready )
    {
-      ui_start_modal( &vg_ui.ctx,
-                      "Steam API is not initialized\n", UI_MODAL_BAD );
+      ui_start_modal( &vg_ui.ctx, "Steam API is not initialized\n", NULL, UI_MODAL_BAD, NULL );
       return 0;
    }