9f05c2b02aaafd6fc105a6182dd82e5b1e13230f
[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 .write_txt = 1,
20 .api_version = csr_api_version,
21 .sampling_mode = k_EMSAA_RGSS
22 };
23
24 int output_set = 0;
25 char *extension = NULL;
26 char *gameinfo = NULL;
27
28 char *arg;
29 while( csr_argp( argc, argv ) )
30 {
31 if( (arg = csr_arg()) )
32 {
33 if( api.num_strings == 20 )
34 {
35 log_error( "Too many arguments! Max 20\n" );
36 goto IL_CSR_EXIT;
37 }
38
39 api.strings[ api.num_strings ++ ].str = arg;
40 }
41
42 if( (arg = csr_opt_arg( 'o' )) )
43 {
44 strcpy( api.output_path, arg );
45 csr_path_winunix( api.output_path );
46
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( csr_opt( 'v' ) || csr_long_opt( "version" ) )
96 {
97 printf( "csRadar build: %u, api_version: %u\n", csr_build, csr_api_version );
98 goto IL_CSR_EXIT;
99 }
100
101 if( csr_opt( 'h' ) || csr_long_opt( "help" ) )
102 {
103 // Display help
104 printf
105 (
106 "csRadar Copyright (C) 2021 Harry Godden (hgn)\n"
107 "\n"
108 "Usage: ./csRadar map.vmf -g \"/gamedir/gameinfo.txt\" layout cover\n"
109 " VMF file is first, then any other arguments (eg. layout, cover), will specify\n"
110 " visgroups to be rendered into individual files\n"
111 " No visgroups specified will simply draw everything\n"
112 "\n"
113 "Options:\n"
114 " -g <gameinfo.txt path> Required if you are loading models\n"
115 " -r 1024 Output resolution\n"
116 " -o <output> Specify output name/path\n"
117 " -e <classname> Same as default arg, but instead filters for entity class\n"
118 //" -s <height> Add a vertical split at this height\n"
119 " --padding=128 When cropping radar, add padding units to border\n"
120 //" --standard-layers Use standard TAR layers/groups\n"
121 " --no-txt Don't create matching radar txt\n"
122 " --multi-sample=RGSS [ none, 2x, rgss, 8r ]\n"
123 " --extension=TAR Use an extension binary instead\n"
124 "\n"
125 " -v --version Display program version\n"
126 " -h --help Display this help text\n"
127 );
128
129 goto IL_CSR_EXIT;
130 }
131 }
132
133 if( api.num_strings )
134 {
135 if( gameinfo )
136 {
137 fs_set_gameinfo( gameinfo );
138 }
139
140 // Path handling
141 if( !output_set )
142 {
143 strcpy( api.output_path, api.strings[0].str );
144 csr_stripext( api.output_path );
145 }
146
147 char *base_name;
148 if( !(base_name = csr_findext( api.output_path, '/' ) ))
149 {
150 base_name = api.output_path;
151 }
152
153 strcpy( api.vmf_name, base_name );
154
155 log_info( "output_path: '%s'\n", api.output_path );
156 log_info( "vmf_name: '%s'\n", api.vmf_name );
157
158 api.map = vmf_init( api.strings[0].str );
159 if( api.map )
160 {
161 // Update arg inferred types
162 api.strings[0].type = k_iftype_vmf;
163 for( int i = 1; i < api.num_strings; i ++ )
164 {
165 if( vmf_visgroup_id( api.map->root, api.strings[i].str ) != -1 )
166 api.strings[i].type = k_iftype_visgroup;
167 else
168 api.strings[i].type = k_iftype_classname;
169 }
170
171 if( !extension )
172 extension = "csRadarFree";
173
174 csr_so ext = csr_libopen( extension );
175
176 if( ext )
177 {
178 void (*csr_ext_main)(csr_api *);
179 void (*csr_ext_exit)(csr_api *);
180
181 csr_ext_main = csr_get_proc( ext, "csr_ext_main" );
182 csr_ext_exit = csr_get_proc( ext, "csr_ext_exit" );
183
184 if( csr_ext_main && csr_ext_exit )
185 {
186 csr_ext_main( &api );
187
188 // Do other
189
190 csr_ext_exit( &api );
191 }
192 else
193 {
194 csr_liberr();
195 }
196
197 csr_libclose( ext );
198 }
199 else
200 {
201 csr_liberr();
202 }
203
204 vmf_free( api.map );
205 }
206 else
207 {
208 log_error( "Could not load VMF\n" );
209 }
210 }
211 else
212 {
213 log_error( "Missing required argument: mapfile\n" );
214 }
215
216 IL_CSR_EXIT:
217 fs_exit();
218 return 0;
219 }