int WINAPI QERApp_LoadShadersFromDir (const char* path) { int count = 0; // scan g_Shaders, and call QERApp_Shader_ForName for each in the given path // this will load the texture if needed and will set it in use.. int nSize = g_Shaders.GetSize(); for (int i = 0; i < nSize; i++) { CShader *pShader = reinterpret_cast<CShader*>(g_Shaders.ElementAt(i)); if (strstr(pShader->getShaderFileName(), path) || strstr(pShader->getName(), path)) { count++; // request the shader, this will load the texture if needed and set "inuse" //++timo FIXME: should we put an Activate member on CShader? // this QERApp_Shader_ForName call is a kind of hack IShader *pFoo = QERApp_Shader_ForName(pShader->getName()); #ifdef _DEBUG // check we activated the right shader // NOTE: if there was something else loaded, the size of g_Shaders may have changed and strange behaviours are to be expected if (pFoo != pShader) Sys_Printf("WARNING: unexpected pFoo != pShader in QERApp_LoadShadersFromDir\n"); #endif } } return count; }
void WINAPI QERApp_LoadShaderFile (const char* filename) { char* pBuff = NULL; int nSize = LoadFile(filename, reinterpret_cast<void**>(&pBuff)); if (nSize == -1) nSize = PakLoadAnyFile(filename, reinterpret_cast<void**>(&pBuff)); if (nSize > 0) { Sys_Printf("Parsing shaderfile %s\n", filename); StartTokenParsing(pBuff); while (GetToken(true)) { // first token should be the path + name.. (from base) CShader *pShader = new CShader(); // we want the relative filename only, it's easier for later lookup .. see QERApp_ReloadShaderFile char cTmp[1024]; QE_ConvertDOSToUnixName( cTmp, filename ); pShader->setShaderFileName( filename + strlen(ValueForKey(g_qeglobals.d_project_entity, "basepath")) + 1); if (pShader->Parse()) { // do we already have this shader? //++timo NOTE: this may a bit slow, we may need to use a map instead of a dumb list if (g_Shaders.Shader_ForName( pShader->getName() ) != NULL) { Sys_Printf( "WARNING: shader %s is already in memory, definition in %s ignored.\n", pShader->getName(), filename ); delete pShader; } else { pShader->IncRef(); g_Shaders.Add( (LPVOID)pShader ); int n = g_PrefsDlg.m_nShader; if ((g_PrefsDlg.m_nShader == CPrefsDlg::SHADER_ALL) || (g_PrefsDlg.m_nShader == CPrefsDlg::SHADER_COMMON && strstr(pShader->getName(), "common" ))) // load the qtexture and display in tex wnd pShader->Activate(); } } else { Sys_Printf("Error parsing shader %s\n", pShader->getName()); delete pShader; } } free (pBuff); } else { Sys_Printf("Unabled to read shaderfile %s\n", filename); } }
void WINAPI QERApp_LoadShaderFile (const char *filename) { char *pBuff; int nSize = vfsLoadFile (filename, reinterpret_cast < void **>(&pBuff), 0); if (nSize > 0) { Sys_Printf ("Parsing shaderfile %s\n", filename); g_ScripLibTable.m_pfnStartTokenParsing (pBuff); while (g_ScripLibTable.m_pfnGetToken (true)) { // first token should be the path + name.. (from base) CShader *pShader = new CShader (); // we want the relative filename only, it's easier for later lookup .. see QERApp_ReloadShaderFile char cTmp[1024]; g_FuncTable.m_pfnQE_ConvertDOSToUnixName (cTmp, filename); // given the vfs, we should not store the full path //pShader->setShaderFileName( filename + strlen(ValueForKey(g_qeglobals.d_project_entity, "basepath"))); pShader->setShaderFileName (filename); if (pShader->Parse ()) { // do we already have this shader? //++timo NOTE: this may a bit slow, we may need to use a map instead of a dumb list if (g_Shaders.Shader_ForName (pShader->getName ()) != NULL) { #ifdef _DEBUG Sys_Printf ("WARNING: shader %s is already in memory, definition in %s ignored.\n", pShader->getName (), filename); #endif delete pShader; } else { pShader->IncRef (); g_Shaders.Add ((void *) pShader); } } else { Sys_Printf ("Error parsing shader %s\n", pShader->getName ()); delete pShader; } } vfsFreeFile (pBuff); } else { Sys_Printf ("Unable to read shaderfile %s\n", filename); } }
IShader* WINAPI QERApp_Shader_ForName(const char* name) { //++timo FIXME: do we allow NULL and "" calling? // how does it deal with notexture? can we simply replace by "textures/radiant/notex"? if (name == NULL || strlen(name) == 0) { Sys_Printf("FIXME: name == NULL || strlen(name) == 0 in QERApp_Shader_ForName\n"); return QERApp_Shader_ForName("radiant/notex"); //++timo ??? } // entities that should be represented with plain colors instead of textures // request a texture name with (r g b) (it's stored in their class_t) if (name[0]=='(') { return QERApp_ColorShader_ForName(name); } CShader* pShader = static_cast<CShader*>(QERApp_Try_Shader_ForName( name )); if (pShader) { pShader->SetDisplayed( true ); return pShader; } // we don't know this shader, maybe it's a straight texture pShader = new CShader; pShader->CreateDefault( name ); // hook it into the shader list g_Shaders.Add( (LPVOID)pShader ); pShader->IncRef(); // if it can't find the texture, "textures/radiant/notex" will be used pShader->Activate(); pShader->SetDisplayed( true ); return pShader; }
int WINAPI QERApp_HasShader( const char *pName ) { // mickey check the global shader array for existense of pName CShader* pShader = g_Shaders.Shader_ForName( pName ); if (pShader) return 1; return 0; }
IShader *WINAPI QERApp_ColorShader_ForName( const char *name ){ CShader *pShader = new CShader(); pShader->CreateColor( name ); // hook it into the shader list pShader->IncRef(); g_Shaders.Add( (void *) pShader ); return pShader; }
void WINAPI QERApp_ReloadShaderFile( const char* name ) { brush_t *b; face_t *f; #ifdef _DEBUG // check the shader name is a reletive path // I hacked together a few quick tests to make sure :-) if (strstr( name, ":\\" ) || !strstr( name, "scripts" )) Sys_Printf("WARNING: is %s a reletive path to a shader file? (QERApp_ReloadShaderFile\n"); #endif // in the actives and global shaders lists, decref and unhook the shaders //++timo NOTE: maybe we'd like to keep track of the shaders we are unhooking? g_ActiveShaders.ReleaseForShaderFile( name ); g_Shaders.ReleaseForShaderFile( name ); // go through a reload of the shader file QERApp_LoadShaderFile( name ); // scan all the brushes, replace all the old ones by refs to their new equivalents for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=b->next) { if (b->patchBrush && !strcmp(b->pPatch->pShader->getShaderFileName(), name)) SetShader(b->pPatch); else for (f=b->brush_faces ; f ; f=f->next) if (!strcmp(f->pShader->getShaderFileName(), name)) SetShader(f); } for (b=selected_brushes.next ; b != NULL && b != &selected_brushes ; b=b->next) { if (b->patchBrush && !strcmp(b->pPatch->pShader->getShaderFileName(), name)) SetShader(b->pPatch); else for (f=b->brush_faces ; f ; f=f->next) if (!strcmp(f->pShader->getShaderFileName(), name)) SetShader(f); } // call Texture_ShowInUse to clean and display only what's required Texture_ShowInuse(); // Texture_SortTextures(); QERApp_SortActiveShaders(); Sys_UpdateWindows (W_TEXTURE); }
IShader* WINAPI QERApp_Try_Shader_ForName(const char* name) { // look for the shader CShader* pShader = g_Shaders.Shader_ForName( name ); if (!pShader) // not found return NULL; // we may need to load the texture or use the "shader without texture" one pShader->Activate(); pShader->SetDisplayed( true ); return pShader; }
void CShader::RegisterActivate(){ // fill the qtexture_t with shader information //++timo FIXME: a lot of that won't be necessary, will be stored at IShader* level // strcpy (m_pTexture->shadername, m_Name); // this flag is set only if we have a shaderfile name // if (m_ShaderFileName[0] != '\0') // m_pTexture->bFromShader = true; // else // m_pTexture->bFromShader = false; //++timo FIXME: what do we do with that? //m_pTexture->fTrans = pInfo->m_fTransValue; // m_pTexture->fTrans = 1.0f; // if != 1.0 it's ot getting drawn in Cam_Draw // m_pTexture->nShaderFlags = m_nFlags; // store in the active shaders list (if necessary) g_ActiveShaders.AddSingle( this ); // when you activate a shader, it gets displayed in the texture browser m_bDisplayed = true; IncRef(); }
IShader *WINAPI QERApp_CreateShader_ForTextureName( const char *name ){ CShader *pShader; pShader = new CShader; // CreateDefault expects a texture / shader name relative to the "textures" directory // (cause shader names are reletive to "textures/") pShader->CreateDefault( name ); // hook it into the shader list g_Shaders.Add( (void *) pShader ); pShader->IncRef(); // if it can't find the texture, SHADER_NOT_FOUND will be used // Hydra: display an error message, so the user can quickly find a list of missing // textures by looking at the console. if ( !pShader->Activate() ) { Sys_Printf( "WARNING: Activate shader failed for %s\n",pShader->getName() ); } pShader->SetDisplayed( true ); return pShader; }
// will sort the active shaders list by name // NOTE: it would be easier if the thing would stay sorted by using a map<name,CShader> thing //++timo FIXME: would need to export that to allow external override? void WINAPI QERApp_SortActiveShaders() { g_ActiveShaders.SortShaders(); }
IShader* WINAPI QERApp_Shader_ForName_NoLoad( const char *pName ) { CShader* pShader = g_Shaders.Shader_ForName( pName ); return pShader; }
void WINAPI QERApp_ReloadShaderFile( const char *name ){ brush_t *b; face_t *f; brush_t *active_brushes; brush_t *selected_brushes; brush_t *filtered_brushes; // Sys_Printf("TODO: QERApp_ReloadShaderFile\n"); active_brushes = g_DataTable.m_pfnActiveBrushes(); selected_brushes = g_DataTable.m_pfnSelectedBrushes(); filtered_brushes = g_DataTable.m_pfnFilteredBrushes(); #ifdef _DEBUG // check the shader name is a reletive path // I hacked together a few quick tests to make sure :-) if ( strstr( name, ":\\" ) || !strstr( name, "scripts" ) ) { Sys_Printf( "WARNING: is %s a reletive path to a shader file? (QERApp_ReloadShaderFile\n" ); } #endif // in the actives and global shaders lists, decref and unhook the shaders //++timo NOTE: maybe we'd like to keep track of the shaders we are unhooking? g_ActiveShaders.ReleaseForShaderFile( name ); g_Shaders.ReleaseForShaderFile( name ); // go through a reload of the shader file QERApp_LoadShaderFile( name ); // scan all the brushes, replace all the old ones by refs to their new equivalents for ( b = active_brushes->next; b != NULL && b != active_brushes; b = b->next ) { if ( b->patchBrush && !strcmp( b->pPatch->pShader->getShaderFileName(), name ) ) { SetShader( b->pPatch ); } else{ for ( f = b->brush_faces; f; f = f->next ) if ( !strcmp( f->pShader->getShaderFileName(), name ) ) { SetShader( f ); } } } for ( b = selected_brushes->next; b != NULL && b != selected_brushes; b = b->next ) { if ( b->patchBrush && !strcmp( b->pPatch->pShader->getShaderFileName(), name ) ) { SetShader( b->pPatch ); } else{ for ( f = b->brush_faces; f; f = f->next ) if ( !strcmp( f->pShader->getShaderFileName(), name ) ) { SetShader( f ); } } } // do that to the filtered brushes as well (we might have some region compiling going on) for ( b = filtered_brushes->next; b != NULL && b != filtered_brushes; b = b->next ) { if ( b->patchBrush && !strcmp( b->pPatch->pShader->getShaderFileName(), name ) ) { SetShader( b->pPatch ); } else{ for ( f = b->brush_faces; f; f = f->next ) if ( !strcmp( f->pShader->getShaderFileName(), name ) ) { SetShader( f ); } } } // call Texture_ShowInUse to clean and display only what's required g_ShadersTable.m_pfnTexture_ShowInuse(); QERApp_SortActiveShaders(); g_FuncTable.m_pfnSysUpdateWindows( W_TEXTURE ); }
IShader *WINAPI QERApp_ActiveShader_ForTextureName (char *name) { return g_ActiveShaders.Shader_ForTextureName (name); }
// will free all GL binded qtextures and shaders // NOTE: doesn't make much sense out of Radiant exit or called during a reload void WINAPI QERApp_FreeShaders () { int i; brush_t *b; brush_t *active_brushes; brush_t *selected_brushes; brush_t *filtered_brushes; qtexture_t **d_qtextures; active_brushes = g_DataTable.m_pfnActiveBrushes (); selected_brushes = g_DataTable.m_pfnSelectedBrushes (); filtered_brushes = g_DataTable.m_pfnFilteredBrushes (); d_qtextures = g_ShadersTable.m_pfnQTextures (); // store the shader names used by the patches for (i = 0; i < PatchShaders.GetSize (); i++) delete static_cast < patchMesh_t * >(PatchShaders.GetAt (i)); PatchShaders.RemoveAll (); for (b = active_brushes->next; b != NULL && b != active_brushes; b = b->next) { if (b->patchBrush) PushPatch (b->pPatch); } for (b = selected_brushes->next; b != NULL && b != selected_brushes; b = b->next) { if (b->patchBrush) PushPatch (b->pPatch); } for (b = filtered_brushes->next; b != NULL && b != filtered_brushes; b = b->next) { if (b->patchBrush) PushPatch (b->pPatch); } // reload shaders // empty the actives shaders list g_ActiveShaders.ReleaseAll (); g_Shaders.ReleaseAll (); // empty the main g_qeglobals.d_qtextures list // FIXME: when we reload later on, we need to have the shader names // for brushes it's stored in the texdef // but patches don't have texdef // see bug 104655 for details // so the solution, build an array of patchMesh_t* and their shader names #ifdef _DEBUG Sys_Printf ("FIXME: patch shader reload workaround (old fenris? bug 104655)\n"); #endif //GtkWidget *widget = g_QglTable.m_pfn_GetQeglobalsGLWidget (); GHashTable *texmap = g_ShadersTable.m_pfnQTexmap (); // NOTE: maybe before we'd like to set all qtexture_t in the shaders list to notex? // NOTE: maybe there are some qtexture_t we don't want to erase? For plain color faces maybe? while (*d_qtextures) { qtexture_t *pTex = *d_qtextures; qtexture_t *pNextTex = pTex->next; //if (widget != NULL) g_QglTable.m_pfn_qglDeleteTextures (1, &pTex->texture_number); g_hash_table_remove (texmap, pTex->name); // all qtexture_t should be manipulated with the glib alloc handlers for now g_free (pTex); *d_qtextures = pNextTex; } g_QglTable.m_pfn_QE_CheckOpenGLForErrors (); }
int WINAPI QERApp_GetActiveShaderCount () { return g_ActiveShaders.GetSize(); }
IShader* WINAPI QERApp_ActiveShader_ForIndex (int i) { return static_cast<CShader *>(g_ActiveShaders.GetAt(i)); }
// Set the IsDisplayed flag on all active shaders void WINAPI QERApp_ActiveShaders_SetDisplayed(bool b) { g_ActiveShaders.SetDisplayed(b); }
void WINAPI QERApp_ActiveShaders_SetInUse(bool b) { g_ActiveShaders.SetInUse(b); }
// will free all GL binded qtextures and shaders // NOTE: doesn't make much sense out of Radiant exit or called during a reload void WINAPI QERApp_FreeShaders() { int i; brush_t *b; // store the shader names used by the patches for(i=0; i<PatchShaders.GetSize(); i++) delete PatchShaders.GetAt(i); PatchShaders.RemoveAll(); for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=b->next) { if (b->patchBrush) PushPatch(b->pPatch); } for (b=selected_brushes.next ; b != NULL && b != &selected_brushes ; b=b->next) { if (b->patchBrush) PushPatch(b->pPatch); } // reload shaders // empty the actives shaders list g_ActiveShaders.ReleaseAll(); g_Shaders.ReleaseAll(); // empty the main g_qeglobals.d_qtextures list // FIXME: when we reload later on, we need to have the shader names // for brushes it's stored in the texdef // but patches don't have texdef // see bug 104655 for details // so the solution, build an array of patchMesh_t* and their shader names #ifdef _DEBUG Sys_Printf("FIXME: bug 104655 workaround\n"); #endif // NOTE: maybe before we'd like to set all qtexture_t in the shaders list to notex? // NOTE: maybe there are some qtexture_t we don't want to erase? For plain color faces maybe? // NOTE: the GL textures are freed later on if (g_qeglobals.d_qtextures) { qtexture_t* pTex = g_qeglobals.d_qtextures->next; while (pTex != NULL && pTex != g_qeglobals.d_qtextures) { qtexture_t* pNextTex = pTex->next; if (g_qeglobals.bSurfacePropertiesPlugin) { // Timo // Surface properties plugin #ifdef _DEBUG if ( !pTex->pData ) Sys_Printf("WARNING: found a qtexture_t* with no IPluginQTexture\n"); #endif if ( pTex->pData ) GETPLUGINTEXDEF(pTex)->DecRef(); } free(pTex); pTex = pNextTex; } } // free GL bindings GLuint* pGln = new GLuint[texture_extension_number-1]; qglGenTextures(texture_extension_number-1, pGln); QE_CheckOpenGLForErrors(); qglDeleteTextures(texture_extension_number-1, pGln); QE_CheckOpenGLForErrors(); delete []pGln; texture_extension_number = 1; g_qeglobals.d_qtextures = NULL; // free the map g_qeglobals.d_qtexmap->RemoveAll(); }