sqek
authorhgn <hgodden00@gmail.com>
Wed, 1 Oct 2025 23:27:30 +0000 (23:27 +0000)
committerhgn <hgodden00@gmail.com>
Wed, 1 Oct 2025 23:27:30 +0000 (23:27 +0000)
foundation.kv
include/common_api.h
include/engine_interface.h
source/console_core.c
source/console_core.h
source/engine/input.c
source/engine/main.c
source/foundation/logging.c
source/foundation/options.c
source/foundation/string.c
source/tools/metacompiler.c

index 763c2a78502a971b0eedb6864fea60c4fb8e85ac..b67b322ea863cb5bacf7ae52a40c96195bf2739a 100644 (file)
@@ -36,120 +36,149 @@ add source/foundation/async.c
    add source/engine/main.c
    add source/engine/ui.c
    add source/engine/shader.c
-   add source/engine/input.c
    add source/engine/console.c
    add source/console_core.c
-   append graphics.kv
-   append glfw3.kv
-
    input_layer
    {
       name console
    }
-
    input
    {
       name console
       type action
       layer_mask console
-      bind GRAVE_ACCENT
    }
 
+   append graphics.kv
+   append glfw3.kv
+
+   add source/engine/input.c
+   ccmd
+   {
+      name bind
+      function _input_bind_ccmd
+      description "Bind device input to a button, action or axis"
+
+      parameter
+      {
+         description "Device input alias"
+      }
+
+      parameter
+      {
+         description "button,action,axis name"
+      }
+   }
+
+   ccmd
+   {
+      name exec
+      function _console_exec_ccmd
+      description "Execute a configuration file"
+
+      parameter
+      {
+         description "The path to the config"
+      }
+   }
+
+   config "bind ALT+GRAVE_ACCENT console"
+   config "bind BACKSPACE ui_backspace"
+   config "bind DELETE ui_delete"
+   config "bind ENTER ui_enter"
+   config "bind TAB ui_indent"
+   config "bind HOME ui_home"
+   config "bind SHIFT+HOME ui_home_select"
+   config "bind END ui_end"
+   config "bind SHIFT+END ui_end_select"
+   config "bind LEFT ui_left"
+   config "bind SHIFT+LEFT ui_left_select"
+   config "bind RIGHT ui_right"
+   config "bind SHIFT+RIGHT ui_right_select"
+   config "bind UP ui_up"
+   config "bind SHIFT+UP ui_up_select"
+   config "bind DOWN ui_down"
+   config "bind SHIFT+DOWN ui_down_select"
+
    input
    {
-      name ui_backspace
-      bind BACKSPACE
+      name ui_delete
       type action
    }
    input
    {
-      name ui_delete
-      bind DELETE
+      name ui_backspace
       type action
    }
    input
    {
       name ui_enter
-      bind ENTER
       type action
    }
    input
    {
       name ui_indent
-      bind TAB
       type action
    }
 
    input
    {
       name ui_home
-      bind HOME
       type action
    }
    input
    {
       name ui_home_select
-      bind "SHIFT HOME"
       type action
    }
    input
    {
       name ui_end
-      bind END
       type action
    }
    input
    {
       name ui_end_select
-      bind "SHIFT END"
       type action
    }
    input
    {
       name ui_left
-      bind LEFT
       type action
    }
    input
    {
       name ui_left_select
-      bind "SHIFT LEFT"
       type action
    }
    input
    {
       name ui_right
-      bind RIGHT
       type action
    }
    input
    {
       name ui_right_select
-      bind "SHIFT RIGHT"
       type action
    }
    input
    {
       name ui_up
-      bind UP
       type action
    }
    input
    {
       name ui_up_select
-      bind "SHIFT UP"
       type action
    }
    input
    {
       name ui_down
-      bind DOWN
       type action
    }
    input
    {
       name ui_down_select
-      bind "SHIFT DOWN"
       type action
    }
 
@@ -170,19 +199,6 @@ add source/foundation/async.c
       description "This is just a test variable!"
    }
 
-   ccmd
-   {
-      name list
-      function _console_list_ccmd
-      description "List everything the console knows"
-
-      parameter
-      {
-         enum "a b c d e f g"
-         description "Nothing!"
-      }
-   }
-
    event
    {
       name TEST_HOOK
index 70e493823f1694764d3a9d41116bf51e69b41382..4b95e613ce547331595687ac400ffc45c078662a 100644 (file)
@@ -205,7 +205,7 @@ bool stream_error( struct stream *stream );
 
 const c8 *string_get( struct stream *string );
 void string_clip( struct stream *string, i32 length );
-void string_append( struct stream *string, const c8 *substring );
+void string_append( struct stream *string, const c8 *substring, u32 length );
 void string_append_c8( struct stream *string, c8 c );
 void string_append_i64( struct stream *string, i64 value, u64 base );
 void string_append_i64r( struct stream *string, i64 value, u64 base, u32 width, c8 blank_c8acter );
@@ -224,7 +224,11 @@ struct v_string_arg
 
    u32 type;
    u32 base;
+   union
+   {
    u32 decimals;
+   u32 length;
+   };
 };
 void v_string( struct stream *string, struct v_string_arg *argument_list );
 
@@ -235,7 +239,7 @@ void v_string( struct stream *string, struct v_string_arg *argument_list );
 #define k_$float 4
 #define k_$errno 5
 
-#define $string( X, ... ) { string_get( X ), __VA_ARGS__ }
+#define $string( X, ... ) { X, __VA_ARGS__ }
 #define $unsigned( X, ... ) { .type=k_$unsigned, ._u64=X, __VA_ARGS__ }
 #define $signed( X, ... ) { .type=k_$signed, ._i64=X, __VA_ARGS__ }
 #define $float( X, ... ) { .type=k_$float, ._f64=X, __VA_ARGS__ }
index 211d6f7180aedd0a9d60575f29601177132d9c8a..c0dd5bcdce6cbdea4f4fb20d19f99a49c4995193 100644 (file)
@@ -34,6 +34,7 @@ enum input_type
 
 enum input_device
 {
+   k_input_device_none = 0,
    k_input_device_keyboard,
    k_input_device_controller
 };
index 0b386ab141bc870f0e7cc368199ef5df3269f9ac..c9db750b32dba62119181cba769f7d416b626f92 100644 (file)
@@ -1,3 +1,11 @@
+#include "console_core.h"
+
+struct console_command 
+{
+   const c8 *alias;
+   i32 (*fn)( struct console_arguments *args );
+};
+
 #include "generated/console.c"
 
 struct
@@ -12,30 +20,115 @@ struct history_item
    const c8 *entry;
 };
 
+i32 _console_exec_ccmd( struct console_arguments *args )
+{
+   const c8 *path = console_get_argument( args, 0 );
+   if( !path )
+   {
+      $log( $error, {"Usage: exec <path>"} );
+      return -1;
+   }
+
+   struct stream file;
+   if( !stream_open_file( &file, path, k_stream_read ) )
+      return -1;
+
+   bool more_to_go = 1;
+   while( more_to_go )
+   {
+      u32 temp_frame = _start_temporary_frame();
+
+      struct stream line;
+      stream_open_stack( &line, _temporary_stack_allocator(), k_stream_null_terminate );
+
+      c8 c;
+      more_to_go = 0;
+      while( stream_read( &file, &c, 1 ) )
+      {
+         if( c == '\n' )
+         {
+            more_to_go = 1;
+            break;
+         }
+         string_append_c8( &line, c );
+      }
+
+      if( stream_offset( &line ) )
+         _console_execute( string_get( &line ), 1, 0 );
+
+      _end_temporary_frame( temp_frame );
+   }
+
+   return 0;
+}
+
 void _console_execute( const c8 *command, bool silent, bool cheat_allowed )
 {
+   if( !silent )
+      $log( $shell, {command} );
+
    struct stream string;
-   stream_open_buffer_read( &string, command, buffer_last_index( command, 0, 0 ), 0 );
+   stream_open_buffer_read( &string, command, buffer_last_index( command, 0, 0 )+1, 0 );
 
-   c8 *tokens[32];
-   u32 token_count = 0;
+   struct console_arguments args;
+   args.count = 0;
 
    u32 temp_frame = _start_temporary_frame();
+   struct console_command *target_command = NULL;
 
-   for( u32 i=0; i<32; i ++ )
+   // TODO: warning if we put to many or to few arguments & required ones.
+   for( u32 i=0; i<ARRAY_COUNT(args.arguments)+1; i ++ )
    {
       u32 start, length;
       enum string_parse_result info = string_parse_string( &string, &start, &length, '"' );
       if( info == k_string_parse_ok )
       {
-         tokens[ token_count ] = _temporary_allocate( length + 1, 4 );
-         buffer_copy( command + start, length, tokens[ token_count ], length );
-         tokens[ token_count ][ length ] = 0;
-         token_count ++;
+         if( i == 0 )
+         {
+            for( u32 j=0; j<ARRAY_COUNT(_console_commands); j ++ )
+            {
+               struct console_command *cmd = &_console_commands[j];
+               if( compare_buffers( cmd->alias, 0, command+start, length ) )
+               {
+                  target_command = cmd;
+                  break;
+               }
+            }
+
+            if( !target_command )
+            {
+               $log( $error, {"There is no command called '"}, $string( command+start, .length=length ), {"'"} );
+               return;
+            }
+         }
+         else
+         {
+            c8 *buffer = _temporary_allocate( length + 1, 4 );
+            buffer_copy( command + start, length, buffer, length );
+            buffer[ length ] = 0;
 
-         $log( $info, {":: "}, {tokens[ token_count ]} );
+            args.arguments[ args.count ] = buffer;
+            args.count ++;
+         }
       }
+      else break;
    }
 
+   if( target_command )
+      target_command->fn( &args );
+
    _end_temporary_frame( temp_frame );
 }
+
+const c8 *console_get_argument( struct console_arguments *args, u32 index )
+{
+   if( index < args->count )
+      return args->arguments[ index ];
+   else 
+      return NULL;
+}
+
+void _console_init(void)
+{
+   _console_execute( "exec cfg/default.cfg", 1, 0 );
+}
index 862bd99420f1ccde0e1286cc335a43395d2db28e..91928ac798e3b77b731a4932e52153410feb0ec8 100644 (file)
@@ -1 +1,11 @@
 #include "generated/console.h"
+
+void _console_init(void);
+void _console_execute( const c8 *command, bool silent, bool cheat_allowed );
+
+struct console_arguments
+{
+   const c8 *arguments[ 32 ];
+   u32 count;
+};
+const c8 *console_get_argument( struct console_arguments *args, u32 index );
index edb1359e90f71464c360459e2f9bccaf734cfb79..bf0c5ec93f7dd7b4fddfc0e30cf0755733a7186d 100644 (file)
@@ -1,7 +1,156 @@
 #include "glfw.h"
 #include "engine_interface.h"
+#include "console_core.h"
 #include "generated/input.c"
 
+struct input_alias
+{
+   const c8 *alias;
+   u8 device_type;
+   u32 key, mod;
+   u32 alias_hash;
+}
+_input_aliases[] = 
+{
+   { "SPACE", k_input_device_keyboard, .key = GLFW_KEY_SPACE },
+   { "APOSTROPHE", k_input_device_keyboard, .key = GLFW_KEY_APOSTROPHE },
+   { "COMMA", k_input_device_keyboard, .key = GLFW_KEY_COMMA },
+   { "MINUS", k_input_device_keyboard, .key = GLFW_KEY_MINUS },
+   { "PERIOD", k_input_device_keyboard, .key = GLFW_KEY_PERIOD },
+   { "SLASH", k_input_device_keyboard, .key = GLFW_KEY_SLASH },
+   { "0", k_input_device_keyboard, .key = GLFW_KEY_0 },
+   { "1", k_input_device_keyboard, .key = GLFW_KEY_1 },
+   { "2", k_input_device_keyboard, .key = GLFW_KEY_2 },
+   { "3", k_input_device_keyboard, .key = GLFW_KEY_3 },
+   { "4", k_input_device_keyboard, .key = GLFW_KEY_4 },
+   { "5", k_input_device_keyboard, .key = GLFW_KEY_5 },
+   { "6", k_input_device_keyboard, .key = GLFW_KEY_6 },
+   { "7", k_input_device_keyboard, .key = GLFW_KEY_7 },
+   { "8", k_input_device_keyboard, .key = GLFW_KEY_8 },
+   { "9", k_input_device_keyboard, .key = GLFW_KEY_9 },
+   { "SEMICOLON", k_input_device_keyboard, .key = GLFW_KEY_SEMICOLON },
+   { "EQUAL", k_input_device_keyboard, .key = GLFW_KEY_EQUAL },
+   { "A", k_input_device_keyboard, .key = GLFW_KEY_A },
+   { "B", k_input_device_keyboard, .key = GLFW_KEY_B },
+   { "C", k_input_device_keyboard, .key = GLFW_KEY_C },
+   { "D", k_input_device_keyboard, .key = GLFW_KEY_D },
+   { "E", k_input_device_keyboard, .key = GLFW_KEY_E },
+   { "F", k_input_device_keyboard, .key = GLFW_KEY_F },
+   { "G", k_input_device_keyboard, .key = GLFW_KEY_G },
+   { "H", k_input_device_keyboard, .key = GLFW_KEY_H },
+   { "I", k_input_device_keyboard, .key = GLFW_KEY_I },
+   { "J", k_input_device_keyboard, .key = GLFW_KEY_J },
+   { "K", k_input_device_keyboard, .key = GLFW_KEY_K },
+   { "L", k_input_device_keyboard, .key = GLFW_KEY_L },
+   { "M", k_input_device_keyboard, .key = GLFW_KEY_M },
+   { "N", k_input_device_keyboard, .key = GLFW_KEY_N },
+   { "O", k_input_device_keyboard, .key = GLFW_KEY_O },
+   { "P", k_input_device_keyboard, .key = GLFW_KEY_P },
+   { "Q", k_input_device_keyboard, .key = GLFW_KEY_Q },
+   { "R", k_input_device_keyboard, .key = GLFW_KEY_R },
+   { "S", k_input_device_keyboard, .key = GLFW_KEY_S },
+   { "T", k_input_device_keyboard, .key = GLFW_KEY_T },
+   { "U", k_input_device_keyboard, .key = GLFW_KEY_U },
+   { "V", k_input_device_keyboard, .key = GLFW_KEY_V },
+   { "W", k_input_device_keyboard, .key = GLFW_KEY_W },
+   { "X", k_input_device_keyboard, .key = GLFW_KEY_X },
+   { "Y", k_input_device_keyboard, .key = GLFW_KEY_Y },
+   { "Z", k_input_device_keyboard, .key = GLFW_KEY_Z },
+   { "LEFT_BRACKET", k_input_device_keyboard, .key = GLFW_KEY_LEFT_BRACKET },
+   { "BACKSLASH", k_input_device_keyboard, .key = GLFW_KEY_BACKSLASH },
+   { "RIGHT_BRACKET", k_input_device_keyboard, .key = GLFW_KEY_RIGHT_BRACKET },
+   { "GRAVE_ACCENT", k_input_device_keyboard, .key = GLFW_KEY_GRAVE_ACCENT },
+   { "WORLD_1", k_input_device_keyboard, .key = GLFW_KEY_WORLD_1 },
+   { "WORLD_2", k_input_device_keyboard, .key = GLFW_KEY_WORLD_2 },
+   { "ESCAPE", k_input_device_keyboard, .key = GLFW_KEY_ESCAPE },
+   { "ENTER", k_input_device_keyboard, .key = GLFW_KEY_ENTER },
+   { "TAB", k_input_device_keyboard, .key = GLFW_KEY_TAB },
+   { "BACKSPACE", k_input_device_keyboard, .key = GLFW_KEY_BACKSPACE },
+   { "INSERT", k_input_device_keyboard, .key = GLFW_KEY_INSERT },
+   { "DELETE", k_input_device_keyboard, .key = GLFW_KEY_DELETE },
+   { "RIGHT", k_input_device_keyboard, .key = GLFW_KEY_RIGHT },
+   { "LEFT", k_input_device_keyboard, .key = GLFW_KEY_LEFT },
+   { "DOWN", k_input_device_keyboard, .key = GLFW_KEY_DOWN },
+   { "UP", k_input_device_keyboard, .key = GLFW_KEY_UP },
+   { "PAGE_UP", k_input_device_keyboard, .key = GLFW_KEY_PAGE_UP },
+   { "PAGE_DOWN", k_input_device_keyboard, .key = GLFW_KEY_PAGE_DOWN },
+   { "HOME", k_input_device_keyboard, .key = GLFW_KEY_HOME },
+   { "END", k_input_device_keyboard, .key = GLFW_KEY_END },
+   { "CAPS_LOCK", k_input_device_keyboard, .key = GLFW_KEY_CAPS_LOCK },
+   { "SCROLL_LOCK", k_input_device_keyboard, .key = GLFW_KEY_SCROLL_LOCK },
+   { "NUM_LOCK", k_input_device_keyboard, .key = GLFW_KEY_NUM_LOCK },
+   { "PRINT_SCREEN", k_input_device_keyboard, .key = GLFW_KEY_PRINT_SCREEN },
+   { "PAUSE", k_input_device_keyboard, .key = GLFW_KEY_PAUSE },
+   { "F1", k_input_device_keyboard, .key = GLFW_KEY_F1 },
+   { "F2", k_input_device_keyboard, .key = GLFW_KEY_F2 },
+   { "F3", k_input_device_keyboard, .key = GLFW_KEY_F3 },
+   { "F4", k_input_device_keyboard, .key = GLFW_KEY_F4 },
+   { "F5", k_input_device_keyboard, .key = GLFW_KEY_F5 },
+   { "F6", k_input_device_keyboard, .key = GLFW_KEY_F6 },
+   { "F7", k_input_device_keyboard, .key = GLFW_KEY_F7 },
+   { "F8", k_input_device_keyboard, .key = GLFW_KEY_F8 },
+   { "F9", k_input_device_keyboard, .key = GLFW_KEY_F9 },
+   { "F10", k_input_device_keyboard, .key = GLFW_KEY_F10 },
+   { "F11", k_input_device_keyboard, .key = GLFW_KEY_F11 },
+   { "F12", k_input_device_keyboard, .key = GLFW_KEY_F12 },
+   { "F13", k_input_device_keyboard, .key = GLFW_KEY_F13 },
+   { "F14", k_input_device_keyboard, .key = GLFW_KEY_F14 },
+   { "F15", k_input_device_keyboard, .key = GLFW_KEY_F15 },
+   { "F16", k_input_device_keyboard, .key = GLFW_KEY_F16 },
+   { "F17", k_input_device_keyboard, .key = GLFW_KEY_F17 },
+   { "F18", k_input_device_keyboard, .key = GLFW_KEY_F18 },
+   { "F19", k_input_device_keyboard, .key = GLFW_KEY_F19 },
+   { "F20", k_input_device_keyboard, .key = GLFW_KEY_F20 },
+   { "F21", k_input_device_keyboard, .key = GLFW_KEY_F21 },
+   { "F22", k_input_device_keyboard, .key = GLFW_KEY_F22 },
+   { "F23", k_input_device_keyboard, .key = GLFW_KEY_F23 },
+   { "F24", k_input_device_keyboard, .key = GLFW_KEY_F24 },
+   { "F25", k_input_device_keyboard, .key = GLFW_KEY_F25 },
+   { "KP_0", k_input_device_keyboard, .key = GLFW_KEY_KP_0 },
+   { "KP_1", k_input_device_keyboard, .key = GLFW_KEY_KP_1 },
+   { "KP_2", k_input_device_keyboard, .key = GLFW_KEY_KP_2 },
+   { "KP_3", k_input_device_keyboard, .key = GLFW_KEY_KP_3 },
+   { "KP_4", k_input_device_keyboard, .key = GLFW_KEY_KP_4 },
+   { "KP_5", k_input_device_keyboard, .key = GLFW_KEY_KP_5 },
+   { "KP_6", k_input_device_keyboard, .key = GLFW_KEY_KP_6 },
+   { "KP_7", k_input_device_keyboard, .key = GLFW_KEY_KP_7 },
+   { "KP_8", k_input_device_keyboard, .key = GLFW_KEY_KP_8 },
+   { "KP_9", k_input_device_keyboard, .key = GLFW_KEY_KP_9 },
+   { "KP_DECIMAL", k_input_device_keyboard, .key = GLFW_KEY_KP_DECIMAL },
+   { "KP_DIVIDE", k_input_device_keyboard, .key = GLFW_KEY_KP_DIVIDE },
+   { "KP_MULTIPLY", k_input_device_keyboard, .key = GLFW_KEY_KP_MULTIPLY },
+   { "KP_SUBTRACT", k_input_device_keyboard, .key = GLFW_KEY_KP_SUBTRACT },
+   { "KP_ADD", k_input_device_keyboard, .key = GLFW_KEY_KP_ADD },
+   { "KP_ENTER", k_input_device_keyboard, .key = GLFW_KEY_KP_ENTER },
+   { "KP_EQUAL", k_input_device_keyboard, .key = GLFW_KEY_KP_EQUAL },
+   { "LEFT_SHIFT", k_input_device_keyboard, .key = GLFW_KEY_LEFT_SHIFT },
+   { "LEFT_CONTROL", k_input_device_keyboard, .key = GLFW_KEY_LEFT_CONTROL },
+   { "LEFT_ALT", k_input_device_keyboard, .key = GLFW_KEY_LEFT_ALT },
+   { "LEFT_SUPER", k_input_device_keyboard, .key = GLFW_KEY_LEFT_SUPER },
+   { "RIGHT_SHIFT", k_input_device_keyboard, .key = GLFW_KEY_RIGHT_SHIFT },
+   { "RIGHT_CONTROL", k_input_device_keyboard, .key = GLFW_KEY_RIGHT_CONTROL },
+   { "RIGHT_ALT", k_input_device_keyboard, .key = GLFW_KEY_RIGHT_ALT },
+   { "RIGHT_SUPER", k_input_device_keyboard, .key = GLFW_KEY_RIGHT_SUPER },
+   { "MENU", k_input_device_keyboard, .key = GLFW_KEY_MENU },
+   { "SHIFT", k_input_device_keyboard, .mod = GLFW_MOD_SHIFT },
+   { "CONTROL", k_input_device_keyboard, .mod = GLFW_MOD_CONTROL },
+   { "ALT", k_input_device_keyboard, .mod = GLFW_MOD_ALT },
+   { "SUPER", k_input_device_keyboard, .mod = GLFW_MOD_SUPER },
+};
+
+static struct input_alias *_input_alias_find( const c8 *alias, u32 alias_length )
+{
+   u32 hash = buffer_djb2( alias, alias_length );
+   for( u32 i=0; i<ARRAY_COUNT( _input_aliases ); i ++ )
+   {
+      struct input_alias *alias_i = &_input_aliases[i];
+      if( alias_i->alias_hash == hash )
+         if( compare_buffers( alias_i->alias, 0, alias, alias_length ) )
+            return alias_i;
+   }
+   return NULL;
+}
+
 static i32 _input_page = 0;
 
 union input_state
@@ -30,14 +179,119 @@ static _input_states[2][k_input_count];
 struct bind
 {
    u16 device, input_index;
-   struct
-   {
-      u32 main, modifiers;
-   }
-   keyboard;
+   u32 id;
+   u32 modifiers;
 };
 struct stretchy_allocator _bind_allocator;
 
+i32 _input_bind_ccmd( struct console_arguments *args )
+{
+   const c8 *buttons = console_get_argument( args, 0 );
+   if( !buttons )
+   {
+      $log( $error, {"Usage: bind <button> <action>"} );
+      return -1;
+   }
+
+   const c8 *input_name = console_get_argument( args, 1 );
+   if( !input_name )
+   {
+      $log( $error, {"Usage: bind <button> <action>"} );
+      return -1;
+   }
+
+   i32 input_id = -1;
+   for( u32 i=0; i<k_input_count; i ++ )
+   {
+      struct input_info *input = &_input_infos[ i ];
+      if( compare_buffers( input->name, 0, input_name, 0 ) )
+      {
+         input_id = i;
+         break;
+      }
+   }
+
+   if( input_id == -1 )
+   {
+      $log( $error, {"Don't know an input called '"}, {input_name}, {"'"} );
+      return -1;
+   }
+
+   struct bind new_bind = { .input_index = input_id };
+   while(1)
+   {
+      i32 plus_index = buffer_first_index( buttons, '+', 0 ),
+          length = plus_index == -1? 0: plus_index;
+
+      struct input_alias *alias = _input_alias_find( buttons, length );
+      if( alias )
+      {
+         if( new_bind.device )
+         {
+            if( alias->device_type != new_bind.device )
+            {
+               $log( $error, {"Device mismatch while parsing buttons"} );
+               return -1;
+            }
+         }
+         else
+            new_bind.device = alias->device_type;
+
+         if( alias->device_type == k_input_device_keyboard )
+         {
+            if( alias->key )
+            {
+               if( new_bind.id )
+               {
+                  $log( $error, {"Cannot specify more than one normal buttons in bind"} );
+                  return -1;
+               }
+               new_bind.id = alias->key;
+            }
+            else //mod
+            {
+               if( new_bind.id )
+               {
+                  $log( $error, {"Modifiers must come first"} );
+                  return -1;
+               }
+               new_bind.modifiers |= alias->mod;
+            }
+         }
+         else
+         {
+            // TODO
+            $log( $error, {"Currently dont support device type'"}, $unsigned(alias->device_type), {"'"} );
+            return -1;
+         }
+      }
+      else
+      {
+         $log( $error, {"Don't know what a '"}, $string( buttons, .length = length ), {"' is"} );
+         return -1;
+      }
+
+      if( plus_index == -1 )
+         break;
+      else
+         buttons += plus_index+1;
+   }
+
+   if( (new_bind.device == k_input_device_keyboard) && !new_bind.id )
+   {
+      $log( $error, {"No key specified for bind"} );
+      if( new_bind.modifiers )
+         $log( $info, {"If you're trying to bind SHIFT to a normal button, use LEFT_SHIFT or RIGHT_ALT etc."} );
+      return -1;
+   }
+
+   if( !stretchy_count( &_bind_allocator ) )
+      stretchy_init( &_bind_allocator, sizeof(struct bind ) );
+   struct bind *a = stretchy_append( &_bind_allocator );
+   *a = new_bind;
+   return 0;
+}
+
 // bind LEFT ui_left  <---- action
 // bind RIGHT ui_right <---- action
 // bind SHIFT ui_select
@@ -57,7 +311,7 @@ static void _input_key_callback( GLFWwindow *window, i32 key, i32 scancode, i32
       struct bind *bind = stretchy_get( &_bind_allocator, i );
       if( bind->device == k_input_device_keyboard )
       {
-         if( bind->keyboard.main == key )
+         if( bind->id == key )
          {
             struct input_info *input = &_input_infos[ bind->input_index ];
             union input_state *state = &_input_states[ _input_page^0x1 ][ bind->input_index ];
@@ -66,7 +320,7 @@ static void _input_key_callback( GLFWwindow *window, i32 key, i32 scancode, i32
             {
                if( (action == GLFW_PRESS) || (action == GLFW_REPEAT) )
                {
-                  if( bind->keyboard.modifiers == mods )
+                  if( bind->modifiers == mods )
                   {
                      ASSERT_CRITICAL( state->action.activation_count < 255 );
                      state->action.activation_count ++;
@@ -102,22 +356,12 @@ static void _input_key_callback( GLFWwindow *window, i32 key, i32 scancode, i32
 void _input_init(void)
 {
    glfwSetKeyCallback( _engine.window_handle, _input_key_callback );
+   for( u32 i=0; i<ARRAY_COUNT( _input_aliases ); i ++ )
+      _input_aliases[i].alias_hash = buffer_djb2( _input_aliases[i].alias, 0 );
 }
 
 void _input_update(void)
 {
-   static bool tester = 0;
-   if( !tester )
-   {
-      stretchy_init( &_bind_allocator, sizeof(struct bind) );
-      struct bind *bind = stretchy_append( &_bind_allocator );
-      bind->device = k_input_device_keyboard;
-      bind->input_index = k_input_action_console;
-      bind->keyboard.main = GLFW_KEY_GRAVE_ACCENT;
-      bind->keyboard.modifiers = GLFW_MOD_SHIFT;
-      tester = 1;
-   }
-
    /* flip to read page and reset the reciever one */
    _input_page ^= 0x1;
    for( u32 i=0; i<k_input_count; i ++ )
index de7bcad6643e84ab84a1a3402f770174e82cc7d4..99970508819a827098642906d1ecd2ef9ac0e975 100644 (file)
@@ -5,6 +5,9 @@
 #include "opengl.h"
 #include "glfw.h"
 
+// TODO: temp
+#include "console_core.h"
+
 struct _engine _engine;
 
 struct
@@ -76,6 +79,7 @@ i32 main( i32 argc, const c8 *argv[] )
    /* ------------- */
    _engine_ui_init();
    _input_init();
+   _console_init();
 
 L_new_frame:;
    f64 now = glfwGetTime();
index 2fa6d1e4dc114be5b958c6ebc30bcc793034de13..923d0f7aae866947248d4e7f8ef809032c2541ce 100644 (file)
@@ -63,26 +63,26 @@ struct stream *_get_console_stream()
 struct stream *_log_event( u32 type, const c8 *code_location )
 {
    struct stream *output = _get_console_stream();
-   string_append( output, KBLK );
+   string_append( output, KBLK, 0 );
 
    u32 line_start = output->offset;
 
    i32 s = buffer_last_index( code_location, '/', 0 );
    if( s != -1 )
    {
-      string_append( output, "..." );
+      string_append( output, "...", 0 );
       code_location += s+1;
    }
-   string_append( output, code_location );
+   string_append( output, code_location, 0 );
 
    while( (output->offset-line_start) < 32 ) string_append_c8( output, ' ' );
-        if( type == $error )   string_append( output, KRED "ERR|" );
-   else if( type == $warning ) string_append( output, KYEL "WRN|" );
-   else if( type == $ok )      string_append( output, KGRN "OK |" );
-   else if( type == $info )    string_append( output, KNRM "LOG|" );
-   else if( type == $low )     string_append( output, KNRM "LOW|" );
-   else if( type == $fatal )   string_append( output, KRED "!!!|" );
-   else if( type == $shell )   string_append( output, KBLU "SHL|" );
-   string_append( output, KNRM );
+        if( type == $error )   string_append( output, KRED "ERR|", 0 );
+   else if( type == $warning ) string_append( output, KYEL "WRN|", 0 );
+   else if( type == $ok )      string_append( output, KGRN "OK |", 0 );
+   else if( type == $info )    string_append( output, KNRM "LOG|", 0 );
+   else if( type == $low )     string_append( output, KNRM "LOW|", 0 );
+   else if( type == $fatal )   string_append( output, KRED "!!!|", 0 );
+   else if( type == $shell )   string_append( output, KBLU "SHL|", 0 );
+   string_append( output, KNRM, 0 );
    return output;
 }
index 9a98b9ba322d305f296404479aa9b68cbbbf3dec..686c55d919ca8640efe0e2cdd35a0c93b0a62dcd 100644 (file)
@@ -111,24 +111,24 @@ void _options_check_end(void)
          u32 base_offset = console->offset;
          if( option->type == k_option_type_flag || option->type == k_option_type_option )
          {
-            string_append( console, "-" );
+            string_append( console, "-", 0 );
             string_append_c8( console, option->alias_c );
             if( option->type == k_option_type_option )
-               string_append( console, " <value>" );
+               string_append( console, " <value>", 0 );
          }
 
          if( option->type == k_option_type_long_flag || option->type == k_option_type_long_option )
          {
-            string_append( console, "--" );
-            string_append( console, option->alias );
+            string_append( console, "--", 0 );
+            string_append( console, option->alias, 0 );
             if( option->type == k_option_type_long_option )
-               string_append( console, "=<value>" );
+               string_append( console, "=<value>", 0 );
          }
 
          while( console->offset < base_offset + 60 )
             string_append_c8( console, ' ' );
 
-         string_append( console, desc );
+         string_append( console, desc, 0 );
          string_append_c8( console, '\n' );
       }
       _normal_exit();
@@ -146,17 +146,17 @@ void _options_check_end(void)
             {
                if( !(argument->used & (0x1<<j)) )
                {
-                  string_append( console, "Unknown option '" );
+                  string_append( console, "Unknown option '", 0 );
                   string_append_c8( console, argument->name[j] );
-                  string_append( console, "'\n" );
+                  string_append( console, "'\n", 0 );
                }
             }
          }
          else
          {
-            string_append( console, "Unknown option '" );
-            string_append( console, argument->name );
-            string_append( console, "'\n" );
+            string_append( console, "Unknown option '", 0 );
+            string_append( console, argument->name, 0 );
+            string_append( console, "'\n", 0 );
          }
          errors = 1;
       }
index 643603ca2fb1112188586ded174e7a2d169e5869..256d601917cbc392e97d1ae232105d5eb8df961d 100644 (file)
@@ -17,9 +17,9 @@ void string_clip( struct stream *string, i32 length )
    stream_write( string, NULL, 0 );
 }
 
-void string_append( struct stream *string, const c8 *substring )
+void string_append( struct stream *string, const c8 *substring, u32 length )
 {
-   stream_write( string, substring, buffer_last_index( substring, 0, 0 ) );
+   stream_write( string, substring, length? length: buffer_last_index( substring, 0, 0 ) );
 }
 
 void string_append_c8( struct stream *string, c8 c )
@@ -318,14 +318,14 @@ void v_string( struct stream *string, struct v_string_arg *argument_list )
       else if( arg->type == k_$float )
          string_append_f64( string, arg->_f64, arg->base? arg->base: 10, arg->decimals? arg->decimals: 2 );
       else if( arg->type == k_$string )
-         string_append( string, arg->_string );
+         string_append( string, arg->_string, arg->length );
       else if( arg->type == k_$errno )
       {
-         string_append( string, "<errno#" );
+         string_append( string, "<errno#", 0 );
          string_append_u64( string, errno, 10 );
-         string_append( string, " (" );
-         string_append( string, strerror(errno) );
-         string_append( string, ")>" );
+         string_append( string, " (", 0 );
+         string_append( string, strerror(errno), 0 );
+         string_append( string, ")>", 0 );
       }
    }
 }
index 5dff89b77a8b6fd109e5942922cebba43d6e14e8..0c441a562ab5330db495165ff3a8645e89ab8468 100644 (file)
@@ -3,7 +3,7 @@
 struct
 {
    c8 project_name[ 128 ];
-   struct stream source_list, include_path_list, define_list;
+   struct stream source_list, include_path_list, define_list, configuration;
    const c8 *enabled_features[ 64 ];
 }
 static _metacompiler;
@@ -12,14 +12,15 @@ struct
 {
    bool using;
    struct stream layer_enums;
-   struct stream input_enums, input_structures, cfg;
+   struct stream input_enums, input_structures;
 }
 static _input;
 
 struct
 {
    bool using;
-   struct stream cvar_header, cvar_definitions;
+   struct stream cvar_header, cvar_definitions, command_prototypes, command_definitions;
+   u32 command_count;
 }
 static _console;
 
@@ -31,7 +32,8 @@ struct block_context
       k_target_input_layer,
       k_target_input,
       k_target_shader,
-      k_target_cvar
+      k_target_cvar,
+      k_target_ccmd
    }
    target;
    u32 feature_count;
@@ -93,6 +95,20 @@ void _parse_kv_block( struct keyvalues *kvs, u32 block, struct block_context con
          $v_string( &_console.cvar_header, {"extern "}, {type}, {" cvar_"}, {name}, {";\n"} );
          $v_string( &_console.cvar_definitions, {type}, {" cvar_"}, {name}, {" = "}, {default_value}, {";\n"} );
       }
+      else if( compare_buffers( block_key, 0, "ccmd", 0 )) 
+      {
+         _console.using = 1;
+         _console.command_count ++;
+         context.target = k_target_ccmd;
+         const c8 *name = keyvalues_read_string( kvs, block, "name", NULL );
+         const c8 *function = keyvalues_read_string( kvs, block, "function", NULL );
+         ASSERT_CRITICAL( name && function );
+         $v_string( &_console.command_definitions, {"   {\n      .alias = \""}, {name}, {"\",\n      .fn = "}, 
+                                                   {function}, {"\n   },\n"} );
+         $v_string( &_console.command_prototypes, {"i32 "}, {function}, {"( struct console_arguments *args );\n"} );
+         // TODO: process parameter descriptions
+         return;
+      }
       else if( compare_buffers( block_key, 0, "shader", 0 )) 
          context.target = k_target_shader;
       else
@@ -143,12 +159,15 @@ void _parse_kv_block( struct keyvalues *kvs, u32 block, struct block_context con
          {
             struct stream path_string;
             stream_open_stack( &path_string, _temporary_stack_allocator(), k_stream_null_terminate );
-            $v_string( &path_string, {context.folder}, {"/"}, {keyvalues_value( kvs, kv, NULL )} );
+            $v_string( &path_string, {context.folder}, {"/"}, {value} );
             _append_kv_list( string_get( &path_string ), context );
          }
          _end_temporary_frame( temp_frame );
       }
 
+      if( compare_buffers( key, 0, "config", 0 ) )
+         $v_string( &_metacompiler.configuration, {value}, {"\n"} );
+
       if( context.target == k_target_main )
       {
          if( compare_buffers( key, 0, "name", 0 ) )
@@ -316,14 +335,16 @@ i32 _terminal_main(void)
    stream_open_buffer_write( &_metacompiler.source_list, _heap_allocate(size), size, options );
    stream_open_buffer_write( &_metacompiler.include_path_list, _heap_allocate(size), size, options );
    stream_open_buffer_write( &_metacompiler.define_list, _heap_allocate(size), size, options );
+   stream_open_buffer_write( &_metacompiler.configuration, _heap_allocate(size), size, options );
 
    stream_open_buffer_write( &_input.layer_enums, _heap_allocate(size), size, options );
    stream_open_buffer_write( &_input.input_enums, _heap_allocate(size), size, options );
    stream_open_buffer_write( &_input.input_structures, _heap_allocate(size), size, options );
-   stream_open_buffer_write( &_input.cfg, _heap_allocate(size), size, options );
    
    stream_open_buffer_write( &_console.cvar_header, _heap_allocate(size), size, options ); 
    stream_open_buffer_write( &_console.cvar_definitions, _heap_allocate(size), size, options ); 
+   stream_open_buffer_write( &_console.command_definitions, _heap_allocate(size), size, options ); 
+   stream_open_buffer_write( &_console.command_prototypes, _heap_allocate(size), size, options ); 
 
    if( platform == k_platform_linux )   _metacompiler.enabled_features[0] = "linux";
    if( platform == k_platform_windows ) _metacompiler.enabled_features[0] = "windows";
@@ -338,13 +359,13 @@ i32 _terminal_main(void)
    {
       struct stream input_header, input_source;
       ASSERT_CRITICAL( stream_open_file( &input_header, "generated/input.h", k_stream_write ) );
-      $v_string( &input_header, {"enum input_layer_id\n{\n"}, $string( &_input.layer_enums ), {"   k_input_layer_count\n};\n"} );
-      $v_string( &input_header, {"enum input_id\n{\n"}, $string( &_input.input_enums ), {"   k_input_count\n};\n"} );
+      $v_string( &input_header, {"enum input_layer_id\n{\n"}, {string_get( &_input.layer_enums )}, {"   k_input_layer_count\n};\n"} );
+      $v_string( &input_header, {"enum input_id\n{\n"}, {string_get( &_input.input_enums )}, {"   k_input_count\n};\n"} );
       stream_close( &input_header );
 
       ASSERT_CRITICAL( stream_open_file( &input_source, "generated/input.c", k_stream_write ) );
       $v_string( &input_source, {"struct input_info _input_infos[k_input_count] = \n{\n"}, 
-                                $string( &_input.input_structures ), {"};\n"} );
+            {string_get( &_input.input_structures )}, {"};\n"} );
       stream_close( &input_source );
    }
 
@@ -352,11 +373,14 @@ i32 _terminal_main(void)
    {
       struct stream console_header, console_source;
       ASSERT_CRITICAL( stream_open_file( &console_header, "generated/console.h", k_stream_write ) );
-      $v_string( &console_header, $string( &_console.cvar_header ) );
+      $v_string( &console_header, {string_get( &_console.cvar_header )} );
       stream_close( &console_header );
 
       ASSERT_CRITICAL( stream_open_file( &console_source, "generated/console.c", k_stream_write ) );
-      $v_string( &console_source, $string( &_console.cvar_definitions ) );
+      $v_string( &console_source, {string_get( &_console.cvar_definitions )} );
+      $v_string( &console_source, {string_get( &_console.command_prototypes )} );
+      $v_string( &console_source, {"static struct console_command _console_commands[] = \n{\n"}, 
+            {string_get( &_console.command_definitions )}, {"};\n\n"} );
       stream_close( &console_source );
    }
 
@@ -386,13 +410,13 @@ i32 _terminal_main(void)
 
       struct stream folder_string;
       stream_open_stack( &folder_string, _temporary_stack_allocator(), k_stream_null_terminate );
-      $v_string( &folder_string, {output_folder}, {"/bin/"}, {_metacompiler.project_name}, {"-"}, $string(&tripple_string) );
+      $v_string( &folder_string, {output_folder}, {"/bin/"}, {_metacompiler.project_name}, {"-"}, {string_get(&tripple_string)} );
 
       free(output_folder);
 
       struct stream command_string;
       stream_open_stack( &command_string, _temporary_stack_allocator(), k_stream_null_terminate );
-      $v_string( &command_string, {"mkdir -p "}, $string( &folder_string ) );
+      $v_string( &command_string, {"mkdir -p "}, {string_get( &folder_string )} );
       system_call( string_get( &command_string ) );
 
 
@@ -404,7 +428,7 @@ i32 _terminal_main(void)
       if( use_tsan ) $v_string( &command_string, {"   -fsanitize=thread -lasan \\\n"} );
       if( use_asan ) $v_string( &command_string, {"   -fsanitize=address -lasan \\\n"} );
 
-      $v_string( &command_string, {"   -target "}, $string(&tripple_string), {" "} );
+      $v_string( &command_string, {"   -target "}, {string_get(&tripple_string)}, {" "} );
       if( platform == k_platform_windows )
       {
          if( !shared )
@@ -419,15 +443,35 @@ i32 _terminal_main(void)
       $v_string( &command_string, {"   -fkeep-static-consts -fkeep-persistent-storage-variables \\\n"} );
 
       $v_string( &command_string, {"      -I. \\\n"} );
-      $v_string( &command_string, $string( &_metacompiler.include_path_list ) );
-      $v_string( &command_string, $string( &_metacompiler.define_list ) );
-      $v_string( &command_string, $string( &_metacompiler.source_list ) );
+      $v_string( &command_string, {string_get( &_metacompiler.include_path_list )} );
+      $v_string( &command_string, {string_get( &_metacompiler.define_list )} );
+      $v_string( &command_string, {string_get( &_metacompiler.source_list )} );
 
-      $v_string( &command_string, {"-o "}, $string( &folder_string ), {"/"}, {_metacompiler.project_name} );
+      $v_string( &command_string, {"-o "}, {string_get( &folder_string )}, {"/"}, {_metacompiler.project_name} );
       if( platform == k_platform_windows ) $v_string( &command_string, {shared? ".dll ": ".exe "} );
       else                                 $v_string( &command_string, {shared? ".so ": " "} );
 
       system_call( string_get( &command_string ) );
+
+      if( _console.using )
+      {
+         u32 temp_frame2 = _start_temporary_frame();
+         struct stream command_string;
+         stream_open_stack( &command_string, _temporary_stack_allocator(), k_stream_null_terminate );
+         $v_string( &command_string, {"mkdir -p "}, {string_get( &folder_string )}, {"/cfg"} );
+         system_call( string_get( &command_string ) );
+
+         struct stream config_path;
+         stream_open_stack( &config_path, _temporary_stack_allocator(), k_stream_null_terminate );
+         $v_string( &config_path, {string_get( &folder_string )}, {"/cfg/default.cfg"} );
+
+         struct stream config_file;
+         ASSERT_CRITICAL( stream_open_file( &config_file, string_get( &config_path ), k_stream_write ) );
+         $v_string( &config_file, {string_get( &_metacompiler.configuration )} );
+         stream_close( &config_file );
+
+         _end_temporary_frame( temp_frame2 ); 
+      }
    }
    _end_temporary_frame( temp_frame ); 
    return 0;