fixed instance loading forget to append basepath.. other path fixes (windows)
[csRadar.git] / csRadar.c
index b05b6a6be3126ae06e7d385c4923f90bd7f99498..17f09a85b547e5434cfa1499471a8d55179eccf3 100644 (file)
--- a/csRadar.c
+++ b/csRadar.c
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#include <time.h>
+// Copyright (C) 2021 Harry Godden (hgn)
 
-// CSR lib
-#include "csrOpt.h"
-#include "csrTypes.h"
-#include "csrMath.h"
-#include "csrMem.h"
-#include "csrIO.h"
-#include "csrComb.h"
+// Building:
+//  gcc -rdynamic csRadar.c -o csRadar -lm -ldl
+//
+// Plugins:
+//  gcc -fpic -shared -o ext/my_plugin.so my_plugin.c -lm
 
-// Valve formats
-#include "vdf.h"
-#include "vpk.h"
-#include "vfilesys.h"
-
-#include "vmdl.h"
-#include "vmf.h"
-
-// CSR main
-#include "csr32f.h"
-#include "csrDraw.h"
-
-#define CSR_VERSION "0.0.1"
-
-// gcc -Wall -fsanitize=address csRadar.c -o csRadar -lm
+#define VALVE_IMPLEMENTATION
+#define CSR_EXECUTABLE
+#include "csRadar.h"
 
 int main( int argc, char *argv[] )
 {
-       char *arg;
-       char *strings[ 20 ];
-       int num_strings = 0;
-       
-       float padding = 128.f;
-       u32 resolution = 1024;
-       int standard_layers = 0;
-       int write_txt = 1;
-       int multi_sample = 1;
-       char output_path[ 512 ];                // Full path eg. /home/harry/my_map.vmf
-       char vmf_name[ 128 ];                   // Just the base name eg. my_map
+       csr_api api = 
+       {
+               .padding = 128.f,
+               .resolution = 1024,
+               .min_z = -INFINITY,
+               .max_z =  INFINITY,
+               .write_txt = 1,
+               .api_version = csr_api_version,
+               .sampling_mode = k_EMSAA_RGSS
+       };
+
        int output_set = 0;
+       char *extension = NULL;
+       char *gameinfo = NULL;
 
+       char *arg;
        while( csr_argp( argc, argv ) )
        {
                if( (arg = csr_arg()) )
                {
-                       if( num_strings == 20 )
+                       if( api.num_strings == 20 )
                        {
-                               fprintf( stderr, "Too many arguments! Max 20\n" );
-                               fs_exit();
-                               exit(0);
+                               log_error( "Too many arguments! Max 20\n" );
+                               goto IL_CSR_EXIT;
                        }
                        
-                       printf( "got: %s\n", arg );
-                       
-                       strings[ num_strings ++ ] = arg;
+                       api.strings[ api.num_strings ++ ].str = arg;
                }
                
                if( (arg = csr_opt_arg( 'o' )) )
                {
-                       strcpy( output_path, arg );
-                       csr_path_winunix( output_path );
-                       
+                       strcpy( api.output_path, arg );
                        output_set = 1;
                }
                
                if( (arg = csr_opt_arg( 'g' )) )
                {
-                       fs_set_gameinfo( arg );
+                       gameinfo = arg;
                }
                
                if( (arg = csr_opt_arg( 'r' )) )
                {
-                       resolution = atoi( arg );
+                       api.resolution = atoi( arg );
                }
                
                if( (arg = csr_long_opt_arg( "padding" )) )
                {
-                       padding = atof( arg );
+                       api.padding = atof( arg );
+               }
+               
+               if( (arg = csr_long_opt_arg( "multi-sample" )) )
+               {
+                       if( !strcmp( arg, "none" ))
+                       {
+                               api.sampling_mode = k_EMSAA_none;
+                       }
+                       else if( !strcmp( arg, "rgss" ))
+                       {
+                               api.sampling_mode = k_EMSAA_RGSS;
+                       }
+                       else if( !strcmp( arg, "2x" ))
+                       {
+                               api.sampling_mode = k_EMSAA_2x2;
+                       }
+                       else if( !strcmp( arg, "8r" ))
+                       {
+                               api.sampling_mode = k_EMSAA_8R;
+                       }
+                       else
+                       {
+                               log_error( "Invalid sampling pattern '%s'\n", arg );
+                               goto IL_CSR_EXIT;
+                       }
+               }
+               
+               if( (arg = csr_long_opt_arg( "extension" )) )
+               {
+                       extension = arg;
                }
+               
+               if( (arg = csr_long_opt_arg( "min" )) )
+                       api.min_z = atof( arg );
+               if( (arg = csr_long_opt_arg( "max" )) )
+                       api.max_z = atof( arg );
 
                if( csr_opt( 'v' ) || csr_long_opt( "version" ) )
                {
-                       printf( "csRadar version: " CSR_VERSION "\n" );
-                       return 0;
+                       printf( "csRadar build: %u, api_version: %u\n", csr_build, csr_api_version );
+                       goto IL_CSR_EXIT;
                }
                
                if( csr_opt( 'h' ) || csr_long_opt( "help" ) )
@@ -104,110 +118,111 @@ int main( int argc, char *argv[] )
                                "Options:\n"
                                "   -g <gameinfo.txt path>         Required if you are loading models\n"
                                "   -r 1024                        Output resolution\n"
-                               "   -o <output>                    Specify output name/path\n"
+                               "   -o <output>                    Specify output name/path (no extension, dir must exist)\n"
+                               "   -e <classname>                 Same as default arg, but instead filters for entity class\n"
                                "   --padding=128                  When cropping radar, add padding units to border\n"
-                               "   --standard-layers              Use standard TAR layers/groups\n"
                                "   --no-txt                       Don't create matching radar txt\n"
-                               "   --multi-sample=                [ none, 2, 4, 4r, 8kn (default), 16c ]\n"
+                               "   --multi-sample=rgss            [ none, 2x, rgss, 8r ]\n"
+                               "   --extension=TAR                Use an extension binary instead\n"
+                               "   --min=z                        Miniumum height to render\n"
+                               "   --max=z                        Maxiumum height to render\n"
                                "\n"
                                "   -v --version                   Display program version\n"
                                "   -h --help                      Display this help text\n"
                        );
                        
-                       return 0;
+                       goto IL_CSR_EXIT;
                }
        }
        
-       if( num_strings )
+       if( api.num_strings )
        {
-               vmf_map *map = vmf_init( strings[0], 1 );
+               if( gameinfo )
+               {
+                       fs_set_gameinfo( gameinfo );
+               }
        
-               if( map )
+               // Path handling
+               if( !output_set )
                {
-                       // Path handling
-                       if( !output_set )
+                       strcpy( api.output_path, api.strings[0].str );
+                       csr_stripext( api.output_path );
+               }
+               
+               strcpy( api.vmf_name, csr_filename( api.output_path ) );
+               strcpy( api.vmf_folder, api.output_path );
+               csr_downlvl( api.vmf_folder );
+               
+               log_info( "output_path: '%s'\n", api.output_path );
+               log_info( "vmf_name: '%s'\n", api.vmf_name );
+               log_info( "vmf_folder: '%s'\n", api.vmf_folder );
+               
+               api.map = vmf_init( api.strings[0].str );
+               if( api.map )
+               {
+                       // Update arg inferred types
+                       api.strings[0].type = k_iftype_vmf;
+                       for( int i = 1; i < api.num_strings; i ++ )
                        {
-                               strcpy( output_path, strings[0] );
-                               csr_stripext( output_path );
+                               if( vmf_visgroup_id( api.map->root, api.strings[i].str ) != -1 )
+                                       api.strings[i].type = k_iftype_visgroup;
+                               else
+                                       api.strings[i].type = k_iftype_classname;
                        }
+               
+                       if( !extension )
+                               extension = "csr_substance";
+               
+                       csr_so ext = csr_libopen( extension );
                        
-                       char *base_name;
-                       if( !(base_name = csr_findext( output_path, '/' ) ))
+                       if( ext )
                        {
-                               base_name = output_path;
-                       }
-                       
-                       strcpy( vmf_name, base_name );
-                       
-                       printf( "output_path: '%s'\nvmf_name: '%s'\n", output_path, vmf_name );
-                       
-                       
-                       // Main
+                               void (*csr_ext_main)(csr_api *);
+                               void (*csr_ext_exit)(csr_api *);
+                               
+                               csr_ext_main = csr_get_proc( ext, "csr_ext_main" );
+                               csr_ext_exit = csr_get_proc( ext, "csr_ext_exit" );
                                        
-                       csr_target target;
-                       
-                       csr_create_target( &target, resolution, resolution );
-                       csr_rt_clear( &target );
-                       
-                       // Compute bounds
-                       csr_filter filter = 
-                       {
-                               .classname = NULL,
-                               .visgroup = NULL,
-                               .compute_bounds_only = 1
-                       };
-                       
-                       // One pass for fitting, second pass for drawing
-                       for( int i = 0; i < 2; i ++ )
-                       {
-                               if( num_strings == 1 )
+                               if( csr_ext_main && csr_ext_exit )
                                {
-                                       // Draw everything
-                                       draw_vmf_group( &target, map, map->root, &filter, NULL, NULL );
-                                       csr_rt_save_buffers( &target, output_path, "all" );
+                                       csr_ext_main( &api );
+                                       
+                                       // Do other
+                                       if( api.write_txt )
+                                       {
+                                               char radar_path[512];
+                                               strcpy( radar_path, api.output_path );
+                                               strcat( radar_path, ".txt" );
+                                               csr_write_txt( radar_path, api.vmf_name, &api.target );
+                                       }
+                                       
+                                       csr_ext_exit( &api );
                                }
                                else
                                {
-                                       // Draw groups
-                                       for( int i = 1; i < num_strings; i ++ )
-                                       {
-                                               filter.visgroup = strings[ i ];
-                                               
-                                               draw_vmf_group( &target, map, map->root, &filter, NULL, NULL );
-                                               csr_rt_save_buffers( &target, output_path, strings[i] );
-                                               
-                                               csr_rt_clear( &target );
-                                       }
+                                       csr_liberr();
                                }
                                
-                               filter.compute_bounds_only = 0;
-                               csr_auto_fit( &target, padding );
+                               csr_libclose( ext );
                        }
-                       
-                       if( write_txt )
+                       else
                        {
-                               char txt_path[ 512 ];
-                               
-                               strcpy( txt_path, output_path );
-                               strcat( txt_path, ".txt" );
-                               
-                               csr_write_txt( txt_path, vmf_name, &target );
+                               csr_liberr();
                        }
                        
-                       csr_rt_free( &target );
-                       vmf_free( map );
+                       vmf_free( api.map );
                }
                else
                {
-                       fprintf( stderr, "Could not load VMF\n" );
+                       log_error( "Could not load VMF\n" );
                }
        }
        else
        {
-               fprintf( stderr, "Missing required argument: mapfile\n" );
+               log_error( "Missing required argument: mapfile\n" );
        }
        
+IL_CSR_EXIT:
        fs_exit();
-
        return 0;
 }