return _pico_normalize_vec( plane );
}
+const picoColor_t picoColor_white = { 255, 255, 255, 255 };
+
/* separate from _pico_set_vec4 */
void _pico_set_color( picoColor_t c, int r, int g, int b, int a ){
c[ 0 ] = r;
c[ 3 ] = a;
}
-void _pico_copy_color( picoColor_t src, picoColor_t dest ){
+void _pico_copy_color( const picoColor_t src, picoColor_t dest ){
dest[ 0 ] = src[ 0 ];
dest[ 1 ] = src[ 1 ];
dest[ 2 ] = src[ 2 ];
return pos;
}
+/* expecting fileName to be relative vfs model path */
+void _pico_deduce_shadername( const char* fileName, const char* srcName, picoShader_t* shader ){
+ if( srcName == NULL || fileName == NULL )
+ return;
+ char name[strlen( srcName ) + 1];
+ strcpy( name, srcName );
+ _pico_unixify( name );
+ _pico_setfext( name, NULL );
+
+ char path[strlen( fileName ) + strlen( name ) + 1];
+ _pico_nofname( fileName, path, strlen( fileName ) + strlen( name ) + 1 );
+ _pico_unixify( path );
+
+ if( !strchr( name , '/' ) ){ /* texture is likely in the folder, where model is */
+ strcat( path, name );
+ }
+ else if( name[0] == '/' || ( name[0] != '\0' && name[1] == ':' ) || strstr( name, ".." ) ){ /* absolute path or with .. */
+ const char* p = name;
+ for (; *p != '\0'; ++p )
+ if ( _pico_strnicmp( p, "/models/", 8 ) == 0 || _pico_strnicmp( p, "/textures/", 10 ) == 0 )
+ break;
+ if( *p != '\0' ){
+ strcpy( path, p + 1 );
+ }
+ else{
+ p = _pico_nopath( name );
+ strcat( path, p );
+ }
+ }
+ else{
+ PicoSetShaderName( shader, name );
+ return;
+ }
+
+ _pico_printf( PICO_NORMAL, "PICO: substituting shader name: %s -> %s", srcName, path );
+ PicoSetShaderName( shader, path );
+}
+
+/* deduce shadernames from bitmap or shadername paths */
+void _pico_deduce_shadernames( picoModel_t *model ){
+ for ( int i = 0; i < model->numShaders; ++i ){
+ /* skip null shaders */
+ if ( model->shader[i] == NULL )
+ continue;
+
+ const char* mapname = model->shader[i]->mapName;
+ const char* shadername = model->shader[i]->name;
+
+ /* Detect intentional material name to not replace it with texture name.
+
+ Reimplement commits by Garux:
+ https://github.com/Garux/netradiant-custom/commit/1bd3e7ae186b55fb61e3738d2493432c0b1f5a7b
+ https://github.com/Garux/netradiant-custom/commit/ea21eee2254fb2e667732d8f1b0f83c439a89bfa
+
+ This attempts to restore proper material behaviour when the mapper knows what he is doing,
+ also called Julius' case or correct case because Julius is always correctâ„¢
+ while keeping the fallback for other situations, also called newbie's case
+ which may be compatible with third-party tools not following Quake 3 conventions.
+
+ See: https://gitlab.com/xonotic/netradiant/-/merge_requests/179#note_777324051 */
+ if ( shadername && *shadername &&
+ ( _pico_strnicmp( shadername, "models/", 7 ) == 0
+ || _pico_strnicmp( shadername, "models\\", 7 ) == 0
+ || _pico_strnicmp( shadername, "textures/", 9 ) == 0
+ || _pico_strnicmp( shadername, "textures\\", 9 ) == 0 ) )
+ {
+ _pico_deduce_shadername( model->fileName, shadername, model->shader[i] );
+ }
+ else if( mapname && *mapname )
+ _pico_deduce_shadername( model->fileName, mapname, model->shader[i] );
+ else if( shadername && *shadername )
+ _pico_deduce_shadername( model->fileName, shadername, model->shader[i] );
+ }
+}
+
/* _pico_parse_skip_white:
* skips white spaces in current pico parser, sets *hasLFs
* to 1 if linefeeds were skipped, and either returns the