fixed instance loading forget to append basepath.. other path fixes (windows)
[csRadar.git] / csRadar.c
1 // Copyright (C) 2021 Harry Godden (hgn)
2
3 // Building:
4 // gcc -rdynamic csRadar.c -o csRadar -lm -ldl
5 //
6 // Plugins:
7 // gcc -fpic -shared -o ext/my_plugin.so my_plugin.c -lm
8
9 #define VALVE_IMPLEMENTATION
10 #define CSR_EXECUTABLE
11 #include "csRadar.h"
12
13 int main( int argc, char *argv[] )
14 {
15 csr_api api =
16 {
17 .padding = 128.f,
18 .resolution = 1024,
19 .min_z = -INFINITY,
20 .max_z = INFINITY,
21 .write_txt = 1,
22 .api_version = csr_api_version,
23 .sampling_mode = k_EMSAA_RGSS
24 };
25
26 int output_set = 0;
27 char *extension = NULL;
28 char *gameinfo = NULL;
29
30 char *arg;
31 while( csr_argp( argc, argv ) )
32 {
33 if( (arg = csr_arg()) )
34 {
35 if( api.num_strings == 20 )
36 {
37 log_error( "Too many arguments! Max 20\n" );
38 goto IL_CSR_EXIT;
39 }
40
41 api.strings[ api.num_strings ++ ].str = arg;
42 }
43
44 if( (arg = csr_opt_arg( 'o' )) )
45 {
46 strcpy( api.output_path, arg );
47 output_set = 1;
48 }
49
50 if( (arg = csr_opt_arg( 'g' )) )
51 {
52 gameinfo = arg;
53 }
54
55 if( (arg = csr_opt_arg( 'r' )) )
56 {
57 api.resolution = atoi( arg );
58 }
59
60 if( (arg = csr_long_opt_arg( "padding" )) )
61 {
62 api.padding = atof( arg );
63 }
64
65 if( (arg = csr_long_opt_arg( "multi-sample" )) )
66 {
67 if( !strcmp( arg, "none" ))
68 {
69 api.sampling_mode = k_EMSAA_none;
70 }
71 else if( !strcmp( arg, "rgss" ))
72 {
73 api.sampling_mode = k_EMSAA_RGSS;
74 }
75 else if( !strcmp( arg, "2x" ))
76 {
77 api.sampling_mode = k_EMSAA_2x2;
78 }
79 else if( !strcmp( arg, "8r" ))
80 {
81 api.sampling_mode = k_EMSAA_8R;
82 }
83 else
84 {
85 log_error( "Invalid sampling pattern '%s'\n", arg );
86 goto IL_CSR_EXIT;
87 }
88 }
89
90 if( (arg = csr_long_opt_arg( "extension" )) )
91 {
92 extension = arg;
93 }
94
95 if( (arg = csr_long_opt_arg( "min" )) )
96 api.min_z = atof( arg );
97 if( (arg = csr_long_opt_arg( "max" )) )
98 api.max_z = atof( arg );
99
100 if( csr_opt( 'v' ) || csr_long_opt( "version" ) )
101 {
102 printf( "csRadar build: %u, api_version: %u\n", csr_build, csr_api_version );
103 goto IL_CSR_EXIT;
104 }
105
106 if( csr_opt( 'h' ) || csr_long_opt( "help" ) )
107 {
108 // Display help
109 printf
110 (
111 "csRadar Copyright (C) 2021 Harry Godden (hgn)\n"
112 "\n"
113 "Usage: ./csRadar map.vmf -g \"/gamedir/gameinfo.txt\" layout cover\n"
114 " VMF file is first, then any other arguments (eg. layout, cover), will specify\n"
115 " visgroups to be rendered into individual files\n"
116 " No visgroups specified will simply draw everything\n"
117 "\n"
118 "Options:\n"
119 " -g <gameinfo.txt path> Required if you are loading models\n"
120 " -r 1024 Output resolution\n"
121 " -o <output> Specify output name/path (no extension, dir must exist)\n"
122 " -e <classname> Same as default arg, but instead filters for entity class\n"
123 " --padding=128 When cropping radar, add padding units to border\n"
124 " --no-txt Don't create matching radar txt\n"
125 " --multi-sample=rgss [ none, 2x, rgss, 8r ]\n"
126 " --extension=TAR Use an extension binary instead\n"
127 " --min=z Miniumum height to render\n"
128 " --max=z Maxiumum height to render\n"
129 "\n"
130 " -v --version Display program version\n"
131 " -h --help Display this help text\n"
132 );
133
134 goto IL_CSR_EXIT;
135 }
136 }
137
138 if( api.num_strings )
139 {
140 if( gameinfo )
141 {
142 fs_set_gameinfo( gameinfo );
143 }
144
145 // Path handling
146 if( !output_set )
147 {
148 strcpy( api.output_path, api.strings[0].str );
149 csr_stripext( api.output_path );
150 }
151
152 strcpy( api.vmf_name, csr_filename( api.output_path ) );
153 strcpy( api.vmf_folder, api.output_path );
154 csr_downlvl( api.vmf_folder );
155
156 log_info( "output_path: '%s'\n", api.output_path );
157 log_info( "vmf_name: '%s'\n", api.vmf_name );
158 log_info( "vmf_folder: '%s'\n", api.vmf_folder );
159
160 api.map = vmf_init( api.strings[0].str );
161 if( api.map )
162 {
163 // Update arg inferred types
164 api.strings[0].type = k_iftype_vmf;
165 for( int i = 1; i < api.num_strings; i ++ )
166 {
167 if( vmf_visgroup_id( api.map->root, api.strings[i].str ) != -1 )
168 api.strings[i].type = k_iftype_visgroup;
169 else
170 api.strings[i].type = k_iftype_classname;
171 }
172
173 if( !extension )
174 extension = "csr_substance";
175
176 csr_so ext = csr_libopen( extension );
177
178 if( ext )
179 {
180 void (*csr_ext_main)(csr_api *);
181 void (*csr_ext_exit)(csr_api *);
182
183 csr_ext_main = csr_get_proc( ext, "csr_ext_main" );
184 csr_ext_exit = csr_get_proc( ext, "csr_ext_exit" );
185
186 if( csr_ext_main && csr_ext_exit )
187 {
188 csr_ext_main( &api );
189
190 // Do other
191 if( api.write_txt )
192 {
193 char radar_path[512];
194 strcpy( radar_path, api.output_path );
195 strcat( radar_path, ".txt" );
196 csr_write_txt( radar_path, api.vmf_name, &api.target );
197 }
198
199 csr_ext_exit( &api );
200 }
201 else
202 {
203 csr_liberr();
204 }
205
206 csr_libclose( ext );
207 }
208 else
209 {
210 csr_liberr();
211 }
212
213 vmf_free( api.map );
214 }
215 else
216 {
217 log_error( "Could not load VMF\n" );
218 }
219 }
220 else
221 {
222 log_error( "Missing required argument: mapfile\n" );
223 }
224
225 IL_CSR_EXIT:
226 fs_exit();
227 return 0;
228 }