From 957d2ffe8155ea5afa18055949ded3e6038de248 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Mon, 11 Feb 2019 02:31:14 +0100 Subject: [PATCH] Revert partially (manual) "reformat code! now the code is only ugly on the *inside*" This reverts commit 9dfae1c9b270ee369c6362903a9205b30751b95f. But only for files whose changes that were manually reverted. --- contrib/bobtoolz/DEntity.cpp | 1043 +++-- plugins/imagepng/plugin.cpp | 287 +- plugins/iqmmodel/iqm.h | 1 - plugins/iqmmodel/plugin.h | 1 - plugins/mapq3/plugin.cpp | 1028 +++-- plugins/mapq3/write.cpp | 162 +- plugins/mapq3/write.h | 2 +- plugins/mapxml/plugin.cpp | 103 +- plugins/shaders/shaders.cpp | 2983 ++++++++------- radiant/brush.h | 6891 ++++++++++++++++------------------ radiant/brushmanip.cpp | 2042 +++++----- radiant/csg.cpp | 1018 +++-- radiant/csg.h | 31 +- radiant/entity.cpp | 1002 +++-- radiant/environment.cpp | 439 ++- radiant/mainframe.cpp | 4855 ++++++++++++------------ radiant/map.cpp | 3379 ++++++++--------- radiant/multimon.cpp | 112 +- radiant/qe3.cpp | 515 ++- radiant/referencecache.cpp | 1225 +++--- radiant/renderstate.cpp | 3779 +++++++++---------- radiant/texwindow.cpp | 4278 ++++++++++----------- 22 files changed, 17056 insertions(+), 18120 deletions(-) diff --git a/contrib/bobtoolz/DEntity.cpp b/contrib/bobtoolz/DEntity.cpp index d764c312..5a4d8e57 100644 --- a/contrib/bobtoolz/DEntity.cpp +++ b/contrib/bobtoolz/DEntity.cpp @@ -55,651 +55,622 @@ #include "scenelib.h" -const char *brushEntityList[] = { - "worldspawn", - "trigger_always", - "trigger_hurt", - "trigger_multiple", - "trigger_push", - "trigger_teleport", - "func_bobbing", - "func_button", - "func_door", - "func_group", - "func_pendulum", - "func_plat", - "func_rotating", - "func_static", - "func_timer", - "func_train", - 0 +const char* brushEntityList[] = { + "worldspawn", + "trigger_always", + "trigger_hurt", + "trigger_multiple", + "trigger_push", + "trigger_teleport", + "func_bobbing", + "func_button", + "func_door", + "func_group", + "func_pendulum", + "func_plat", + "func_rotating", + "func_static", + "func_timer", + "func_train", + 0 }; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// -DEntity::DEntity(const char *classname, int ID) -{ - SetClassname(classname); - m_nID = ID; - QER_Entity = NULL; +DEntity::DEntity( const char *classname, int ID ){ + SetClassname( classname ); + m_nID = ID; + QER_Entity = NULL; } -DEntity::~DEntity() -{ - ClearPatches(); - ClearBrushes(); - ClearEPairs(); +DEntity::~DEntity(){ + ClearPatches(); + ClearBrushes(); + ClearEPairs(); } ////////////////////////////////////////////////////////////////////// // Implementation ////////////////////////////////////////////////////////////////////// -void DEntity::ClearBrushes() -{ - for (std::list::const_iterator deadBrush = brushList.begin(); deadBrush != brushList.end(); deadBrush++) { - delete *deadBrush; - } - brushList.clear(); +void DEntity::ClearBrushes(){ + for ( std::list::const_iterator deadBrush = brushList.begin(); deadBrush != brushList.end(); deadBrush++ ) + { + delete *deadBrush; + } + brushList.clear(); } -void DEntity::ClearPatches() -{ - for (std::list::const_iterator deadPatch = patchList.begin(); deadPatch != patchList.end(); deadPatch++) { - delete *deadPatch; - } - patchList.clear(); -} +void DEntity::ClearPatches(){ + for ( std::list::const_iterator deadPatch = patchList.begin(); deadPatch != patchList.end(); deadPatch++ ) + { + delete *deadPatch; + } + patchList.clear(); +} + +DPatch* DEntity::NewPatch(){ + DPatch* newPatch = new DPatch; + + patchList.push_back( newPatch ); + + return newPatch; +} -DPatch *DEntity::NewPatch() -{ - DPatch *newPatch = new DPatch; +DBrush* DEntity::NewBrush( int ID ){ + DBrush* newBrush = new DBrush( ID ); - patchList.push_back(newPatch); + brushList.push_back( newBrush ); - return newPatch; + return newBrush; } -DBrush *DEntity::NewBrush(int ID) -{ - DBrush *newBrush = new DBrush(ID); - - brushList.push_back(newBrush); +char* getNextBracket( char* s ){ + char* p = s; + while ( *p ) + { + p++; + if ( *p == '(' ) { + break; + } + } - return newBrush; + return p; } -char *getNextBracket(char *s) -{ - char *p = s; - while (*p) { - p++; - if (*p == '(') { - break; - } - } +bool DEntity::LoadFromPrt( char *filename ){ + CPortals portals; + strcpy( portals.fn, filename ); + portals.Load(); - return p; -} + if ( portals.node_count == 0 ) { + return false; + } -bool DEntity::LoadFromPrt(char *filename) -{ - CPortals portals; - strcpy(portals.fn, filename); - portals.Load(); - - if (portals.node_count == 0) { - return false; - } - - ClearBrushes(); - ClearEPairs(); - - bool build = false; - for (unsigned int i = 0; i < portals.node_count; i++) { - build = false; - DBrush *brush = NewBrush(); - - for (unsigned int j = 0; j < portals.node[i].portal_count; j++) { - for (unsigned int k = 0; k < portals.node[i].portal[j].point_count - 2; k++) { - vec3_t v1{}, v2{}, normal{}, n{}; - VectorSubtract(portals.node[i].portal[j].point[k + 2].p, portals.node[i].portal[j].point[k + 1].p, v1); - VectorSubtract(portals.node[i].portal[j].point[k].p, portals.node[i].portal[j].point[k + 1].p, v2); - CrossProduct(v1, v2, n); - VectorNormalize(n, v2); - - if (k == 0) { - VectorCopy(v2, normal); - } else { - VectorSubtract(v2, normal, v1); - if (VectorLength(v1) > 0.01) { - build = true; - break; - } - } - } - - if (!build) { - brush->AddFace(portals.node[i].portal[j].point[2].p, portals.node[i].portal[j].point[1].p, - portals.node[i].portal[j].point[0].p, "textures/common/caulk", false); - } else { - brush->AddFace(portals.node[i].portal[j].point[0].p, portals.node[i].portal[j].point[1].p, - portals.node[i].portal[j].point[2].p, "textures/common/caulk", false); - } - } - if (build) { - brush->BuildInRadiant(false, NULL); - } - } - - return true; -} - -DPlane *DEntity::AddFaceToBrush(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData *faceData, int ID) -{ - DBrush *buildBrush = GetBrushForID(ID); - return buildBrush->AddFace(va, vb, vc, faceData); - // slow, dont use much + ClearBrushes(); + ClearEPairs(); + + bool build = false; + for ( unsigned int i = 0; i < portals.node_count; i++ ) + { + build = false; + DBrush* brush = NewBrush(); + + for ( unsigned int j = 0; j < portals.node[i].portal_count; j++ ) + { + for ( unsigned int k = 0; k < portals.node[i].portal[j].point_count - 2; k++ ) + { + vec3_t v1{}, v2{}, normal{}, n{}; + VectorSubtract( portals.node[i].portal[j].point[k + 2].p, portals.node[i].portal[j].point[k + 1].p, v1 ); + VectorSubtract( portals.node[i].portal[j].point[k].p, portals.node[i].portal[j].point[k + 1].p, v2 ); + CrossProduct( v1, v2, n ); + VectorNormalize( n, v2 ); + + if ( k == 0 ) { + VectorCopy( v2, normal ); + } + else + { + VectorSubtract( v2, normal, v1 ); + if ( VectorLength( v1 ) > 0.01 ) { + build = true; + break; + } + } + } + + if ( !build ) { + brush->AddFace( portals.node[i].portal[j].point[2].p, portals.node[i].portal[j].point[1].p, portals.node[i].portal[j].point[0].p, "textures/common/caulk", false ); + } + else{ + brush->AddFace( portals.node[i].portal[j].point[0].p, portals.node[i].portal[j].point[1].p, portals.node[i].portal[j].point[2].p, "textures/common/caulk", false ); + } + } + if ( build ) { + brush->BuildInRadiant( false, NULL ); + } + } + + return true; } -DBrush *DEntity::GetBrushForID(int ID) -{ - DBrush *buildBrush = NULL; +DPlane* DEntity::AddFaceToBrush( vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* faceData, int ID ){ + DBrush* buildBrush = GetBrushForID( ID ); + return buildBrush->AddFace( va, vb, vc, faceData ); + // slow, dont use much +} - for (std::list::const_iterator chkBrush = brushList.begin(); chkBrush != brushList.end(); chkBrush++) { - if ((*chkBrush)->m_nBrushID == ID) { - buildBrush = (*chkBrush); - break; - } - } +DBrush* DEntity::GetBrushForID( int ID ){ + DBrush* buildBrush = NULL; - if (!buildBrush) { - buildBrush = NewBrush(ID); - } + for ( std::list::const_iterator chkBrush = brushList.begin(); chkBrush != brushList.end(); chkBrush++ ) + { + if ( ( *chkBrush )->m_nBrushID == ID ) { + buildBrush = ( *chkBrush ); + break; + } + } - return buildBrush; + if ( !buildBrush ) { + buildBrush = NewBrush( ID ); + } + + return buildBrush; } template -class BrushSelectedVisitor : public SelectionSystem::Visitor { - const Functor &m_functor; +class BrushSelectedVisitor : public SelectionSystem::Visitor +{ +const Functor& m_functor; public: - BrushSelectedVisitor(const Functor &functor) : m_functor(functor) - { - } - - void visit(scene::Instance &instance) const - { - if (Node_isBrush(instance.path().top())) { - m_functor(instance); - } - } +BrushSelectedVisitor( const Functor& functor ) : m_functor( functor ){ +} +void visit( scene::Instance& instance ) const { + if ( Node_isBrush( instance.path().top() ) ) { + m_functor( instance ); + } +} }; template -inline const Functor &Scene_forEachSelectedBrush(const Functor &functor) -{ - GlobalSelectionSystem().foreachSelected(BrushSelectedVisitor(functor)); - return functor; +inline const Functor& Scene_forEachSelectedBrush( const Functor& functor ){ + GlobalSelectionSystem().foreachSelected( BrushSelectedVisitor( functor ) ); + return functor; } -void DEntity_loadBrush(DEntity &entity, scene::Instance &brush) -{ - DBrush *loadBrush = entity.NewBrush(static_cast( entity.brushList.size())); - loadBrush->LoadFromBrush(brush, true); +void DEntity_loadBrush( DEntity& entity, scene::Instance& brush ){ + DBrush* loadBrush = entity.NewBrush( static_cast( entity.brushList.size() ) ); + loadBrush->LoadFromBrush( brush, true ); } -typedef ReferenceCaller DEntityLoadBrushCaller; +typedef ReferenceCaller DEntityLoadBrushCaller; -void DEntity::LoadSelectedBrushes() -{ - ClearBrushes(); - ClearEPairs(); +void DEntity::LoadSelectedBrushes(){ + ClearBrushes(); + ClearEPairs(); - Scene_forEachSelectedBrush(DEntityLoadBrushCaller(*this)); + Scene_forEachSelectedBrush( DEntityLoadBrushCaller( *this ) ); } template -class PatchSelectedVisitor : public SelectionSystem::Visitor { - const Functor &m_functor; +class PatchSelectedVisitor : public SelectionSystem::Visitor +{ +const Functor& m_functor; public: - PatchSelectedVisitor(const Functor &functor) : m_functor(functor) - { - } - - void visit(scene::Instance &instance) const - { - if (Node_isPatch(instance.path().top())) { - m_functor(instance); - } - } +PatchSelectedVisitor( const Functor& functor ) : m_functor( functor ){ +} +void visit( scene::Instance& instance ) const { + if ( Node_isPatch( instance.path().top() ) ) { + m_functor( instance ); + } +} }; template -inline const Functor &Scene_forEachSelectedPatch(const Functor &functor) -{ - GlobalSelectionSystem().foreachSelected(PatchSelectedVisitor(functor)); - return functor; +inline const Functor& Scene_forEachSelectedPatch( const Functor& functor ){ + GlobalSelectionSystem().foreachSelected( PatchSelectedVisitor( functor ) ); + return functor; } -void DEntity_loadPatch(DEntity &entity, scene::Instance &patch) -{ - DPatch *loadPatch = entity.NewPatch(); - loadPatch->LoadFromPatch(patch); +void DEntity_loadPatch( DEntity& entity, scene::Instance& patch ){ + DPatch* loadPatch = entity.NewPatch(); + loadPatch->LoadFromPatch( patch ); } -typedef ReferenceCaller DEntityLoadPatchCaller; +typedef ReferenceCaller DEntityLoadPatchCaller; -void DEntity::LoadSelectedPatches() -{ - ClearPatches(); - ClearEPairs(); +void DEntity::LoadSelectedPatches(){ + ClearPatches(); + ClearEPairs(); - Scene_forEachSelectedPatch(DEntityLoadPatchCaller(*this)); + Scene_forEachSelectedPatch( DEntityLoadPatchCaller( *this ) ); } -bool *DEntity::BuildIntersectList() -{ - int max = GetIDMax(); - if (max == 0) { - return NULL; - } +bool* DEntity::BuildIntersectList(){ + int max = GetIDMax(); + if ( max == 0 ) { + return NULL; + } - bool *pbIntList = new bool[max]; - memset(pbIntList, 0, sizeof(bool) * (max)); + bool* pbIntList = new bool[max]; + memset( pbIntList, 0, sizeof( bool ) * ( max ) ); - for (std::list::const_iterator pB1 = brushList.begin(); pB1 != brushList.end(); pB1++) { - std::list::const_iterator pB2 = pB1; - for (pB2++; pB2 != brushList.end(); pB2++) { - if ((*pB1)->IntersectsWith((*pB2))) { - pbIntList[(*pB1)->m_nBrushID] = true; - pbIntList[(*pB2)->m_nBrushID] = true; - } - } - } + for ( std::list::const_iterator pB1 = brushList.begin(); pB1 != brushList.end(); pB1++ ) + { + std::list::const_iterator pB2 = pB1; + for ( pB2++; pB2 != brushList.end(); pB2++ ) + { + if ( ( *pB1 )->IntersectsWith( ( *pB2 ) ) ) { + pbIntList[( *pB1 )->m_nBrushID] = true; + pbIntList[( *pB2 )->m_nBrushID] = true; + } + } + } - return pbIntList; + return pbIntList; } -bool *DEntity::BuildDuplicateList() -{ - int max = GetIDMax(); - if (max == 0) { - return NULL; - } +bool* DEntity::BuildDuplicateList(){ + int max = GetIDMax(); + if ( max == 0 ) { + return NULL; + } - bool *pbDupList = new bool[max]; - memset(pbDupList, 0, sizeof(bool) * (max)); + bool* pbDupList = new bool[max]; + memset( pbDupList, 0, sizeof( bool ) * ( max ) ); - for (std::list::const_iterator pB1 = brushList.begin(); pB1 != brushList.end(); pB1++) { - std::list::const_iterator pB2 = pB1; - for (pB2++; pB2 != brushList.end(); pB2++) { - if (**pB1 == *pB2) { - pbDupList[(*pB1)->m_nBrushID] = true; - pbDupList[(*pB2)->m_nBrushID] = true; - } - } - } + for ( std::list::const_iterator pB1 = brushList.begin(); pB1 != brushList.end(); pB1++ ) + { + std::list::const_iterator pB2 = pB1; + for ( pB2++; pB2 != brushList.end(); pB2++ ) + { + if ( **pB1 == *pB2 ) { + pbDupList[( *pB1 )->m_nBrushID] = true; + pbDupList[( *pB2 )->m_nBrushID] = true; + } + } + } - return pbDupList; + return pbDupList; } -void DEntity::SelectBrushes(bool *selectList) -{ - if (selectList == NULL) { - return; - } +void DEntity::SelectBrushes( bool *selectList ){ + if ( selectList == NULL ) { + return; + } - GlobalSelectionSystem().setSelectedAll(false); + GlobalSelectionSystem().setSelectedAll( false ); - scene::Path path(NodeReference(GlobalSceneGraph().root())); - path.push(NodeReference(*QER_Entity)); + scene::Path path( NodeReference( GlobalSceneGraph().root() ) ); + path.push( NodeReference( *QER_Entity ) ); - for (std::list::const_iterator pBrush = brushList.begin(); pBrush != brushList.end(); pBrush++) { - if (selectList[(*pBrush)->m_nBrushID]) { - path.push(NodeReference(*(*pBrush)->QER_brush)); - Instance_getSelectable(*GlobalSceneGraph().find(path))->setSelected(true); - path.pop(); - } - } + for ( std::list::const_iterator pBrush = brushList.begin(); pBrush != brushList.end(); pBrush++ ) + { + if ( selectList[( *pBrush )->m_nBrushID] ) { + path.push( NodeReference( *( *pBrush )->QER_brush ) ); + Instance_getSelectable( *GlobalSceneGraph().find( path ) )->setSelected( true ); + path.pop(); + } + } } -bool DEntity::LoadFromEntity(scene::Node &ent, bool bLoadPatches) -{ - ClearPatches(); - ClearBrushes(); - ClearEPairs(); - - QER_Entity = &ent; - - LoadEPairList(Node_getEntity(ent)); - - bool keep = false; - int i; - for (i = 0; brushEntityList[i]; i++) { - if (string_equal_nocase(brushEntityList[i], m_Classname)) { - keep = true; - break; - } - } - - if (!keep) { - return false; - } - - if (Node_getTraversable(ent)) { - class load_brushes_t : public scene::Traversable::Walker { - DEntity *m_entity; - mutable int m_count; - public: - load_brushes_t(DEntity *entity) - : m_entity(entity), m_count(0) - { - } - - bool pre(scene::Node &node) const - { - scene::Path path(NodeReference(GlobalSceneGraph().root())); - path.push(NodeReference(*m_entity->QER_Entity)); - path.push(NodeReference(node)); - scene::Instance *instance = GlobalSceneGraph().find(path); - ASSERT_MESSAGE(instance != 0, ""); - - if (Node_isPatch(node)) { - DPatch *loadPatch = m_entity->NewPatch(); - loadPatch->LoadFromPatch(*instance); - } else if (Node_isBrush(node)) { - DBrush *loadBrush = m_entity->NewBrush(m_count++); - loadBrush->LoadFromBrush(*instance, true); - } - return false; - } - } load_brushes(this); - - Node_getTraversable(ent)->traverse(load_brushes); - } - - return true; -} - -void DEntity::RemoveNonCheckBrushes(std::list *exclusionList, bool useDetail) -{ - std::list::iterator chkBrush = brushList.begin(); - - while (chkBrush != brushList.end()) { - if (!useDetail) { - if ((*chkBrush)->IsDetail()) { - delete *chkBrush; - chkBrush = brushList.erase(chkBrush); - continue; - } - } - - std::list::iterator eTexture; - - for (eTexture = exclusionList->begin(); eTexture != exclusionList->end(); eTexture++) { - if ((*chkBrush)->HasTexture((*eTexture).GetBuffer())) { - delete *chkBrush; - chkBrush = brushList.erase(chkBrush); - break; - } - } - - if (eTexture == exclusionList->end()) { - chkBrush++; - } - } -} - -void DEntity::ResetChecks(std::list *exclusionList) -{ - for (std::list::const_iterator resetBrush = brushList.begin(); - resetBrush != brushList.end(); resetBrush++) { - (*resetBrush)->ResetChecks(exclusionList); - } -} +bool DEntity::LoadFromEntity( scene::Node& ent, bool bLoadPatches ) { + ClearPatches(); + ClearBrushes(); + ClearEPairs(); -int DEntity::FixBrushes() -{ - int count = 0; + QER_Entity = &ent; - for (std::list::const_iterator fixBrush = brushList.begin(); fixBrush != brushList.end(); fixBrush++) { - count += (*fixBrush)->RemoveRedundantPlanes(); - } + LoadEPairList( Node_getEntity( ent ) ); - return count; -} + bool keep = false; + int i; + for ( i = 0; brushEntityList[i]; i++ ) + { + if ( string_equal_nocase( brushEntityList[i], m_Classname ) ) { + keep = true; + break; + } + } + + if ( !keep ) { + return false; + } + + if ( Node_getTraversable( ent ) ) { + class load_brushes_t : public scene::Traversable::Walker + { + DEntity* m_entity; + mutable int m_count; +public: + load_brushes_t( DEntity* entity ) + : m_entity( entity ), m_count( 0 ){ + } + + bool pre( scene::Node& node ) const { + scene::Path path( NodeReference( GlobalSceneGraph().root() ) ); + path.push( NodeReference( *m_entity->QER_Entity ) ); + path.push( NodeReference( node ) ); + scene::Instance* instance = GlobalSceneGraph().find( path ); + ASSERT_MESSAGE( instance != 0, "" ); -void DEntity::BuildInRadiant(bool allowDestruction) -{ - bool makeEntity = strcmp(m_Classname, "worldspawn") ? true : false; + if ( Node_isPatch( node ) ) { + DPatch* loadPatch = m_entity->NewPatch(); + loadPatch->LoadFromPatch( *instance ); + } + else if ( Node_isBrush( node ) ) { + DBrush* loadBrush = m_entity->NewBrush( m_count++ ); + loadBrush->LoadFromBrush( *instance, true ); + } + return false; + } + } load_brushes( this ); - if (makeEntity) { - NodeSmartReference node(GlobalEntityCreator().createEntity( - GlobalEntityClassManager().findOrInsert(m_Classname.GetBuffer(), - !brushList.empty() || !patchList.empty()))); + Node_getTraversable( ent )->traverse( load_brushes ); + } - for (std::list::const_iterator buildEPair = epairList.begin(); - buildEPair != epairList.end(); buildEPair++) { - Node_getEntity(node)->setKeyValue((*buildEPair)->key, (*buildEPair)->value); - } + return true; +} - Node_getTraversable(GlobalSceneGraph().root())->insert(node); +void DEntity::RemoveNonCheckBrushes( std::list* exclusionList, bool useDetail ){ + std::list::iterator chkBrush = brushList.begin(); - for (std::list::const_iterator buildBrush = brushList.begin(); - buildBrush != brushList.end(); buildBrush++) { - (*buildBrush)->BuildInRadiant(allowDestruction, NULL, node.get_pointer()); - } + while ( chkBrush != brushList.end() ) + { + if ( !useDetail ) { + if ( ( *chkBrush )->IsDetail() ) { + delete *chkBrush; + chkBrush = brushList.erase( chkBrush ); + continue; + } + } - for (std::list::const_iterator buildPatch = patchList.begin(); - buildPatch != patchList.end(); buildPatch++) { - (*buildPatch)->BuildInRadiant(node.get_pointer()); - } + std::list::iterator eTexture; - QER_Entity = node.get_pointer(); - } else { - for (std::list::const_iterator buildBrush = brushList.begin(); - buildBrush != brushList.end(); buildBrush++) { - (*buildBrush)->BuildInRadiant(allowDestruction, NULL); - } + for ( eTexture = exclusionList->begin(); eTexture != exclusionList->end(); eTexture++ ) + { + if ( ( *chkBrush )->HasTexture( ( *eTexture ).GetBuffer() ) ) { + delete *chkBrush; + chkBrush = brushList.erase( chkBrush ); + break; + } + } - for (std::list::const_iterator buildPatch = patchList.begin(); - buildPatch != patchList.end(); buildPatch++) { - (*buildPatch)->BuildInRadiant(); - } - } + if ( eTexture == exclusionList->end() ) { + chkBrush++; + } + } } - -int DEntity::GetIDMax(void) -{ - int max = -1; - for (std::list::const_iterator cntBrush = brushList.begin(); cntBrush != brushList.end(); cntBrush++) { - if ((*cntBrush)->m_nBrushID > max) { - max = (*cntBrush)->m_nBrushID; - } - } - return max + 1; +void DEntity::ResetChecks( std::list* exclusionList ){ + for ( std::list::const_iterator resetBrush = brushList.begin(); resetBrush != brushList.end(); resetBrush++ ) + { + ( *resetBrush )->ResetChecks( exclusionList ); + } } -void DEntity::SetClassname(const char *classname) -{ - m_Classname = classname; +int DEntity::FixBrushes(){ + int count = 0; + + for ( std::list::const_iterator fixBrush = brushList.begin(); fixBrush != brushList.end(); fixBrush++ ) + { + count += ( *fixBrush )->RemoveRedundantPlanes(); + } + + return count; } -void DEntity::SaveToFile(FILE *pFile) -{ - fprintf(pFile, "{\n"); +void DEntity::BuildInRadiant( bool allowDestruction ){ + bool makeEntity = strcmp( m_Classname, "worldspawn" ) ? true : false; + + if ( makeEntity ) { + NodeSmartReference node( GlobalEntityCreator().createEntity( GlobalEntityClassManager().findOrInsert( m_Classname.GetBuffer(), !brushList.empty() || !patchList.empty() ) ) ); + + for ( std::list::const_iterator buildEPair = epairList.begin(); buildEPair != epairList.end(); buildEPair++ ) + { + Node_getEntity( node )->setKeyValue( ( *buildEPair )->key, ( *buildEPair )->value ); + } - fprintf(pFile, "\"classname\" \"%s\"\n", (const char *) m_Classname); + Node_getTraversable( GlobalSceneGraph().root() )->insert( node ); - for (std::list::const_iterator ep = epairList.begin(); ep != epairList.end(); ep++) { - fprintf(pFile, "\"%s\" \"%s\"\n", (const char *) (*ep)->key, (const char *) (*ep)->value); - } + for ( std::list::const_iterator buildBrush = brushList.begin(); buildBrush != brushList.end(); buildBrush++ ) + ( *buildBrush )->BuildInRadiant( allowDestruction, NULL, node.get_pointer() ); - for (std::list::const_iterator bp = brushList.begin(); bp != brushList.end(); bp++) { - (*bp)->SaveToFile(pFile); - } + for ( std::list::const_iterator buildPatch = patchList.begin(); buildPatch != patchList.end(); buildPatch++ ) + ( *buildPatch )->BuildInRadiant( node.get_pointer() ); - fprintf(pFile, "}\n"); + QER_Entity = node.get_pointer(); + } + else + { + for ( std::list::const_iterator buildBrush = brushList.begin(); buildBrush != brushList.end(); buildBrush++ ) + ( *buildBrush )->BuildInRadiant( allowDestruction, NULL ); + + for ( std::list::const_iterator buildPatch = patchList.begin(); buildPatch != patchList.end(); buildPatch++ ) + ( *buildPatch )->BuildInRadiant(); + } } -void DEntity::ClearEPairs() -{ - for (std::list::const_iterator deadEPair = epairList.begin(); deadEPair != epairList.end(); deadEPair++) { - delete (*deadEPair); - } - epairList.clear(); +int DEntity::GetIDMax( void ) { + int max = -1; + for ( std::list::const_iterator cntBrush = brushList.begin(); cntBrush != brushList.end(); cntBrush++ ) { + if ( ( *cntBrush )->m_nBrushID > max ) { + max = ( *cntBrush )->m_nBrushID; + } + } + return max + 1; } -void DEntity::AddEPair(const char *key, const char *value) -{ - DEPair *newEPair; - newEPair = FindEPairByKey(key); - if (!newEPair) { - newEPair = new DEPair; - newEPair->Build(key, value); - epairList.push_back(newEPair); - } else { - newEPair->Build(key, value); - } -} - -void DEntity::LoadEPairList(Entity *epl) -{ - class load_epairs_t : public Entity::Visitor { - DEntity *m_entity; - public: - load_epairs_t(DEntity *entity) - : m_entity(entity) - { - } - - void visit(const char *key, const char *value) - { - if (strcmp(key, "classname") == 0) { - m_entity->SetClassname(value); - } else { - m_entity->AddEPair(key, value); - } - } - - } load_epairs(this); - - epl->forEachKeyValue(load_epairs); -} - -bool DEntity::ResetTextures(const char *textureName, float fScale[2], float fShift[2], int rotation, - const char *newTextureName, - int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation, - bool rebuild) -{ - bool reset = false; - - for (std::list::const_iterator resetBrush = brushList.begin(); - resetBrush != brushList.end(); resetBrush++) { - bool tmp = (*resetBrush)->ResetTextures(textureName, fScale, fShift, rotation, newTextureName, - bResetTextureName, bResetScale, bResetShift, bResetRotation); - - if (tmp) { - reset = true; - if (rebuild) { - Node_getTraversable(*(*resetBrush)->QER_entity)->erase(*(*resetBrush)->QER_brush); - (*resetBrush)->BuildInRadiant(false, NULL, (*resetBrush)->QER_entity); - } - } - } - - if (bResetTextureName) { - for (std::list::const_iterator resetPatch = patchList.begin(); - resetPatch != patchList.end(); resetPatch++) { - bool tmp = (*resetPatch)->ResetTextures(textureName, newTextureName); - - if (tmp) { - reset = true; - if (rebuild) { - Node_getTraversable(*(*resetPatch)->QER_entity)->erase(*(*resetPatch)->QER_brush); - (*resetPatch)->BuildInRadiant((*resetPatch)->QER_entity); - } - } - } - } - - return reset; -} - -DEPair *DEntity::FindEPairByKey(const char *keyname) -{ - for (std::list::const_iterator ep = epairList.begin(); ep != epairList.end(); ep++) { - char *c = (*ep)->key; - if (!strcmp(c, keyname)) { - return *ep; - } - } - return NULL; +void DEntity::SetClassname( const char *classname ) { + m_Classname = classname; } -void DEntity::RemoveFromRadiant() -{ - Node_getTraversable(GlobalSceneGraph().root())->erase(*QER_Entity); +void DEntity::SaveToFile( FILE *pFile ){ + fprintf( pFile, "{\n" ); - QER_Entity = NULL; -} + fprintf( pFile, "\"classname\" \"%s\"\n", (const char *)m_Classname ); -void DEntity::SpawnString(const char *key, const char *defaultstring, const char **out) -{ - DEPair *pEP = FindEPairByKey(key); - if (pEP) { - *out = pEP->value; - } else { - *out = defaultstring; - } -} + for ( std::list::const_iterator ep = epairList.begin(); ep != epairList.end(); ep++ ) + { + fprintf( pFile, "\"%s\" \"%s\"\n", (const char *)( *ep )->key, (const char *)( *ep )->value ); + } -void DEntity::SpawnInt(const char *key, const char *defaultstring, int *out) -{ - DEPair *pEP = FindEPairByKey(key); - if (pEP) { - *out = atoi(pEP->value); - } else { - *out = atoi(defaultstring); - } -} + for ( std::list::const_iterator bp = brushList.begin(); bp != brushList.end(); bp++ ) + { + ( *bp )->SaveToFile( pFile ); + } -void DEntity::SpawnFloat(const char *key, const char *defaultstring, float *out) -{ - DEPair *pEP = FindEPairByKey(key); - if (pEP) { - *out = static_cast( atof(pEP->value)); - } else { - *out = static_cast( atof(defaultstring)); - } + fprintf( pFile, "}\n" ); } -void DEntity::SpawnVector(const char *key, const char *defaultstring, vec_t *out) -{ - DEPair *pEP = FindEPairByKey(key); - if (pEP) { - sscanf(pEP->value, "%f %f %f", &out[0], &out[1], &out[2]); - } else { - sscanf(defaultstring, "%f %f %f", &out[0], &out[1], &out[2]); - } +void DEntity::ClearEPairs(){ + for ( std::list::const_iterator deadEPair = epairList.begin(); deadEPair != epairList.end(); deadEPair++ ) + { + delete ( *deadEPair ); + } + epairList.clear(); } -int DEntity::GetBrushCount(void) -{ - return static_cast( brushList.size()); +void DEntity::AddEPair( const char *key, const char *value ) { + DEPair* newEPair; + newEPair = FindEPairByKey( key ); + if ( !newEPair ) { + newEPair = new DEPair; + newEPair->Build( key, value ); + epairList.push_back( newEPair ); + } + else { + newEPair->Build( key, value ); + } } -DBrush *DEntity::FindBrushByPointer(scene::Node &brush) -{ - for (std::list::const_iterator listBrush = brushList.begin(); listBrush != brushList.end(); listBrush++) { - DBrush *pBrush = (*listBrush); - if (pBrush->QER_brush == &brush) { - return pBrush; - } - } - return NULL; +void DEntity::LoadEPairList( Entity *epl ){ + class load_epairs_t : public Entity::Visitor + { + DEntity* m_entity; +public: + load_epairs_t( DEntity* entity ) + : m_entity( entity ){ + } + void visit( const char* key, const char* value ){ + if ( strcmp( key, "classname" ) == 0 ) { + m_entity->SetClassname( value ); + } + else{ + m_entity->AddEPair( key, value ); + } + } + + } load_epairs( this ); + + epl->forEachKeyValue( load_epairs ); +} + +bool DEntity::ResetTextures( const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName, + int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation, bool rebuild ){ + bool reset = false; + + for ( std::list::const_iterator resetBrush = brushList.begin(); resetBrush != brushList.end(); resetBrush++ ) + { + bool tmp = ( *resetBrush )->ResetTextures( textureName, fScale, fShift, rotation, newTextureName, + bResetTextureName, bResetScale, bResetShift, bResetRotation ); + + if ( tmp ) { + reset = true; + if ( rebuild ) { + Node_getTraversable( *( *resetBrush )->QER_entity )->erase( *( *resetBrush )->QER_brush ); + ( *resetBrush )->BuildInRadiant( false, NULL, ( *resetBrush )->QER_entity ); + } + } + } + + if ( bResetTextureName ) { + for ( std::list::const_iterator resetPatch = patchList.begin(); resetPatch != patchList.end(); resetPatch++ ) + { + bool tmp = ( *resetPatch )->ResetTextures( textureName, newTextureName ); + + if ( tmp ) { + reset = true; + if ( rebuild ) { + Node_getTraversable( *( *resetPatch )->QER_entity )->erase( *( *resetPatch )->QER_brush ); + ( *resetPatch )->BuildInRadiant( ( *resetPatch )->QER_entity ); + } + } + } + } + + return reset; +} + +DEPair* DEntity::FindEPairByKey( const char* keyname ){ + for ( std::list::const_iterator ep = epairList.begin(); ep != epairList.end(); ep++ ) + { + char* c = ( *ep )->key; + if ( !strcmp( c, keyname ) ) { + return *ep; + } + } + return NULL; +} + +void DEntity::RemoveFromRadiant(){ + Node_getTraversable( GlobalSceneGraph().root() )->erase( *QER_Entity ); + + QER_Entity = NULL; +} + +void DEntity::SpawnString( const char* key, const char* defaultstring, const char** out ){ + DEPair* pEP = FindEPairByKey( key ); + if ( pEP ) { + *out = pEP->value; + } + else { + *out = defaultstring; + } +} + +void DEntity::SpawnInt( const char* key, const char* defaultstring, int* out ){ + DEPair* pEP = FindEPairByKey( key ); + if ( pEP ) { + *out = atoi( pEP->value ); + } + else { + *out = atoi( defaultstring ); + } +} + +void DEntity::SpawnFloat( const char* key, const char* defaultstring, float* out ){ + DEPair* pEP = FindEPairByKey( key ); + if ( pEP ) { + *out = static_cast( atof( pEP->value ) ); + } + else { + *out = static_cast( atof( defaultstring ) ); + } +} + +void DEntity::SpawnVector( const char* key, const char* defaultstring, vec_t* out ){ + DEPair* pEP = FindEPairByKey( key ); + if ( pEP ) { + sscanf( pEP->value, "%f %f %f", &out[0], &out[1], &out[2] ); + } + else { + sscanf( defaultstring, "%f %f %f", &out[0], &out[1], &out[2] ); + } +} + +int DEntity::GetBrushCount( void ) { + return static_cast( brushList.size() ); +} + +DBrush* DEntity::FindBrushByPointer( scene::Node& brush ) { + for ( std::list::const_iterator listBrush = brushList.begin(); listBrush != brushList.end(); listBrush++ ) { + DBrush* pBrush = ( *listBrush ); + if ( pBrush->QER_brush == &brush ) { + return pBrush; + } + } + return NULL; } diff --git a/plugins/imagepng/plugin.cpp b/plugins/imagepng/plugin.cpp index 65ae5950..281193fd 100644 --- a/plugins/imagepng/plugin.cpp +++ b/plugins/imagepng/plugin.cpp @@ -31,167 +31,165 @@ #include "png.h" #include -void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) -{ - globalErrorStream() << "libpng warning: " << warning_msg << "\n"; +void user_warning_fn( png_structp png_ptr, png_const_charp warning_msg ){ + globalErrorStream() << "libpng warning: " << warning_msg << "\n"; } -void user_error_fn(png_structp png_ptr, png_const_charp error_msg) -{ - globalErrorStream() << "libpng error: " << error_msg << "\n"; - longjmp(png_jmpbuf(png_ptr), 0); +void user_error_fn( png_structp png_ptr, png_const_charp error_msg ){ + globalErrorStream() << "libpng error: " << error_msg << "\n"; + longjmp( png_jmpbuf(png_ptr), 0 ); } -void user_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length) -{ - png_bytep *p_p_fbuffer = (png_bytep *) png_get_io_ptr(png_ptr); - memcpy(data, *p_p_fbuffer, length); - *p_p_fbuffer += length; +void user_read_data( png_structp png_ptr, png_bytep data, png_uint_32 length ){ + png_bytep *p_p_fbuffer = (png_bytep*)png_get_io_ptr( png_ptr ); + memcpy( data, *p_p_fbuffer, length ); + *p_p_fbuffer += length; } -Image *LoadPNGBuff(unsigned char *fbuffer) -{ - png_byte **row_pointers; - png_bytep p_fbuffer; - - p_fbuffer = fbuffer; - - // the reading glue - // http://www.libpng.org/pub/png/libpng-manual.html - - png_structp png_ptr = png_create_read_struct - (PNG_LIBPNG_VER_STRING, (png_voidp) NULL, - user_error_fn, user_warning_fn); - if (!png_ptr) { - globalErrorStream() << "libpng error: png_create_read_struct\n"; - return 0; - } - - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_read_struct(&png_ptr, - (png_infopp) NULL, (png_infopp) NULL); - globalErrorStream() << "libpng error: png_create_info_struct (info_ptr)\n"; - return 0; - } - - png_infop end_info = png_create_info_struct(png_ptr); - if (!end_info) { - png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp) NULL); - globalErrorStream() << "libpng error: png_create_info_struct (end_info)\n"; - return 0; - } - - // configure the read function - png_set_read_fn(png_ptr, (png_voidp) &p_fbuffer, (png_rw_ptr) &user_read_data); - - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_read_struct(&png_ptr, &info_ptr, - &end_info); - return 0; - } - - png_read_info(png_ptr, info_ptr); - - int bit_depth = png_get_bit_depth(png_ptr, info_ptr); - int color_type = png_get_color_type(png_ptr, info_ptr); - - // we want to treat all images the same way - // The following code transforms grayscale images of less than 8 to 8 bits, - // changes paletted images to RGB, and adds a full alpha channel if there is - // transparency information in a tRNS chunk. - - if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - png_set_gray_to_rgb(png_ptr); - } else if (color_type == PNG_COLOR_TYPE_PALETTE) { - png_set_palette_to_rgb(png_ptr); - } - - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { - png_set_expand_gray_1_2_4_to_8(png_ptr); - } - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { - png_set_tRNS_to_alpha(png_ptr); - } else if (!(color_type & PNG_COLOR_MASK_ALPHA)) { - // Set the background color to draw transparent and alpha images over. - png_color_16 my_background, *image_background; - - if (png_get_bKGD(png_ptr, info_ptr, &image_background)) { - png_set_background(png_ptr, image_background, - PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); - } else { - png_set_background(png_ptr, &my_background, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - } - - // Add alpha byte after each RGB triplet - png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); - } - - // read the sucker in one chunk - png_read_update_info(png_ptr, info_ptr); - - color_type = png_get_color_type(png_ptr, info_ptr); - bit_depth = png_get_bit_depth(png_ptr, info_ptr); - - int width = png_get_image_width(png_ptr, info_ptr); - int height = png_get_image_height(png_ptr, info_ptr); - - // allocate the pixel buffer, and the row pointers - RGBAImage *image = new RGBAImage(width, height); - - row_pointers = (png_byte **) malloc((height) * sizeof(png_byte *)); - - int i; - for (i = 0; i < (height); i++) { - row_pointers[i] = (png_byte *) (image->getRGBAPixels()) + i * 4 * (width); - } - - // actual read - png_read_image(png_ptr, row_pointers); - - /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ - png_read_end(png_ptr, info_ptr); - - /* free up the memory structure */ - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - - free(row_pointers); - - return image; +Image* LoadPNGBuff( unsigned char* fbuffer ){ + png_byte** row_pointers; + png_bytep p_fbuffer; + + p_fbuffer = fbuffer; + + // the reading glue + // http://www.libpng.org/pub/png/libpng-manual.html + + png_structp png_ptr = png_create_read_struct + ( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, + user_error_fn, user_warning_fn ); + if ( !png_ptr ) { + globalErrorStream() << "libpng error: png_create_read_struct\n"; + return 0; + } + + png_infop info_ptr = png_create_info_struct( png_ptr ); + if ( !info_ptr ) { + png_destroy_read_struct( &png_ptr, + (png_infopp)NULL, (png_infopp)NULL ); + globalErrorStream() << "libpng error: png_create_info_struct (info_ptr)\n"; + return 0; + } + + png_infop end_info = png_create_info_struct( png_ptr ); + if ( !end_info ) { + png_destroy_read_struct( &png_ptr, &info_ptr, + (png_infopp)NULL ); + globalErrorStream() << "libpng error: png_create_info_struct (end_info)\n"; + return 0; + } + + // configure the read function + png_set_read_fn( png_ptr, ( png_voidp ) & p_fbuffer, ( png_rw_ptr ) & user_read_data ); + + if ( setjmp( png_jmpbuf(png_ptr) ) ) { + png_destroy_read_struct( &png_ptr, &info_ptr, + &end_info ); + return 0; + } + + png_read_info( png_ptr, info_ptr ); + + int bit_depth = png_get_bit_depth( png_ptr, info_ptr ); + int color_type = png_get_color_type( png_ptr, info_ptr ); + + // we want to treat all images the same way + // The following code transforms grayscale images of less than 8 to 8 bits, + // changes paletted images to RGB, and adds a full alpha channel if there is + // transparency information in a tRNS chunk. + + if ( color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) { + png_set_gray_to_rgb( png_ptr ); + } + else if ( color_type == PNG_COLOR_TYPE_PALETTE ) { + png_set_palette_to_rgb( png_ptr ); + } + + if ( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 ) { + png_set_expand_gray_1_2_4_to_8( png_ptr ); + } + + if ( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) ) { + png_set_tRNS_to_alpha( png_ptr ); + } + + if ( !( color_type & PNG_COLOR_MASK_ALPHA ) ) { + // Set the background color to draw transparent and alpha images over. + png_color_16 my_background, *image_background; + + if ( png_get_bKGD( png_ptr, info_ptr, &image_background ) ) { + png_set_background( png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0 ); + } + else{ + png_set_background( png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0 ); + } + + // Add alpha byte after each RGB triplet + png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER ); + } + + // read the sucker in one chunk + png_read_update_info( png_ptr, info_ptr ); + + color_type = png_get_color_type( png_ptr, info_ptr ); + bit_depth = png_get_bit_depth( png_ptr, info_ptr ); + + int width = png_get_image_width( png_ptr, info_ptr ); + int height = png_get_image_height( png_ptr, info_ptr ); + + // allocate the pixel buffer, and the row pointers + RGBAImage* image = new RGBAImage( width, height ); + + row_pointers = (png_byte**) malloc( ( height ) * sizeof( png_byte* ) ); + + int i; + for ( i = 0; i < ( height ); i++ ) + row_pointers[i] = (png_byte*)( image->getRGBAPixels() ) + i * 4 * ( width ); + + // actual read + png_read_image( png_ptr, row_pointers ); + + /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end( png_ptr, info_ptr ); + + /* free up the memory structure */ + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + + free( row_pointers ); + + return image; } -Image *LoadPNG(ArchiveFile &file) -{ - ScopedArchiveBuffer buffer(file); - return LoadPNGBuff(buffer.buffer); +Image* LoadPNG( ArchiveFile& file ){ + ScopedArchiveBuffer buffer( file ); + return LoadPNGBuff( buffer.buffer ); } #include "modulesystem/singletonmodule.h" -class ImageDependencies : public GlobalFileSystemModuleRef { +class ImageDependencies : public GlobalFileSystemModuleRef +{ }; -class ImagePNGAPI { - _QERPlugImageTable m_imagepng; +class ImagePNGAPI +{ +_QERPlugImageTable m_imagepng; public: - typedef _QERPlugImageTable Type; +typedef _QERPlugImageTable Type; - STRING_CONSTANT(Name, "png"); +STRING_CONSTANT( Name, "png" ); - ImagePNGAPI() - { - m_imagepng.loadImage = LoadPNG; - } +ImagePNGAPI(){ + m_imagepng.loadImage = LoadPNG; +} - _QERPlugImageTable *getTable() - { - return &m_imagepng; - } +_QERPlugImageTable* getTable(){ + return &m_imagepng; +} }; typedef SingletonModule ImagePNGModule; @@ -199,9 +197,8 @@ typedef SingletonModule ImagePNGModule; ImagePNGModule g_ImagePNGModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) -{ - initialiseModule(server); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ + initialiseModule( server ); - g_ImagePNGModule.selfRegister(); + g_ImagePNGModule.selfRegister(); } diff --git a/plugins/iqmmodel/iqm.h b/plugins/iqmmodel/iqm.h index 8f48f3bb..5e6a0146 100644 --- a/plugins/iqmmodel/iqm.h +++ b/plugins/iqmmodel/iqm.h @@ -27,5 +27,4 @@ class ArchiveFile; scene::Node &loadIQMModel( ArchiveFile &file ); - #endif diff --git a/plugins/iqmmodel/plugin.h b/plugins/iqmmodel/plugin.h index c6bfe6ce..c94ee67e 100644 --- a/plugins/iqmmodel/plugin.h +++ b/plugins/iqmmodel/plugin.h @@ -21,5 +21,4 @@ #if !defined( INCLUDED_SAMPLE_H ) #define INCLUDED_SAMPLE_H - #endif diff --git a/plugins/mapq3/plugin.cpp b/plugins/mapq3/plugin.cpp index af04cea3..8b427d42 100644 --- a/plugins/mapq3/plugin.cpp +++ b/plugins/mapq3/plugin.cpp @@ -38,286 +38,272 @@ class MapDoom3Dependencies : - public GlobalRadiantModuleRef, - public GlobalFiletypesModuleRef, - public GlobalScripLibModuleRef, - public GlobalEntityClassManagerModuleRef, - public GlobalSceneGraphModuleRef, - public GlobalBrushModuleRef { - PatchModuleRef m_patchDef2Doom3Module; - PatchModuleRef m_patchDoom3Module; + public GlobalRadiantModuleRef, + public GlobalFiletypesModuleRef, + public GlobalScripLibModuleRef, + public GlobalEntityClassManagerModuleRef, + public GlobalSceneGraphModuleRef, + public GlobalBrushModuleRef +{ +PatchModuleRef m_patchDef2Doom3Module; +PatchModuleRef m_patchDoom3Module; public: - MapDoom3Dependencies() : - GlobalEntityClassManagerModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entityclass")), - GlobalBrushModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("brushtypes")), - m_patchDef2Doom3Module("def2doom3"), - m_patchDoom3Module("doom3") - { - } - - BrushCreator &getBrushDoom3() - { - return GlobalBrushModule::getTable(); - } - - PatchCreator &getPatchDoom3() - { - return *m_patchDoom3Module.getTable(); - } - - PatchCreator &getPatchDef2Doom3() - { - return *m_patchDef2Doom3Module.getTable(); - } +MapDoom3Dependencies() : + GlobalEntityClassManagerModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "entityclass" ) ), + GlobalBrushModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "brushtypes" ) ), + m_patchDef2Doom3Module( "def2doom3" ), + m_patchDoom3Module( "doom3" ){ +} + +BrushCreator& getBrushDoom3(){ + return GlobalBrushModule::getTable(); +} + +PatchCreator& getPatchDoom3(){ + return *m_patchDoom3Module.getTable(); +} + +PatchCreator& getPatchDef2Doom3(){ + return *m_patchDef2Doom3Module.getTable(); +} }; -class MapDoom3API : public TypeSystemRef, public MapFormat, public PrimitiveParser { - MapDoom3Dependencies &m_dependencies; +class MapDoom3API : public TypeSystemRef, public MapFormat, public PrimitiveParser +{ +MapDoom3Dependencies& m_dependencies; public: - typedef MapFormat Type; - - STRING_CONSTANT(Name, "mapdoom3"); - - UINT_CONSTANT(MapVersion, 2); - - MapDoom3API(MapDoom3Dependencies &dependencies) : m_dependencies(dependencies) - { - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("doom3 maps", "*.map")); - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("doom3 region", "*.reg")); - } - - MapFormat *getTable() - { - return this; - } - - scene::Node &parsePrimitive(Tokeniser &tokeniser) const - { - const char *primitive = tokeniser.getToken(); - if (primitive != 0) { - if (string_equal(primitive, "patchDef3")) { - return m_dependencies.getPatchDoom3().createPatch(); - } else if (string_equal(primitive, "patchDef2")) { - return m_dependencies.getPatchDef2Doom3().createPatch(); - } else if (string_equal(primitive, "brushDef3")) { - return m_dependencies.getBrushDoom3().createBrush(); - } - } - - Tokeniser_unexpectedError(tokeniser, primitive, "#doom3-primitive"); - return g_nullNode; - } - - void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const - { - Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); - tokeniser.nextLine(); - if (!Tokeniser_parseToken(tokeniser, "Version")) { - return; - } - std::size_t version; - if (!Tokeniser_getSize(tokeniser, version)) { - return; - } - if (version != MapVersion()) { - globalErrorStream() << "Doom 3 map version " << MapVersion() << " supported, version is " - << Unsigned(version) << "\n"; - return; - } - tokeniser.nextLine(); - Map_Read(root, tokeniser, entityTable, *this); - tokeniser.release(); - } - - void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream, bool writeComments) const - { - TokenWriter &writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter(outputStream); - writer.writeToken("Version"); - writer.writeInteger(MapVersion()); - writer.nextLine(); - Map_Write(root, traverse, writer, false, writeComments); - writer.release(); - } +typedef MapFormat Type; + +STRING_CONSTANT( Name, "mapdoom3" ); + +UINT_CONSTANT( MapVersion, 2 ); + +MapDoom3API( MapDoom3Dependencies& dependencies ) : m_dependencies( dependencies ){ + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "doom3 maps", "*.map" ) ); + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "doom3 region", "*.reg" ) ); +} + +MapFormat* getTable(){ + return this; +} + +scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { + const char* primitive = tokeniser.getToken(); + if ( primitive != 0 ) { + if ( string_equal( primitive, "patchDef3" ) ) { + return m_dependencies.getPatchDoom3().createPatch(); + } + else if ( string_equal( primitive, "patchDef2" ) ) { + return m_dependencies.getPatchDef2Doom3().createPatch(); + } + else if ( string_equal( primitive, "brushDef3" ) ) { + return m_dependencies.getBrushDoom3().createBrush(); + } + } + + Tokeniser_unexpectedError( tokeniser, primitive, "#doom3-primitive" ); + return g_nullNode; +} +void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { + Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); + tokeniser.nextLine(); + if ( !Tokeniser_parseToken( tokeniser, "Version" ) ) { + return; + } + std::size_t version; + if ( !Tokeniser_getSize( tokeniser, version ) ) { + return; + } + if ( version != MapVersion() ) { + globalErrorStream() << "Doom 3 map version " << MapVersion() << " supported, version is " << Unsigned( version ) << "\n"; + return; + } + tokeniser.nextLine(); + Map_Read( root, tokeniser, entityTable, *this ); + tokeniser.release(); +} + +void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream, bool writeComments ) const { + TokenWriter& writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter( outputStream ); + writer.writeToken( "Version" ); + writer.writeInteger( MapVersion() ); + writer.nextLine(); + Map_Write( root, traverse, writer, false, writeComments ); + writer.release(); +} }; typedef SingletonModule< - MapDoom3API, - MapDoom3Dependencies, - DependenciesAPIConstructor -> - MapDoom3Module; + MapDoom3API, + MapDoom3Dependencies, + DependenciesAPIConstructor + > +MapDoom3Module; MapDoom3Module g_MapDoom3Module; -class MapQuake4API : public TypeSystemRef, public MapFormat, public PrimitiveParser { - MapDoom3Dependencies &m_dependencies; +class MapQuake4API : public TypeSystemRef, public MapFormat, public PrimitiveParser +{ +MapDoom3Dependencies& m_dependencies; public: - typedef MapFormat Type; - - STRING_CONSTANT(Name, "mapquake4"); - - UINT_CONSTANT(MapVersion, 3); - - MapQuake4API(MapDoom3Dependencies &dependencies) : m_dependencies(dependencies) - { - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake4 maps", "*.map")); - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake4 region", "*.reg")); - } - - MapFormat *getTable() - { - return this; - } - - scene::Node &parsePrimitive(Tokeniser &tokeniser) const - { - const char *primitive = tokeniser.getToken(); - if (primitive != 0) { - if (string_equal(primitive, "patchDef3")) { - return m_dependencies.getPatchDoom3().createPatch(); - } else if (string_equal(primitive, "patchDef2")) { - return m_dependencies.getPatchDef2Doom3().createPatch(); - } else if (string_equal(primitive, "brushDef3")) { - return m_dependencies.getBrushDoom3().createBrush(); - } - } - - Tokeniser_unexpectedError(tokeniser, primitive, "#quake4-primitive"); - return g_nullNode; - } - - void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const - { - Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); - tokeniser.nextLine(); - if (!Tokeniser_parseToken(tokeniser, "Version")) { - return; - } - std::size_t version; - if (!Tokeniser_getSize(tokeniser, version)) { - return; - } - if (version != MapVersion()) { - globalErrorStream() << "Quake 4 map version " << MapVersion() << " supported, version is " - << Unsigned(version) << "\n"; - return; - } - tokeniser.nextLine(); - Map_Read(root, tokeniser, entityTable, *this); - tokeniser.release(); - } - - void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream, bool writeComments) const - { - TokenWriter &writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter(outputStream); - writer.writeToken("Version"); - writer.writeInteger(MapVersion()); - writer.nextLine(); - Map_Write(root, traverse, writer, false, writeComments); - writer.release(); - } +typedef MapFormat Type; + +STRING_CONSTANT( Name, "mapquake4" ); + +UINT_CONSTANT( MapVersion, 3 ); + +MapQuake4API( MapDoom3Dependencies& dependencies ) : m_dependencies( dependencies ){ + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake4 maps", "*.map" ) ); + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake4 region", "*.reg" ) ); +} + +MapFormat* getTable(){ + return this; +} + +scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { + const char* primitive = tokeniser.getToken(); + if ( primitive != 0 ) { + if ( string_equal( primitive, "patchDef3" ) ) { + return m_dependencies.getPatchDoom3().createPatch(); + } + else if ( string_equal( primitive, "patchDef2" ) ) { + return m_dependencies.getPatchDef2Doom3().createPatch(); + } + else if ( string_equal( primitive, "brushDef3" ) ) { + return m_dependencies.getBrushDoom3().createBrush(); + } + } + + Tokeniser_unexpectedError( tokeniser, primitive, "#quake4-primitive" ); + return g_nullNode; +} +void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { + Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); + tokeniser.nextLine(); + if ( !Tokeniser_parseToken( tokeniser, "Version" ) ) { + return; + } + std::size_t version; + if ( !Tokeniser_getSize( tokeniser, version ) ) { + return; + } + if ( version != MapVersion() ) { + globalErrorStream() << "Quake 4 map version " << MapVersion() << " supported, version is " << Unsigned( version ) << "\n"; + return; + } + tokeniser.nextLine(); + Map_Read( root, tokeniser, entityTable, *this ); + tokeniser.release(); +} + +void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream, bool writeComments ) const { + TokenWriter& writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter( outputStream ); + writer.writeToken( "Version" ); + writer.writeInteger( MapVersion() ); + writer.nextLine(); + Map_Write( root, traverse, writer, false, writeComments ); + writer.release(); +} }; typedef SingletonModule< - MapQuake4API, - MapDoom3Dependencies, - DependenciesAPIConstructor -> - MapQuake4Module; + MapQuake4API, + MapDoom3Dependencies, + DependenciesAPIConstructor + > +MapQuake4Module; MapQuake4Module g_MapQuake4Module; class MapDependencies : - public GlobalRadiantModuleRef, - public GlobalBrushModuleRef, - public GlobalPatchModuleRef, - public GlobalFiletypesModuleRef, - public GlobalScripLibModuleRef, - public GlobalEntityClassManagerModuleRef, - public GlobalSceneGraphModuleRef { + public GlobalRadiantModuleRef, + public GlobalBrushModuleRef, + public GlobalPatchModuleRef, + public GlobalFiletypesModuleRef, + public GlobalScripLibModuleRef, + public GlobalEntityClassManagerModuleRef, + public GlobalSceneGraphModuleRef +{ public: - MapDependencies() : - GlobalBrushModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("brushtypes")), - GlobalPatchModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("patchtypes")), - GlobalEntityClassManagerModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entityclass")) - { - } +MapDependencies() : + GlobalBrushModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "brushtypes" ) ), + GlobalPatchModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "patchtypes" ) ), + GlobalEntityClassManagerModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "entityclass" ) ){ +} }; -class MapQ3API : public TypeSystemRef, public MapFormat, public PrimitiveParser { - mutable bool detectedFormat; +class MapQ3API : public TypeSystemRef, public MapFormat, public PrimitiveParser +{ +mutable bool detectedFormat; public: - typedef MapFormat Type; - - STRING_CONSTANT(Name, "mapq3"); - - MapQ3API() - { - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), - filetype_t("quake3 maps", "*.map", true, true, true)); - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), - filetype_t("quake3 region", "*.reg", true, true, true)); - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), - filetype_t("quake3 compiled maps", "*.bsp", false, true, false)); - } - - MapFormat *getTable() - { - return this; - } - - scene::Node &parsePrimitive(Tokeniser &tokeniser) const - { - const char *primitive = tokeniser.getToken(); - if (primitive != 0) { - if (string_equal(primitive, "patchDef2")) { - return GlobalPatchModule::getTable().createPatch(); - } - if (GlobalBrushModule::getTable().useAlternativeTextureProjection()) { - if (string_equal(primitive, "brushDef")) { - detectedFormat = true; - return GlobalBrushModule::getTable().createBrush(); - } else if (!detectedFormat && string_equal(primitive, "(")) { - detectedFormat = true; - wrongFormat = true; - Tokeniser_unexpectedError(tokeniser, primitive, "#quake3-switch-to-texdef"); - return g_nullNode; - } - } else { - if (string_equal(primitive, "(")) { - detectedFormat = true; - tokeniser.ungetToken(); // ( - return GlobalBrushModule::getTable().createBrush(); - } else if (!detectedFormat && string_equal(primitive, "brushDef")) { - detectedFormat = true; - wrongFormat = true; - Tokeniser_unexpectedError(tokeniser, primitive, "#quake3-switch-to-brush-primitives"); - return g_nullNode; - } - } - } - - Tokeniser_unexpectedError(tokeniser, primitive, "#quake3-primitive"); - return g_nullNode; - } - - void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const - { - detectedFormat = false; - wrongFormat = false; - Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); - Map_Read(root, tokeniser, entityTable, *this); - tokeniser.release(); - } - - void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream, bool writeComments) const - { - TokenWriter &writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter(outputStream); - Map_Write(root, traverse, writer, false, writeComments); - writer.release(); - } +typedef MapFormat Type; + +STRING_CONSTANT( Name, "mapq3" ); + +MapQ3API(){ + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake3 maps", "*.map", true, true, true ) ); + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake3 region", "*.reg", true, true, true ) ); + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake3 compiled maps", "*.bsp", false, true, false ) ); +} + +MapFormat* getTable(){ + return this; +} + +scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { + const char* primitive = tokeniser.getToken(); + if ( primitive != 0 ) { + if ( string_equal( primitive, "patchDef2" ) ) { + return GlobalPatchModule::getTable().createPatch(); + } + if ( GlobalBrushModule::getTable().useAlternativeTextureProjection() ) { + if ( string_equal( primitive, "brushDef" ) ) { + detectedFormat = true; + return GlobalBrushModule::getTable().createBrush(); + } + else if ( !detectedFormat && string_equal( primitive, "(" ) ) { + detectedFormat = true; + wrongFormat = true; + Tokeniser_unexpectedError( tokeniser, primitive, "#quake3-switch-to-texdef" ); + return g_nullNode; + } + } + else + { + if ( string_equal( primitive, "(" ) ) { + detectedFormat = true; + tokeniser.ungetToken(); // ( + return GlobalBrushModule::getTable().createBrush(); + } + else if ( !detectedFormat && string_equal( primitive, "brushDef" ) ) { + detectedFormat = true; + wrongFormat = true; + Tokeniser_unexpectedError( tokeniser, primitive, "#quake3-switch-to-brush-primitives" ); + return g_nullNode; + } + } + } + + Tokeniser_unexpectedError( tokeniser, primitive, "#quake3-primitive" ); + return g_nullNode; +} + +void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { + detectedFormat = false; + wrongFormat = false; + Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); + Map_Read( root, tokeniser, entityTable, *this ); + tokeniser.release(); +} + +void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream, bool writeComments ) const { + TokenWriter& writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter( outputStream ); + Map_Write( root, traverse, writer, false, writeComments ); + writer.release(); +} }; typedef SingletonModule MapQ3Module; @@ -325,50 +311,45 @@ typedef SingletonModule MapQ3Module; MapQ3Module g_MapQ3Module; -class MapQ1API : public TypeSystemRef, public MapFormat, public PrimitiveParser { +class MapQ1API : public TypeSystemRef, public MapFormat, public PrimitiveParser +{ public: - typedef MapFormat Type; - - STRING_CONSTANT(Name, "mapq1"); - - MapQ1API() - { - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake maps", "*.map")); - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake region", "*.reg")); - } - - MapFormat *getTable() - { - return this; - } - - scene::Node &parsePrimitive(Tokeniser &tokeniser) const - { - const char *primitive = tokeniser.getToken(); - if (primitive != 0) { - if (string_equal(primitive, "(")) { - tokeniser.ungetToken(); // ( - return GlobalBrushModule::getTable().createBrush(); - } - } - - Tokeniser_unexpectedError(tokeniser, primitive, "#quake-primitive"); - return g_nullNode; - } - - void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const - { - Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); - Map_Read(root, tokeniser, entityTable, *this); - tokeniser.release(); - } - - void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream, bool writeComments) const - { - TokenWriter &writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter(outputStream); - Map_Write(root, traverse, writer, true, writeComments); - writer.release(); - } +typedef MapFormat Type; + +STRING_CONSTANT( Name, "mapq1" ); + +MapQ1API(){ + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake maps", "*.map" ) ); + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake region", "*.reg" ) ); +} + +MapFormat* getTable(){ + return this; +} + +scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { + const char* primitive = tokeniser.getToken(); + if ( primitive != 0 ) { + if ( string_equal( primitive, "(" ) ) { + tokeniser.ungetToken(); // ( + return GlobalBrushModule::getTable().createBrush(); + } + } + + Tokeniser_unexpectedError( tokeniser, primitive, "#quake-primitive" ); + return g_nullNode; +} +void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { + Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); + Map_Read( root, tokeniser, entityTable, *this ); + tokeniser.release(); +} + +void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream, bool writeComments ) const { + TokenWriter& writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter( outputStream ); + Map_Write( root, traverse, writer, true, writeComments ); + writer.release(); +} }; typedef SingletonModule MapQ1Module; @@ -376,50 +357,46 @@ typedef SingletonModule MapQ1Module; MapQ1Module g_MapQ1Module; -class MapHalfLifeAPI : public TypeSystemRef, public MapFormat, public PrimitiveParser { +class MapHalfLifeAPI : public TypeSystemRef, public MapFormat, public PrimitiveParser +{ public: - typedef MapFormat Type; - - STRING_CONSTANT(Name, "maphl"); - - MapHalfLifeAPI() - { - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("half-life maps", "*.map")); - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("half-life region", "*.reg")); - } - - MapFormat *getTable() - { - return this; - } - - scene::Node &parsePrimitive(Tokeniser &tokeniser) const - { - const char *primitive = tokeniser.getToken(); - if (primitive != 0) { - if (string_equal(primitive, "(")) { - tokeniser.ungetToken(); // ( - return GlobalBrushModule::getTable().createBrush(); - } - } - - Tokeniser_unexpectedError(tokeniser, primitive, "#halflife-primitive"); - return g_nullNode; - } - - void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const - { - Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); - Map_Read(root, tokeniser, entityTable, *this); - tokeniser.release(); - } - - void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream, bool writeComments) const - { - TokenWriter &writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter(outputStream); - Map_Write(root, traverse, writer, true, writeComments); - writer.release(); - } +typedef MapFormat Type; + +STRING_CONSTANT( Name, "maphl" ); + +MapHalfLifeAPI(){ + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "half-life maps", "*.map" ) ); + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "half-life region", "*.reg" ) ); +} + +MapFormat* getTable(){ + return this; +} + +scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { + const char* primitive = tokeniser.getToken(); + if ( primitive != 0 ) { + if ( string_equal( primitive, "(" ) ) { + tokeniser.ungetToken(); // ( + return GlobalBrushModule::getTable().createBrush(); + } + } + + Tokeniser_unexpectedError( tokeniser, primitive, "#halflife-primitive" ); + return g_nullNode; +} + +void readGraph( scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable ) const { + Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); + Map_Read( root, tokeniser, entityTable, *this ); + tokeniser.release(); +} + +void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream, bool writeComments ) const { + TokenWriter& writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter( outputStream ); + Map_Write( root, traverse, writer, true, writeComments ); + writer.release(); +} }; typedef SingletonModule MapHalfLifeModule; @@ -427,50 +404,44 @@ typedef SingletonModule MapHalfLifeModule; MapHalfLifeModule g_MapHalfLifeModule; -class MapQ2API : public TypeSystemRef, public MapFormat, public PrimitiveParser { +class MapQ2API : public TypeSystemRef, public MapFormat, public PrimitiveParser +{ public: - typedef MapFormat Type; - - STRING_CONSTANT(Name, "mapq2"); - - MapQ2API() - { - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake2 maps", "*.map")); - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("quake2 region", "*.reg")); - } - - MapFormat *getTable() - { - return this; - } - - scene::Node &parsePrimitive(Tokeniser &tokeniser) const - { - const char *primitive = tokeniser.getToken(); - if (primitive != 0) { - if (string_equal(primitive, "(")) { - tokeniser.ungetToken(); // ( - return GlobalBrushModule::getTable().createBrush(); - } - } - - Tokeniser_unexpectedError(tokeniser, primitive, "#quake2-primitive"); - return g_nullNode; - } - - void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const - { - Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); - Map_Read(root, tokeniser, entityTable, *this); - tokeniser.release(); - } - - void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream, bool writeComments) const - { - TokenWriter &writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter(outputStream); - Map_Write(root, traverse, writer, true, writeComments); - writer.release(); - } +typedef MapFormat Type; + +STRING_CONSTANT( Name, "mapq2" ); + +MapQ2API(){ + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake2 maps", "*.map" ) ); + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "quake2 region", "*.reg" ) ); +} + +MapFormat* getTable(){ + return this; +} +scene::Node& parsePrimitive( Tokeniser& tokeniser ) const { + const char* primitive = tokeniser.getToken(); + if ( primitive != 0 ) { + if ( string_equal( primitive, "(" ) ) { + tokeniser.ungetToken(); // ( + return GlobalBrushModule::getTable().createBrush(); + } + } + + Tokeniser_unexpectedError( tokeniser, primitive, "#quake2-primitive" ); + return g_nullNode; +} +void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { + Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); + Map_Read( root, tokeniser, entityTable, *this ); + tokeniser.release(); +} + +void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream, bool writeComments ) const { + TokenWriter& writer = GlobalScripLibModule::getTable().m_pfnNewSimpleTokenWriter( outputStream ); + Map_Write( root, traverse, writer, true, writeComments ); + writer.release(); +} }; typedef SingletonModule MapQ2Module; @@ -480,9 +451,8 @@ MapQ2Module g_MapQ2Module; const char *PARSE_ERROR = "error parsing VMF"; -inline void parseToken(Tokeniser &tokeniser, const char *token) -{ - ASSERT_MESSAGE(Tokeniser_parseToken(tokeniser, token), "error parsing vmf: token not found: " << makeQuoted(token)); +inline void parseToken( Tokeniser& tokeniser, const char* token ){ + ASSERT_MESSAGE( Tokeniser_parseToken( tokeniser, token ), "error parsing vmf: token not found: " << makeQuoted( token ) ); } #include "generic/arrayrange.h" @@ -492,75 +462,67 @@ class VMFBlock; typedef ArrayConstRange VMFBlockArrayRange; -class VMFBlock { +class VMFBlock +{ public: - const char *m_name; - VMFBlockArrayRange m_children; - typedef const VMFBlock Value; - - VMFBlock(const char *name, VMFBlockArrayRange children = VMFBlockArrayRange(0, 0)) : m_name(name), - m_children(children) - { - } - - const char *name() const - { - return m_name; - } - - typedef Value *const_iterator; - - const_iterator begin() const - { - return m_children.first; - } - - const_iterator end() const - { - return m_children.last; - } +const char* m_name; +VMFBlockArrayRange m_children; +typedef const VMFBlock Value; + +VMFBlock( const char* name, VMFBlockArrayRange children = VMFBlockArrayRange( 0, 0 ) ) : m_name( name ), m_children( children ){ +} +const char* name() const { + return m_name; +} +typedef Value* const_iterator; + +const_iterator begin() const { + return m_children.first; +} + +const_iterator end() const { + return m_children.last; +} }; -const VMFBlock c_vmfNormals("normals"); -const VMFBlock c_vmfDistances("distances"); -const VMFBlock c_vmfOffsets("offsets"); -const VMFBlock c_vmfOffsetNormals("offset_normals"); -const VMFBlock c_vmfAlphas("alphas"); -const VMFBlock c_vmfTriangleTags("triangle_tags"); -const VMFBlock c_vmfAllowedVerts("allowed_verts"); -const VMFBlock c_vmfDispInfoChildren[] = {c_vmfNormals, c_vmfDistances, c_vmfOffsets, c_vmfOffsetNormals, c_vmfAlphas, - c_vmfTriangleTags, c_vmfAllowedVerts}; -const VMFBlock c_vmfDispInfo("dispinfo", ARRAY_RANGE(c_vmfDispInfoChildren)); -const VMFBlock c_vmfSideChildren[] = {c_vmfDispInfo}; -const VMFBlock c_vmfSide("side", ARRAY_RANGE(c_vmfSideChildren)); -const VMFBlock c_vmfEditor("editor"); -const VMFBlock c_vmfVersionInfo("versioninfo"); -const VMFBlock c_vmfViewSettings("viewsettings"); -const VMFBlock c_vmfCordon("cordon"); -const VMFBlock c_vmfGroupChildren[] = {c_vmfEditor}; -const VMFBlock c_vmfGroup("group", ARRAY_RANGE(c_vmfGroupChildren)); -const VMFBlock c_vmfCamera("camera"); -const VMFBlock c_vmfCamerasChildren[] = {c_vmfCamera}; -const VMFBlock c_vmfCameras("cameras", ARRAY_RANGE(c_vmfCamerasChildren)); -VMFBlock c_vmfVisGroup("visgroup"); -VMFBlock c_vmfVisGroups("visgroups", VMFBlockArrayRange(&c_vmfVisGroup, &c_vmfVisGroup + 1)); -const VMFBlock c_vmfSolidChildren[] = {c_vmfSide, c_vmfEditor}; -const VMFBlock c_vmfSolid("solid", ARRAY_RANGE(c_vmfSolidChildren)); -const VMFBlock c_vmfConnections("connections"); -const VMFBlock c_vmfEntityChildren[] = {c_vmfEditor, c_vmfSolid, c_vmfGroup, c_vmfConnections}; -const VMFBlock c_vmfEntity("entity", ARRAY_RANGE(c_vmfEntityChildren)); -const VMFBlock c_vmfWorldChildren[] = {c_vmfEditor, c_vmfSolid, c_vmfGroup}; -const VMFBlock c_vmfWorld("world", ARRAY_RANGE(c_vmfWorldChildren)); -const VMFBlock c_vmfRootChildren[] = {c_vmfVersionInfo, c_vmfViewSettings, c_vmfVisGroups, c_vmfWorld, c_vmfEntity, - c_vmfCameras, c_vmfCordon}; -const VMFBlock c_vmfRoot("", ARRAY_RANGE(c_vmfRootChildren)); - -class VMFInit { +const VMFBlock c_vmfNormals( "normals" ); +const VMFBlock c_vmfDistances( "distances" ); +const VMFBlock c_vmfOffsets( "offsets" ); +const VMFBlock c_vmfOffsetNormals( "offset_normals" ); +const VMFBlock c_vmfAlphas( "alphas" ); +const VMFBlock c_vmfTriangleTags( "triangle_tags" ); +const VMFBlock c_vmfAllowedVerts( "allowed_verts" ); +const VMFBlock c_vmfDispInfoChildren[] = { c_vmfNormals, c_vmfDistances, c_vmfOffsets, c_vmfOffsetNormals, c_vmfAlphas, c_vmfTriangleTags, c_vmfAllowedVerts }; +const VMFBlock c_vmfDispInfo( "dispinfo", ARRAY_RANGE( c_vmfDispInfoChildren ) ); +const VMFBlock c_vmfSideChildren[] = { c_vmfDispInfo }; +const VMFBlock c_vmfSide( "side", ARRAY_RANGE( c_vmfSideChildren ) ); +const VMFBlock c_vmfEditor( "editor" ); +const VMFBlock c_vmfVersionInfo( "versioninfo" ); +const VMFBlock c_vmfViewSettings( "viewsettings" ); +const VMFBlock c_vmfCordon( "cordon" ); +const VMFBlock c_vmfGroupChildren[] = { c_vmfEditor }; +const VMFBlock c_vmfGroup( "group", ARRAY_RANGE( c_vmfGroupChildren ) ); +const VMFBlock c_vmfCamera( "camera" ); +const VMFBlock c_vmfCamerasChildren[] = { c_vmfCamera }; +const VMFBlock c_vmfCameras( "cameras", ARRAY_RANGE( c_vmfCamerasChildren ) ); +VMFBlock c_vmfVisGroup( "visgroup" ); +VMFBlock c_vmfVisGroups( "visgroups", VMFBlockArrayRange( &c_vmfVisGroup, &c_vmfVisGroup + 1 ) ); +const VMFBlock c_vmfSolidChildren[] = { c_vmfSide, c_vmfEditor }; +const VMFBlock c_vmfSolid( "solid", ARRAY_RANGE( c_vmfSolidChildren ) ); +const VMFBlock c_vmfConnections( "connections" ); +const VMFBlock c_vmfEntityChildren[] = { c_vmfEditor, c_vmfSolid, c_vmfGroup, c_vmfConnections }; +const VMFBlock c_vmfEntity( "entity", ARRAY_RANGE( c_vmfEntityChildren ) ); +const VMFBlock c_vmfWorldChildren[] = { c_vmfEditor, c_vmfSolid, c_vmfGroup }; +const VMFBlock c_vmfWorld( "world", ARRAY_RANGE( c_vmfWorldChildren ) ); +const VMFBlock c_vmfRootChildren[] = { c_vmfVersionInfo, c_vmfViewSettings, c_vmfVisGroups, c_vmfWorld, c_vmfEntity, c_vmfCameras, c_vmfCordon }; +const VMFBlock c_vmfRoot( "", ARRAY_RANGE( c_vmfRootChildren ) ); + +class VMFInit +{ public: - VMFInit() - { - c_vmfVisGroup.m_children = VMFBlockArrayRange(&c_vmfVisGroup, &c_vmfVisGroup + 1); - } +VMFInit(){ + c_vmfVisGroup.m_children = VMFBlockArrayRange( &c_vmfVisGroup, &c_vmfVisGroup + 1 ); +} }; VMFInit g_VMFInit; @@ -568,82 +530,79 @@ VMFInit g_VMFInit; int g_vmf_entities; int g_vmf_brushes; -inline VMFBlock::const_iterator VMFBlock_find(const VMFBlock &block, const char *name) -{ - for (VMFBlock::const_iterator i = block.begin(); i != block.end(); ++i) { - if (string_equal(name, (*i).name())) { - return i; - } - } - return block.end(); +inline VMFBlock::const_iterator VMFBlock_find( const VMFBlock& block, const char* name ){ + for ( VMFBlock::const_iterator i = block.begin(); i != block.end(); ++i ) + { + if ( string_equal( name, ( *i ).name() ) ) { + return i; + } + } + return block.end(); } -void VMF_parseBlock(Tokeniser &tokeniser, const VMFBlock &block) -{ - for (;;) { - const char *key = tokeniser.getToken(); - if (key == 0 || string_equal(key, "}")) { - tokeniser.ungetToken(); - break; - } - CopiedString tmp(key); - tokeniser.nextLine(); - const char *value = tokeniser.getToken(); - tokeniser.nextLine(); - if (string_equal(value, "{")) { - VMFBlock::const_iterator i = VMFBlock_find(block, tmp.c_str()); - ASSERT_MESSAGE(i != block.end(), - "error parsing vmf block " << makeQuoted(block.name()) << ": unknown block: " - << makeQuoted(tmp.c_str())); - if (string_equal(tmp.c_str(), "solid")) { - ++g_vmf_brushes; - } else if (string_equal(tmp.c_str(), "entity") || string_equal(tmp.c_str(), "world")) { - ++g_vmf_entities; - } - VMF_parseBlock(tokeniser, *i); - parseToken(tokeniser, "}"); - tokeniser.nextLine(); - } else { - // was a pair - } - } -} - -void VMF_Read(scene::Node &root, Tokeniser &tokeniser, EntityCreator &entityTable) -{ - g_vmf_entities = g_vmf_brushes = 0; - VMF_parseBlock(tokeniser, c_vmfRoot); - globalOutputStream() << g_vmf_entities << " entities\n"; - globalOutputStream() << g_vmf_brushes << " brushes\n"; +void VMF_parseBlock( Tokeniser& tokeniser, const VMFBlock& block ){ + for (;; ) + { + const char* key = tokeniser.getToken(); + if ( key == 0 || string_equal( key, "}" ) ) { + tokeniser.ungetToken(); + break; + } + CopiedString tmp( key ); + tokeniser.nextLine(); + const char* value = tokeniser.getToken(); + tokeniser.nextLine(); + if ( string_equal( value, "{" ) ) { + VMFBlock::const_iterator i = VMFBlock_find( block, tmp.c_str() ); + ASSERT_MESSAGE( i != block.end(), "error parsing vmf block " << makeQuoted( block.name() ) << ": unknown block: " << makeQuoted( tmp.c_str() ) ); + if ( string_equal( tmp.c_str(), "solid" ) ) { + ++g_vmf_brushes; + } + else if ( string_equal( tmp.c_str(), "entity" ) || string_equal( tmp.c_str(), "world" ) ) { + ++g_vmf_entities; + } + VMF_parseBlock( tokeniser, *i ); + parseToken( tokeniser, "}" ); + tokeniser.nextLine(); + } + else + { + // was a pair + } + } +} + +void VMF_Read( scene::Node& root, Tokeniser& tokeniser, EntityCreator& entityTable ){ + g_vmf_entities = g_vmf_brushes = 0; + VMF_parseBlock( tokeniser, c_vmfRoot ); + globalOutputStream() << g_vmf_entities << " entities\n"; + globalOutputStream() << g_vmf_brushes << " brushes\n"; } -class MapVMFAPI : public TypeSystemRef, public MapFormat { +class MapVMFAPI : public TypeSystemRef, public MapFormat +{ public: - typedef MapFormat Type; - - STRING_CONSTANT(Name, "mapvmf"); - - MapVMFAPI() - { - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("vmf maps", "*.vmf")); - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("vmf region", "*.reg")); - } - - MapFormat *getTable() - { - return this; - } - - void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const - { - Tokeniser &tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser(inputStream); - VMF_Read(root, tokeniser, entityTable); - tokeniser.release(); - } - - void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream, bool writeComments) const - { - } +typedef MapFormat Type; + +STRING_CONSTANT( Name, "mapvmf" ); + +MapVMFAPI(){ + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "vmf maps", "*.vmf" ) ); + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "vmf region", "*.reg" ) ); +} + +MapFormat* getTable(){ + return this; +} + +void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { + Tokeniser& tokeniser = GlobalScripLibModule::getTable().m_pfnNewSimpleTokeniser( inputStream ); + VMF_Read( root, tokeniser, entityTable ); + tokeniser.release(); +} + +void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream, bool writeComments ) const { +} }; typedef SingletonModule MapVMFModule; @@ -651,15 +610,14 @@ typedef SingletonModule MapVMFModule; MapVMFModule g_MapVMFModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) -{ - initialiseModule(server); - - g_MapDoom3Module.selfRegister(); - g_MapQuake4Module.selfRegister(); - g_MapQ3Module.selfRegister(); - g_MapQ1Module.selfRegister(); - g_MapQ2Module.selfRegister(); - g_MapHalfLifeModule.selfRegister(); - g_MapVMFModule.selfRegister(); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ + initialiseModule( server ); + + g_MapDoom3Module.selfRegister(); + g_MapQuake4Module.selfRegister(); + g_MapQ3Module.selfRegister(); + g_MapQ1Module.selfRegister(); + g_MapQ2Module.selfRegister(); + g_MapHalfLifeModule.selfRegister(); + g_MapVMFModule.selfRegister(); } diff --git a/plugins/mapq3/write.cpp b/plugins/mapq3/write.cpp index 9cf9c48a..4bfbbe78 100644 --- a/plugins/mapq3/write.cpp +++ b/plugins/mapq3/write.cpp @@ -25,9 +25,8 @@ #include "iscriplib.h" #include "scenelib.h" -inline MapExporter *Node_getMapExporter(scene::Node &node) -{ - return NodeTypeCast::cast(node); +inline MapExporter* Node_getMapExporter( scene::Node& node ){ + return NodeTypeCast::cast( node ); } @@ -35,89 +34,86 @@ static std::size_t g_count_entities; static std::size_t g_count_brushes; -void Entity_ExportTokens(const Entity &entity, TokenWriter &writer) -{ - g_count_brushes = 0; - - class WriteKeyValue : public Entity::Visitor { - TokenWriter &m_writer; - public: - WriteKeyValue(TokenWriter &writer) - : m_writer(writer) - { - } - - void visit(const char *key, const char *value) - { - m_writer.writeString(key); - m_writer.writeString(value); - m_writer.nextLine(); - } - - } visitor(writer); - - entity.forEachKeyValue(visitor); +void Entity_ExportTokens( const Entity& entity, TokenWriter& writer ){ + g_count_brushes = 0; + + class WriteKeyValue : public Entity::Visitor + { + TokenWriter& m_writer; +public: + WriteKeyValue( TokenWriter& writer ) + : m_writer( writer ){ + } + + void visit( const char* key, const char* value ){ + m_writer.writeString( key ); + m_writer.writeString( value ); + m_writer.nextLine(); + } + + } visitor( writer ); + + entity.forEachKeyValue( visitor ); } -class WriteTokensWalker : public scene::Traversable::Walker { - mutable Stack m_stack; - TokenWriter &m_writer; - bool m_ignorePatches; - bool m_writeComments; +class WriteTokensWalker : public scene::Traversable::Walker +{ +mutable Stack m_stack; +TokenWriter& m_writer; +bool m_ignorePatches; +bool m_writeComments; public: - WriteTokensWalker(TokenWriter &writer, bool ignorePatches, bool writeComments) - : m_writer(writer), m_ignorePatches(ignorePatches), m_writeComments(writeComments) - { - } - - bool pre(scene::Node &node) const - { - m_stack.push(false); - - Entity *entity = Node_getEntity(node); - if (entity != 0) { - if (m_writeComments) { - m_writer.writeToken("//"); - m_writer.writeToken("entity"); - m_writer.writeUnsigned(g_count_entities++); - m_writer.nextLine(); - } - - m_writer.writeToken("{"); - m_writer.nextLine(); - m_stack.top() = true; - - Entity_ExportTokens(*entity, m_writer); - } else { - MapExporter *exporter = Node_getMapExporter(node); - if (exporter != 0 - && !(m_ignorePatches && Node_isPatch(node))) { - if (m_writeComments) { - m_writer.writeToken("//"); - m_writer.writeToken("brush"); - m_writer.writeUnsigned(g_count_brushes++); - m_writer.nextLine(); - } - - exporter->exportTokens(m_writer); - } - } - - return true; - } - - void post(scene::Node &node) const - { - if (m_stack.top()) { - m_writer.writeToken("}"); - m_writer.nextLine(); - } - m_stack.pop(); - } +WriteTokensWalker( TokenWriter& writer, bool ignorePatches, bool writeComments ) + : m_writer( writer ), m_ignorePatches( ignorePatches ), m_writeComments( writeComments ){ +} + +bool pre( scene::Node &node ) const { + m_stack.push( false ); + + Entity* entity = Node_getEntity( node ); + if ( entity != 0 ) { + if ( m_writeComments ) { + m_writer.writeToken( "//" ); + m_writer.writeToken( "entity" ); + m_writer.writeUnsigned( g_count_entities++ ); + m_writer.nextLine(); + } + + m_writer.writeToken( "{" ); + m_writer.nextLine(); + m_stack.top() = true; + + Entity_ExportTokens( *entity, m_writer ); + } + else + { + MapExporter* exporter = Node_getMapExporter( node ); + if ( exporter != 0 + && !( m_ignorePatches && Node_isPatch( node ) ) ) { + if ( m_writeComments ) { + m_writer.writeToken( "//" ); + m_writer.writeToken( "brush" ); + m_writer.writeUnsigned( g_count_brushes++ ); + m_writer.nextLine(); + } + + exporter->exportTokens( m_writer ); + } + } + + return true; +} + +void post( scene::Node& node ) const { + if ( m_stack.top() ) { + m_writer.writeToken( "}" ); + m_writer.nextLine(); + } + m_stack.pop(); +} }; -void Map_Write(scene::Node &root, GraphTraversalFunc traverse, TokenWriter &writer, bool ignorePatches, bool writeComments) -{ - g_count_entities = 0; - traverse(root, WriteTokensWalker(writer, ignorePatches, writeComments)); +void Map_Write( scene::Node& root, GraphTraversalFunc traverse, TokenWriter& writer, bool ignorePatches, bool writeComments ){ + g_count_entities = 0; + traverse( root, WriteTokensWalker( writer, ignorePatches, writeComments ) ); } diff --git a/plugins/mapq3/write.h b/plugins/mapq3/write.h index fbc131cf..ae07784d 100644 --- a/plugins/mapq3/write.h +++ b/plugins/mapq3/write.h @@ -24,6 +24,6 @@ #include "imap.h" -void Map_Write(scene::Node &root, GraphTraversalFunc traverse, TokenWriter &writer, bool ignorePatches, bool writeComments); +void Map_Write( scene::Node& root, GraphTraversalFunc traverse, TokenWriter& writer, bool ignorePatches, bool writeComments ); #endif diff --git a/plugins/mapxml/plugin.cpp b/plugins/mapxml/plugin.cpp index 73bccb17..516e06be 100644 --- a/plugins/mapxml/plugin.cpp +++ b/plugins/mapxml/plugin.cpp @@ -33,63 +33,57 @@ class MapXMLDependencies : - public GlobalRadiantModuleRef, - public GlobalBrushModuleRef, - public GlobalFiletypesModuleRef, - public GlobalEntityClassManagerModuleRef, - public GlobalSceneGraphModuleRef { - PatchModuleRef m_patchDef2Doom3Module; - PatchModuleRef m_patchDoom3Module; + public GlobalRadiantModuleRef, + public GlobalBrushModuleRef, + public GlobalFiletypesModuleRef, + public GlobalEntityClassManagerModuleRef, + public GlobalSceneGraphModuleRef +{ +PatchModuleRef m_patchDef2Doom3Module; +PatchModuleRef m_patchDoom3Module; public: - MapXMLDependencies() : - GlobalBrushModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("brushtypes")), - GlobalEntityClassManagerModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("entityclass")), - m_patchDef2Doom3Module("def2doom3"), - m_patchDoom3Module("doom3") - { - } - - BrushCreator &getBrushDoom3() - { - return GlobalBrushModule::getTable(); - } - - PatchCreator &getPatchDoom3() - { - return *m_patchDoom3Module.getTable(); - } - - PatchCreator &getPatchDef2Doom3() - { - return *m_patchDef2Doom3Module.getTable(); - } +MapXMLDependencies() : + GlobalBrushModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "brushtypes" ) ), + GlobalEntityClassManagerModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "entityclass" ) ), + m_patchDef2Doom3Module( "def2doom3" ), + m_patchDoom3Module( "doom3" ){ +} + +BrushCreator& getBrushDoom3(){ + return GlobalBrushModule::getTable(); +} + +PatchCreator& getPatchDoom3(){ + return *m_patchDoom3Module.getTable(); +} + +PatchCreator& getPatchDef2Doom3(){ + return *m_patchDef2Doom3Module.getTable(); +} }; -class MapXMLAPI : public TypeSystemRef, public MapFormat { +class MapXMLAPI : public TypeSystemRef, public MapFormat +{ public: - typedef MapFormat Type; +typedef MapFormat Type; - STRING_CONSTANT(Name, "xmldoom3"); +STRING_CONSTANT( Name, "xmldoom3" ); - MapXMLAPI() - { - GlobalFiletypesModule::getTable().addType(Type::Name(), Name(), filetype_t("xml doom3 maps", "*.xmap")); - } +MapXMLAPI(){ + GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "xml doom3 maps", "*.xmap" ) ); +} - MapFormat *getTable() - { - return this; - } +MapFormat* getTable(){ + return this; +} - void readGraph(scene::Node &root, TextInputStream &inputStream, EntityCreator &entityTable) const - { - Map_Read(root, inputStream, entityTable); - } +void readGraph( scene::Node& root, TextInputStream& inputStream, EntityCreator& entityTable ) const { + Map_Read( root, inputStream, entityTable ); +} - void writeGraph(scene::Node &root, GraphTraversalFunc traverse, TextOutputStream &outputStream, bool writeComments) const - { - Map_Write(root, traverse, outputStream); - } +void writeGraph( scene::Node& root, GraphTraversalFunc traverse, TextOutputStream& outputStream, bool writeComments ) const { + Map_Write( root, traverse, outputStream ); +} }; typedef SingletonModule MapXMLModule; @@ -97,12 +91,11 @@ typedef SingletonModule MapXMLModule; MapXMLModule g_MapXMLModule; -extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules(ModuleServer &server) -{ - GlobalErrorStream::instance().setOutputStream(server.getErrorStream()); - GlobalOutputStream::instance().setOutputStream(server.getOutputStream()); - GlobalDebugMessageHandler::instance().setHandler(server.getDebugMessageHandler()); - GlobalModuleServer::instance().set(server); +extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server ){ + GlobalErrorStream::instance().setOutputStream( server.getErrorStream() ); + GlobalOutputStream::instance().setOutputStream( server.getOutputStream() ); + GlobalDebugMessageHandler::instance().setHandler( server.getDebugMessageHandler() ); + GlobalModuleServer::instance().set( server ); - g_MapXMLModule.selfRegister(); + g_MapXMLModule.selfRegister(); } diff --git a/plugins/shaders/shaders.cpp b/plugins/shaders/shaders.cpp index a88fe2e3..f982605e 100644 --- a/plugins/shaders/shaders.cpp +++ b/plugins/shaders/shaders.cpp @@ -31,7 +31,7 @@ // // Shaders Manager Plugin // -// Leonardo Zide (leo@lokigames.com) +// Leonardo Zide ( leo@lokigames.com ) // #include "defaults.h" @@ -71,13 +71,13 @@ #include "archivelib.h" #include "imagelib.h" -const char *g_shadersExtension = ""; -const char *g_shadersDirectory = ""; +const char* g_shadersExtension = ""; +const char* g_shadersDirectory = ""; bool g_enableDefaultShaders = true; ShaderLanguage g_shaderLanguage = SHADERLANGUAGE_QUAKE3; bool g_useShaderList = true; -_QERPlugImageTable *g_bitmapModule = 0; -const char *g_texturePrefix = DEFAULT_TEXTURE_DIRNAME; +_QERPlugImageTable* g_bitmapModule = 0; +const char* g_texturePrefix = DEFAULT_TEXTURE_DIRNAME; void ActiveShaders_IteratorBegin(); @@ -91,9 +91,9 @@ Callback g_ActiveShadersChangedNotify; void FreeShaders(); -void LoadShaderFile(const char *filename); +void LoadShaderFile( const char *filename ); -qtexture_t *Texture_ForName(const char *filename); +qtexture_t *Texture_ForName( const char *filename ); /*! @@ -103,49 +103,47 @@ qtexture_t *Texture_ForName(const char *filename); this was in the initial design of the shader code since early GtkRadiant alpha, and got sort of foxed in 1.2 and put back in */ -Image *loadBitmap(void *environment, const char *name) -{ - DirectoryArchiveFile file(name, name); - if (!file.failed()) { - return g_bitmapModule->loadImage(file); - } - return 0; +Image* loadBitmap( void* environment, const char* name ){ + DirectoryArchiveFile file( name, name ); + if ( !file.failed() ) { + return g_bitmapModule->loadImage( file ); + } + return 0; } -inline byte *getPixel(byte *pixels, int width, int height, int x, int y) -{ - return pixels + (((((y + height) % height) * width) + ((x + width) % width)) * 4); +inline byte* getPixel( byte* pixels, int width, int height, int x, int y ){ + return pixels + ( ( ( ( ( y + height ) % height ) * width ) + ( ( x + width ) % width ) ) * 4 ); } -class KernelElement { +class KernelElement +{ public: - int x, y; - float w; +int x, y; +float w; }; -Image &convertHeightmapToNormalmap(Image &heightmap, float scale) -{ - int w = heightmap.getWidth(); - int h = heightmap.getHeight(); +Image& convertHeightmapToNormalmap( Image& heightmap, float scale ){ + int w = heightmap.getWidth(); + int h = heightmap.getHeight(); - Image &normalmap = *(new RGBAImage(heightmap.getWidth(), heightmap.getHeight())); + Image& normalmap = *( new RGBAImage( heightmap.getWidth(), heightmap.getHeight() ) ); - byte *in = heightmap.getRGBAPixels(); - byte *out = normalmap.getRGBAPixels(); + byte* in = heightmap.getRGBAPixels(); + byte* out = normalmap.getRGBAPixels(); #if 1 - // no filtering - const int kernelSize = 2; - KernelElement kernel_du[kernelSize] = { - {-1, 0, -0.5f}, - {1, 0, 0.5f} - }; - KernelElement kernel_dv[kernelSize] = { - {0, 1, 0.5f}, - {0, -1, -0.5f} - }; + // no filtering + const int kernelSize = 2; + KernelElement kernel_du[kernelSize] = { + {-1, 0,-0.5f }, + { 1, 0, 0.5f } + }; + KernelElement kernel_dv[kernelSize] = { + { 0, 1, 0.5f }, + { 0,-1,-0.5f } + }; #else - // 3x3 Prewitt + // 3x3 Prewitt const int kernelSize = 6; KernelElement kernel_du[kernelSize] = { {-1, 1,-1.0f }, @@ -165,52 +163,56 @@ Image &convertHeightmapToNormalmap(Image &heightmap, float scale) }; #endif - int x, y = 0; - while (y < h) { - x = 0; - while (x < w) { - float du = 0; - for (KernelElement *i = kernel_du; i != kernel_du + kernelSize; ++i) { - du += (getPixel(in, w, h, x + (*i).x, y + (*i).y)[0] / 255.0) * (*i).w; - } - float dv = 0; - for (KernelElement *i = kernel_dv; i != kernel_dv + kernelSize; ++i) { - dv += (getPixel(in, w, h, x + (*i).x, y + (*i).y)[0] / 255.0) * (*i).w; - } - - float nx = -du * scale; - float ny = -dv * scale; - float nz = 1.0; - - // Normalize - float norm = 1.0 / sqrt(nx * nx + ny * ny + nz * nz); - out[0] = float_to_integer(((nx * norm) + 1) * 127.5); - out[1] = float_to_integer(((ny * norm) + 1) * 127.5); - out[2] = float_to_integer(((nz * norm) + 1) * 127.5); - out[3] = 255; - - x++; - out += 4; - } - - y++; - } - - return normalmap; -} - -Image *loadHeightmap(void *environment, const char *name) -{ - Image *heightmap = GlobalTexturesCache().loadImage(name); - if (heightmap != 0) { - Image &normalmap = convertHeightmapToNormalmap(*heightmap, *reinterpret_cast( environment )); - heightmap->release(); - return &normalmap; - } - return 0; + int x, y = 0; + while ( y < h ) + { + x = 0; + while ( x < w ) + { + float du = 0; + for ( KernelElement* i = kernel_du; i != kernel_du + kernelSize; ++i ) + { + du += ( getPixel( in, w, h, x + ( *i ).x, y + ( *i ).y )[0] / 255.0 ) * ( *i ).w; + } + float dv = 0; + for ( KernelElement* i = kernel_dv; i != kernel_dv + kernelSize; ++i ) + { + dv += ( getPixel( in, w, h, x + ( *i ).x, y + ( *i ).y )[0] / 255.0 ) * ( *i ).w; + } + + float nx = -du * scale; + float ny = -dv * scale; + float nz = 1.0; + + // Normalize + float norm = 1.0 / sqrt( nx * nx + ny * ny + nz * nz ); + out[0] = float_to_integer( ( ( nx * norm ) + 1 ) * 127.5 ); + out[1] = float_to_integer( ( ( ny * norm ) + 1 ) * 127.5 ); + out[2] = float_to_integer( ( ( nz * norm ) + 1 ) * 127.5 ); + out[3] = 255; + + x++; + out += 4; + } + + y++; + } + + return normalmap; +} + +Image* loadHeightmap( void* environment, const char* name ){ + Image* heightmap = GlobalTexturesCache().loadImage( name ); + if ( heightmap != 0 ) { + Image& normalmap = convertHeightmapToNormalmap( *heightmap, *reinterpret_cast( environment ) ); + heightmap->release(); + return &normalmap; + } + return 0; } -class ShaderPoolContext { +class ShaderPoolContext +{ }; typedef Static ShaderPool; @@ -225,45 +227,40 @@ typedef CopiedString TextureExpression; // we compare as case insensitive. That is Radiant is case insensitive, but knows that the engine is case sensitive. //++timo FIXME: we need to put code somewhere to detect when two shaders that are case insensitive equal are present template -void parseTextureName(StringType &name, const char *token) -{ - StringOutputStream cleaned(256); - cleaned << PathCleaned(token); - name = CopiedString( - StringRange(cleaned.c_str(), path_get_filename_base_end(cleaned.c_str()))).c_str(); // remove extension +void parseTextureName( StringType& name, const char* token ){ + StringOutputStream cleaned( 256 ); + cleaned << PathCleaned( token ); + name = CopiedString( StringRange( cleaned.c_str(), path_get_filename_base_end( cleaned.c_str() ) ) ).c_str(); // remove extension } -bool Tokeniser_parseTextureName(Tokeniser &tokeniser, TextureExpression &name) -{ - const char *token = tokeniser.getToken(); - if (token == 0) { - Tokeniser_unexpectedError(tokeniser, token, "#texture-name"); - return false; - } - parseTextureName(name, token); - return true; +bool Tokeniser_parseTextureName( Tokeniser& tokeniser, TextureExpression& name ){ + const char* token = tokeniser.getToken(); + if ( token == 0 ) { + Tokeniser_unexpectedError( tokeniser, token, "#texture-name" ); + return false; + } + parseTextureName( name, token ); + return true; } -bool Tokeniser_parseShaderName(Tokeniser &tokeniser, CopiedString &name) -{ - const char *token = tokeniser.getToken(); - if (token == 0) { - Tokeniser_unexpectedError(tokeniser, token, "#shader-name"); - return false; - } - parseTextureName(name, token); - return true; +bool Tokeniser_parseShaderName( Tokeniser& tokeniser, CopiedString& name ){ + const char* token = tokeniser.getToken(); + if ( token == 0 ) { + Tokeniser_unexpectedError( tokeniser, token, "#shader-name" ); + return false; + } + parseTextureName( name, token ); + return true; } -bool Tokeniser_parseString(Tokeniser &tokeniser, ShaderString &string) -{ - const char *token = tokeniser.getToken(); - if (token == 0) { - Tokeniser_unexpectedError(tokeniser, token, "#string"); - return false; - } - string = token; - return true; +bool Tokeniser_parseString( Tokeniser& tokeniser, ShaderString& string ){ + const char* token = tokeniser.getToken(); + if ( token == 0 ) { + Tokeniser_unexpectedError( tokeniser, token, "#string" ); + return false; + } + string = token; + return true; } @@ -272,393 +269,414 @@ typedef std::list ShaderArguments; typedef std::pair BlendFuncExpression; -class ShaderTemplate { - std::size_t m_refcount; - CopiedString m_Name; +class ShaderTemplate +{ +std::size_t m_refcount; +CopiedString m_Name; public: - ShaderParameters m_params; +ShaderParameters m_params; - TextureExpression m_textureName; - TextureExpression m_diffuse; - TextureExpression m_bump; - ShaderValue m_heightmapScale; - TextureExpression m_specular; - TextureExpression m_lightFalloffImage; +TextureExpression m_textureName; +TextureExpression m_diffuse; +TextureExpression m_bump; +ShaderValue m_heightmapScale; +TextureExpression m_specular; +TextureExpression m_lightFalloffImage; - int m_nFlags; - float m_fTrans; +int m_nFlags; +float m_fTrans; // alphafunc stuff - IShader::EAlphaFunc m_AlphaFunc; - float m_AlphaRef; +IShader::EAlphaFunc m_AlphaFunc; +float m_AlphaRef; // cull stuff - IShader::ECull m_Cull; - - ShaderTemplate() : - m_refcount(0) - { - m_nFlags = 0; - m_fTrans = 1.0f; - } - - void IncRef() - { - ++m_refcount; - } - - void DecRef() - { - ASSERT_MESSAGE(m_refcount != 0, "shader reference-count going below zero"); - if (--m_refcount == 0) { - delete this; - } - } - - std::size_t refcount() - { - return m_refcount; - } - - const char *getName() const - { - return m_Name.c_str(); - } - - void setName(const char *name) - { - m_Name = name; - } +IShader::ECull m_Cull; + +ShaderTemplate() : + m_refcount( 0 ){ + m_nFlags = 0; + m_fTrans = 1.0f; +} + +void IncRef(){ + ++m_refcount; +} + +void DecRef(){ + ASSERT_MESSAGE( m_refcount != 0, "shader reference-count going below zero" ); + if ( --m_refcount == 0 ) { + delete this; + } +} + +std::size_t refcount(){ + return m_refcount; +} + +const char* getName() const { + return m_Name.c_str(); +} + +void setName( const char* name ){ + m_Name = name; +} // ----------------------------------------- - bool parseDoom3(Tokeniser &tokeniser); - - bool parseQuake3(Tokeniser &tokeniser); - - bool parseTemplate(Tokeniser &tokeniser); - - - void CreateDefault(const char *name) - { - if (g_enableDefaultShaders) { - m_textureName = name; - } else { - m_textureName = ""; - } - setName(name); - } - - - class MapLayerTemplate { - TextureExpression m_texture; - BlendFuncExpression m_blendFunc; - bool m_clampToBorder; - ShaderValue m_alphaTest; - public: - MapLayerTemplate(const TextureExpression &texture, const BlendFuncExpression &blendFunc, bool clampToBorder, - const ShaderValue &alphaTest) : - m_texture(texture), - m_blendFunc(blendFunc), - m_clampToBorder(false), - m_alphaTest(alphaTest) - { - } - - const TextureExpression &texture() const - { - return m_texture; - } - - const BlendFuncExpression &blendFunc() const - { - return m_blendFunc; - } - - bool clampToBorder() const - { - return m_clampToBorder; - } - - const ShaderValue &alphaTest() const - { - return m_alphaTest; - } - }; - - typedef std::vector MapLayers; - MapLayers m_layers; -}; +bool parseDoom3( Tokeniser& tokeniser ); +bool parseQuake3( Tokeniser& tokeniser ); -bool Doom3Shader_parseHeightmap(Tokeniser &tokeniser, TextureExpression &bump, ShaderValue &heightmapScale) -{ - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); - RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, bump)); - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ",")); - RETURN_FALSE_IF_FAIL(Tokeniser_parseString(tokeniser, heightmapScale)); - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")")); - return true; +bool parseTemplate( Tokeniser& tokeniser ); + + +void CreateDefault( const char *name ){ + if ( g_enableDefaultShaders ) { + m_textureName = name; + } + else + { + m_textureName = ""; + } + setName( name ); } -bool Doom3Shader_parseAddnormals(Tokeniser &tokeniser, TextureExpression &bump) -{ - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); - RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, bump)); - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ",")); - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "heightmap")); - TextureExpression heightmapName; - ShaderValue heightmapScale; - RETURN_FALSE_IF_FAIL(Doom3Shader_parseHeightmap(tokeniser, heightmapName, heightmapScale)); - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")")); - return true; -} - -bool Doom3Shader_parseBumpmap(Tokeniser &tokeniser, TextureExpression &bump, ShaderValue &heightmapScale) + +class MapLayerTemplate { - const char *token = tokeniser.getToken(); - if (token == 0) { - Tokeniser_unexpectedError(tokeniser, token, "#bumpmap"); - return false; - } - if (string_equal(token, "heightmap")) { - RETURN_FALSE_IF_FAIL(Doom3Shader_parseHeightmap(tokeniser, bump, heightmapScale)); - } else if (string_equal(token, "addnormals")) { - RETURN_FALSE_IF_FAIL(Doom3Shader_parseAddnormals(tokeniser, bump)); - } else { - parseTextureName(bump, token); - } - return true; -} - -enum LayerTypeId { - LAYER_NONE, - LAYER_BLEND, - LAYER_DIFFUSEMAP, - LAYER_BUMPMAP, - LAYER_SPECULARMAP +TextureExpression m_texture; +BlendFuncExpression m_blendFunc; +bool m_clampToBorder; +ShaderValue m_alphaTest; +public: +MapLayerTemplate( const TextureExpression& texture, const BlendFuncExpression& blendFunc, bool clampToBorder, const ShaderValue& alphaTest ) : + m_texture( texture ), + m_blendFunc( blendFunc ), + m_clampToBorder( false ), + m_alphaTest( alphaTest ){ +} + +const TextureExpression& texture() const { + return m_texture; +} + +const BlendFuncExpression& blendFunc() const { + return m_blendFunc; +} + +bool clampToBorder() const { + return m_clampToBorder; +} + +const ShaderValue& alphaTest() const { + return m_alphaTest; +} }; -class LayerTemplate { -public: - LayerTypeId m_type; - TextureExpression m_texture; - BlendFuncExpression m_blendFunc; - bool m_clampToBorder; - ShaderValue m_alphaTest; - ShaderValue m_heightmapScale; - - LayerTemplate() : m_type(LAYER_NONE), m_blendFunc("GL_ONE", "GL_ZERO"), m_clampToBorder(false), m_alphaTest("-1"), - m_heightmapScale("0") - { - } +typedef std::vector MapLayers; +MapLayers m_layers; }; -bool parseShaderParameters(Tokeniser &tokeniser, ShaderParameters ¶ms) + +bool Doom3Shader_parseHeightmap( Tokeniser& tokeniser, TextureExpression& bump, ShaderValue& heightmapScale ){ + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) ); + RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, bump ) ); + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "," ) ); + RETURN_FALSE_IF_FAIL( Tokeniser_parseString( tokeniser, heightmapScale ) ); + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) ); + return true; +} + +bool Doom3Shader_parseAddnormals( Tokeniser& tokeniser, TextureExpression& bump ){ + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) ); + RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, bump ) ); + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "," ) ); + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "heightmap" ) ); + TextureExpression heightmapName; + ShaderValue heightmapScale; + RETURN_FALSE_IF_FAIL( Doom3Shader_parseHeightmap( tokeniser, heightmapName, heightmapScale ) ); + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) ); + return true; +} + +bool Doom3Shader_parseBumpmap( Tokeniser& tokeniser, TextureExpression& bump, ShaderValue& heightmapScale ){ + const char* token = tokeniser.getToken(); + if ( token == 0 ) { + Tokeniser_unexpectedError( tokeniser, token, "#bumpmap" ); + return false; + } + if ( string_equal( token, "heightmap" ) ) { + RETURN_FALSE_IF_FAIL( Doom3Shader_parseHeightmap( tokeniser, bump, heightmapScale ) ); + } + else if ( string_equal( token, "addnormals" ) ) { + RETURN_FALSE_IF_FAIL( Doom3Shader_parseAddnormals( tokeniser, bump ) ); + } + else + { + parseTextureName( bump, token ); + } + return true; +} + +enum LayerTypeId { - Tokeniser_parseToken(tokeniser, "("); - for (;;) { - const char *param = tokeniser.getToken(); - if (string_equal(param, ")")) { - break; - } - params.push_back(param); - const char *comma = tokeniser.getToken(); - if (string_equal(comma, ")")) { - break; - } - if (!string_equal(comma, ",")) { - Tokeniser_unexpectedError(tokeniser, comma, ","); - return false; - } - } - return true; -} - -bool ShaderTemplate::parseTemplate(Tokeniser &tokeniser) + LAYER_NONE, + LAYER_BLEND, + LAYER_DIFFUSEMAP, + LAYER_BUMPMAP, + LAYER_SPECULARMAP +}; + +class LayerTemplate { - m_Name = tokeniser.getToken(); - if (!parseShaderParameters(tokeniser, m_params)) { - globalErrorStream() << "shader template: " << makeQuoted(m_Name.c_str()) << ": parameter parse failed\n"; - return false; - } +public: +LayerTypeId m_type; +TextureExpression m_texture; +BlendFuncExpression m_blendFunc; +bool m_clampToBorder; +ShaderValue m_alphaTest; +ShaderValue m_heightmapScale; + +LayerTemplate() : m_type( LAYER_NONE ), m_blendFunc( "GL_ONE", "GL_ZERO" ), m_clampToBorder( false ), m_alphaTest( "-1" ), m_heightmapScale( "0" ){ +} +}; - return parseDoom3(tokeniser); +bool parseShaderParameters( Tokeniser& tokeniser, ShaderParameters& params ){ + Tokeniser_parseToken( tokeniser, "(" ); + for (;; ) + { + const char* param = tokeniser.getToken(); + if ( string_equal( param, ")" ) ) { + break; + } + params.push_back( param ); + const char* comma = tokeniser.getToken(); + if ( string_equal( comma, ")" ) ) { + break; + } + if ( !string_equal( comma, "," ) ) { + Tokeniser_unexpectedError( tokeniser, comma, "," ); + return false; + } + } + return true; } -bool ShaderTemplate::parseDoom3(Tokeniser &tokeniser) -{ - LayerTemplate currentLayer; - bool isFog = false; - - // we need to read until we hit a balanced } - int depth = 0; - for (;;) { - tokeniser.nextLine(); - const char *token = tokeniser.getToken(); - - if (token == 0) { - return false; - } - - if (string_equal(token, "{")) { - ++depth; - continue; - } else if (string_equal(token, "}")) { - --depth; - if (depth < 0) { // error - return false; - } - if (depth == 0) { // end of shader - break; - } - if (depth == 1) { // end of layer - if (currentLayer.m_type == LAYER_DIFFUSEMAP) { - m_diffuse = currentLayer.m_texture; - } else if (currentLayer.m_type == LAYER_BUMPMAP) { - m_bump = currentLayer.m_texture; - } else if (currentLayer.m_type == LAYER_SPECULARMAP) { - m_specular = currentLayer.m_texture; - } else if (!string_empty(currentLayer.m_texture.c_str())) { - m_layers.push_back(MapLayerTemplate( - currentLayer.m_texture.c_str(), - currentLayer.m_blendFunc, - currentLayer.m_clampToBorder, - currentLayer.m_alphaTest - )); - } - currentLayer.m_type = LAYER_NONE; - currentLayer.m_texture = ""; - } - continue; - } - - if (depth == 2) { // in layer - if (string_equal_nocase(token, "blend")) { - const char *blend = tokeniser.getToken(); - - if (blend == 0) { - Tokeniser_unexpectedError(tokeniser, blend, "#blend"); - return false; - } - - if (string_equal_nocase(blend, "diffusemap")) { - currentLayer.m_type = LAYER_DIFFUSEMAP; - } else if (string_equal_nocase(blend, "bumpmap")) { - currentLayer.m_type = LAYER_BUMPMAP; - } else if (string_equal_nocase(blend, "specularmap")) { - currentLayer.m_type = LAYER_SPECULARMAP; - } else { - currentLayer.m_blendFunc.first = blend; - - const char *comma = tokeniser.getToken(); - - if (comma == 0) { - Tokeniser_unexpectedError(tokeniser, comma, "#comma"); - return false; - } - - if (string_equal(comma, ",")) { - RETURN_FALSE_IF_FAIL(Tokeniser_parseString(tokeniser, currentLayer.m_blendFunc.second)); - } else { - currentLayer.m_blendFunc.second = ""; - tokeniser.ungetToken(); - } - } - } else if (string_equal_nocase(token, "map")) { - if (currentLayer.m_type == LAYER_BUMPMAP) { - RETURN_FALSE_IF_FAIL( - Doom3Shader_parseBumpmap(tokeniser, currentLayer.m_texture, currentLayer.m_heightmapScale)); - } else { - const char *map = tokeniser.getToken(); - - if (map == 0) { - Tokeniser_unexpectedError(tokeniser, map, "#map"); - return false; - } - - if (string_equal(map, "makealpha")) { - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); - const char *texture = tokeniser.getToken(); - if (texture == 0) { - Tokeniser_unexpectedError(tokeniser, texture, "#texture"); - return false; - } - currentLayer.m_texture = texture; - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")")); - } else { - parseTextureName(currentLayer.m_texture, map); - } - } - } else if (string_equal_nocase(token, "zeroclamp")) { - currentLayer.m_clampToBorder = true; - } +bool ShaderTemplate::parseTemplate( Tokeniser& tokeniser ){ + m_Name = tokeniser.getToken(); + if ( !parseShaderParameters( tokeniser, m_params ) ) { + globalErrorStream() << "shader template: " << makeQuoted( m_Name.c_str() ) << ": parameter parse failed\n"; + return false; + } + + return parseDoom3( tokeniser ); +} + +bool ShaderTemplate::parseDoom3( Tokeniser& tokeniser ){ + LayerTemplate currentLayer; + bool isFog = false; + + // we need to read until we hit a balanced } + int depth = 0; + for (;; ) + { + tokeniser.nextLine(); + const char* token = tokeniser.getToken(); + + if ( token == 0 ) { + return false; + } + + if ( string_equal( token, "{" ) ) { + ++depth; + continue; + } + else if ( string_equal( token, "}" ) ) { + --depth; + if ( depth < 0 ) { // error + return false; + } + if ( depth == 0 ) { // end of shader + break; + } + if ( depth == 1 ) { // end of layer + if ( currentLayer.m_type == LAYER_DIFFUSEMAP ) { + m_diffuse = currentLayer.m_texture; + } + else if ( currentLayer.m_type == LAYER_BUMPMAP ) { + m_bump = currentLayer.m_texture; + } + else if ( currentLayer.m_type == LAYER_SPECULARMAP ) { + m_specular = currentLayer.m_texture; + } + else if ( !string_empty( currentLayer.m_texture.c_str() ) ) { + m_layers.push_back( MapLayerTemplate( + currentLayer.m_texture.c_str(), + currentLayer.m_blendFunc, + currentLayer.m_clampToBorder, + currentLayer.m_alphaTest + ) ); + } + currentLayer.m_type = LAYER_NONE; + currentLayer.m_texture = ""; + } + continue; + } + + if ( depth == 2 ) { // in layer + if ( string_equal_nocase( token, "blend" ) ) { + const char* blend = tokeniser.getToken(); + + if ( blend == 0 ) { + Tokeniser_unexpectedError( tokeniser, blend, "#blend" ); + return false; + } + + if ( string_equal_nocase( blend, "diffusemap" ) ) { + currentLayer.m_type = LAYER_DIFFUSEMAP; + } + else if ( string_equal_nocase( blend, "bumpmap" ) ) { + currentLayer.m_type = LAYER_BUMPMAP; + } + else if ( string_equal_nocase( blend, "specularmap" ) ) { + currentLayer.m_type = LAYER_SPECULARMAP; + } + else + { + currentLayer.m_blendFunc.first = blend; + + const char* comma = tokeniser.getToken(); + + if ( comma == 0 ) { + Tokeniser_unexpectedError( tokeniser, comma, "#comma" ); + return false; + } + + if ( string_equal( comma, "," ) ) { + RETURN_FALSE_IF_FAIL( Tokeniser_parseString( tokeniser, currentLayer.m_blendFunc.second ) ); + } + else + { + currentLayer.m_blendFunc.second = ""; + tokeniser.ungetToken(); + } + } + } + else if ( string_equal_nocase( token, "map" ) ) { + if ( currentLayer.m_type == LAYER_BUMPMAP ) { + RETURN_FALSE_IF_FAIL( Doom3Shader_parseBumpmap( tokeniser, currentLayer.m_texture, currentLayer.m_heightmapScale ) ); + } + else + { + const char* map = tokeniser.getToken(); + + if ( map == 0 ) { + Tokeniser_unexpectedError( tokeniser, map, "#map" ); + return false; + } + + if ( string_equal( map, "makealpha" ) ) { + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) ); + const char* texture = tokeniser.getToken(); + if ( texture == 0 ) { + Tokeniser_unexpectedError( tokeniser, texture, "#texture" ); + return false; + } + currentLayer.m_texture = texture; + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) ); + } + else + { + parseTextureName( currentLayer.m_texture, map ); + } + } + } + else if ( string_equal_nocase( token, "zeroclamp" ) ) { + currentLayer.m_clampToBorder = true; + } #if 0 - else if ( string_equal_nocase( token, "alphaTest" ) ) { + else if ( string_equal_nocase( token, "alphaTest" ) ) { Tokeniser_getFloat( tokeniser, currentLayer.m_alphaTest ); } #endif - } else if (depth == 1) { - if (string_equal_nocase(token, "qer_editorimage")) { - RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, m_textureName)); - } else if (string_equal_nocase(token, "qer_trans")) { - m_fTrans = string_read_float(tokeniser.getToken()); - m_nFlags |= QER_TRANS; - } else if (string_equal_nocase(token, "translucent")) { - m_fTrans = 1; - m_nFlags |= QER_TRANS; - } else if (string_equal(token, "DECAL_MACRO")) { - m_fTrans = 1; - m_nFlags |= QER_TRANS; - } else if (string_equal_nocase(token, "bumpmap")) { - RETURN_FALSE_IF_FAIL(Doom3Shader_parseBumpmap(tokeniser, m_bump, m_heightmapScale)); - } else if (string_equal_nocase(token, "diffusemap")) { - RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, m_diffuse)); - } else if (string_equal_nocase(token, "specularmap")) { - RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, m_specular)); - } else if (string_equal_nocase(token, "twosided")) { - m_Cull = IShader::eCullNone; - m_nFlags |= QER_CULL; - } else if (string_equal_nocase(token, "nodraw")) { - m_nFlags |= QER_NODRAW; - } else if (string_equal_nocase(token, "nonsolid")) { - m_nFlags |= QER_NONSOLID; - } else if (string_equal_nocase(token, "liquid")) { - m_nFlags |= QER_WATER; - } else if (string_equal_nocase(token, "areaportal")) { - m_nFlags |= QER_AREAPORTAL; - } else if (string_equal_nocase(token, "playerclip") - || string_equal_nocase(token, "monsterclip") - || string_equal_nocase(token, "ikclip") - || string_equal_nocase(token, "moveableclip")) { - m_nFlags |= QER_CLIP; - } - if (string_equal_nocase(token, "fogLight")) { - isFog = true; - } else if (!isFog && string_equal_nocase(token, "lightFalloffImage")) { - const char *lightFalloffImage = tokeniser.getToken(); - if (lightFalloffImage == 0) { - Tokeniser_unexpectedError(tokeniser, lightFalloffImage, "#lightFalloffImage"); - return false; - } - if (string_equal_nocase(lightFalloffImage, "makeintensity")) { - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, "(")); - TextureExpression name; - RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, name)); - m_lightFalloffImage = name; - RETURN_FALSE_IF_FAIL(Tokeniser_parseToken(tokeniser, ")")); - } else { - m_lightFalloffImage = lightFalloffImage; - } - } - } - } - - if (string_empty(m_textureName.c_str())) { - m_textureName = m_diffuse; - } - - return true; + } + else if ( depth == 1 ) { + if ( string_equal_nocase( token, "qer_editorimage" ) ) { + RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, m_textureName ) ); + } + else if ( string_equal_nocase( token, "qer_trans" ) ) { + m_fTrans = string_read_float( tokeniser.getToken() ); + m_nFlags |= QER_TRANS; + } + else if ( string_equal_nocase( token, "translucent" ) ) { + m_fTrans = 1; + m_nFlags |= QER_TRANS; + } + else if ( string_equal( token, "DECAL_MACRO" ) ) { + m_fTrans = 1; + m_nFlags |= QER_TRANS; + } + else if ( string_equal_nocase( token, "bumpmap" ) ) { + RETURN_FALSE_IF_FAIL( Doom3Shader_parseBumpmap( tokeniser, m_bump, m_heightmapScale ) ); + } + else if ( string_equal_nocase( token, "diffusemap" ) ) { + RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, m_diffuse ) ); + } + else if ( string_equal_nocase( token, "specularmap" ) ) { + RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, m_specular ) ); + } + else if ( string_equal_nocase( token, "twosided" ) ) { + m_Cull = IShader::eCullNone; + m_nFlags |= QER_CULL; + } + else if ( string_equal_nocase( token, "nodraw" ) ) { + m_nFlags |= QER_NODRAW; + } + else if ( string_equal_nocase( token, "nonsolid" ) ) { + m_nFlags |= QER_NONSOLID; + } + else if ( string_equal_nocase( token, "liquid" ) ) { + m_nFlags |= QER_WATER; + } + else if ( string_equal_nocase( token, "areaportal" ) ) { + m_nFlags |= QER_AREAPORTAL; + } + else if ( string_equal_nocase( token, "playerclip" ) + || string_equal_nocase( token, "monsterclip" ) + || string_equal_nocase( token, "ikclip" ) + || string_equal_nocase( token, "moveableclip" ) ) { + m_nFlags |= QER_CLIP; + } + if ( string_equal_nocase( token, "fogLight" ) ) { + isFog = true; + } + else if ( !isFog && string_equal_nocase( token, "lightFalloffImage" ) ) { + const char* lightFalloffImage = tokeniser.getToken(); + if ( lightFalloffImage == 0 ) { + Tokeniser_unexpectedError( tokeniser, lightFalloffImage, "#lightFalloffImage" ); + return false; + } + if ( string_equal_nocase( lightFalloffImage, "makeintensity" ) ) { + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, "(" ) ); + TextureExpression name; + RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, name ) ); + m_lightFalloffImage = name; + RETURN_FALSE_IF_FAIL( Tokeniser_parseToken( tokeniser, ")" ) ); + } + else + { + m_lightFalloffImage = lightFalloffImage; + } + } + } + } + + if ( string_empty( m_textureName.c_str() ) ) { + m_textureName = m_diffuse; + } + + return true; } typedef SmartPointer ShaderTemplatePointer; @@ -667,476 +685,439 @@ typedef std::map ShaderTemplateMap; ShaderTemplateMap g_shaders; ShaderTemplateMap g_shaderTemplates; -ShaderTemplate *findTemplate(const char *name) -{ - ShaderTemplateMap::iterator i = g_shaderTemplates.find(name); - if (i != g_shaderTemplates.end()) { - return (*i).second.get(); - } - return 0; +ShaderTemplate* findTemplate( const char* name ){ + ShaderTemplateMap::iterator i = g_shaderTemplates.find( name ); + if ( i != g_shaderTemplates.end() ) { + return ( *i ).second.get(); + } + return 0; } -class ShaderDefinition { +class ShaderDefinition +{ public: - ShaderDefinition(ShaderTemplate *shaderTemplate, const ShaderArguments &args, const char *filename) - : shaderTemplate(shaderTemplate), args(args), filename(filename) - { - } - - ShaderTemplate *shaderTemplate; - ShaderArguments args; - const char *filename; +ShaderDefinition( ShaderTemplate* shaderTemplate, const ShaderArguments& args, const char* filename ) + : shaderTemplate( shaderTemplate ), args( args ), filename( filename ){ +} + +ShaderTemplate* shaderTemplate; +ShaderArguments args; +const char* filename; }; typedef std::map ShaderDefinitionMap; ShaderDefinitionMap g_shaderDefinitions; -bool parseTemplateInstance(Tokeniser &tokeniser, const char *filename) -{ - CopiedString name; - RETURN_FALSE_IF_FAIL(Tokeniser_parseShaderName(tokeniser, name)); - const char *templateName = tokeniser.getToken(); - ShaderTemplate *shaderTemplate = findTemplate(templateName); - if (shaderTemplate == 0) { - globalErrorStream() << "shader instance: " << makeQuoted(name.c_str()) << ": shader template not found: " - << makeQuoted(templateName) << "\n"; - } - - ShaderArguments args; - if (!parseShaderParameters(tokeniser, args)) { - globalErrorStream() << "shader instance: " << makeQuoted(name.c_str()) << ": argument parse failed\n"; - return false; - } - - if (shaderTemplate != 0) { - if (!g_shaderDefinitions.insert( - ShaderDefinitionMap::value_type(name, ShaderDefinition(shaderTemplate, args, filename))).second) { - globalErrorStream() << "shader instance: " << makeQuoted(name.c_str()) - << ": already exists, second definition ignored\n"; - } - } - return true; -} - - -const char *evaluateShaderValue(const char *value, const ShaderParameters ¶ms, const ShaderArguments &args) -{ - ShaderArguments::const_iterator j = args.begin(); - for (ShaderParameters::const_iterator i = params.begin(); i != params.end(); ++i, ++j) { - const char *other = (*i).c_str(); - if (string_equal(value, other)) { - return (*j).c_str(); - } - } - return value; +bool parseTemplateInstance( Tokeniser& tokeniser, const char* filename ){ + CopiedString name; + RETURN_FALSE_IF_FAIL( Tokeniser_parseShaderName( tokeniser, name ) ); + const char* templateName = tokeniser.getToken(); + ShaderTemplate* shaderTemplate = findTemplate( templateName ); + if ( shaderTemplate == 0 ) { + globalErrorStream() << "shader instance: " << makeQuoted( name.c_str() ) << ": shader template not found: " << makeQuoted( templateName ) << "\n"; + } + + ShaderArguments args; + if ( !parseShaderParameters( tokeniser, args ) ) { + globalErrorStream() << "shader instance: " << makeQuoted( name.c_str() ) << ": argument parse failed\n"; + return false; + } + + if ( shaderTemplate != 0 ) { + if ( !g_shaderDefinitions.insert( ShaderDefinitionMap::value_type( name, ShaderDefinition( shaderTemplate, args, filename ) ) ).second ) { + globalErrorStream() << "shader instance: " << makeQuoted( name.c_str() ) << ": already exists, second definition ignored\n"; + } + } + return true; +} + + +const char* evaluateShaderValue( const char* value, const ShaderParameters& params, const ShaderArguments& args ){ + ShaderArguments::const_iterator j = args.begin(); + for ( ShaderParameters::const_iterator i = params.begin(); i != params.end(); ++i, ++j ) + { + const char* other = ( *i ).c_str(); + if ( string_equal( value, other ) ) { + return ( *j ).c_str(); + } + } + return value; } ///\todo BlendFunc parsing -BlendFunc -evaluateBlendFunc(const BlendFuncExpression &blendFunc, const ShaderParameters ¶ms, const ShaderArguments &args) -{ - return BlendFunc(BLEND_ONE, BLEND_ZERO); +BlendFunc evaluateBlendFunc( const BlendFuncExpression& blendFunc, const ShaderParameters& params, const ShaderArguments& args ){ + return BlendFunc( BLEND_ONE, BLEND_ZERO ); } -qtexture_t * -evaluateTexture(const TextureExpression &texture, const ShaderParameters ¶ms, const ShaderArguments &args, - const LoadImageCallback &loader = GlobalTexturesCache().defaultLoader()) -{ - StringOutputStream result(64); - const char *expression = texture.c_str(); - const char *end = expression + string_length(expression); - if (!string_empty(expression)) { - for (;;) { - const char *best = end; - const char *bestParam = 0; - const char *bestArg = 0; - ShaderArguments::const_iterator j = args.begin(); - for (ShaderParameters::const_iterator i = params.begin(); i != params.end(); ++i, ++j) { - const char *found = strstr(expression, (*i).c_str()); - if (found != 0 && found < best) { - best = found; - bestParam = (*i).c_str(); - bestArg = (*j).c_str(); - } - } - if (best != end) { - result << StringRange(expression, best); - result << PathCleaned(bestArg); - expression = best + string_length(bestParam); - } else { - break; - } - } - result << expression; - } - return GlobalTexturesCache().capture(loader, result.c_str()); -} - -float evaluateFloat(const ShaderValue &value, const ShaderParameters ¶ms, const ShaderArguments &args) -{ - const char *result = evaluateShaderValue(value.c_str(), params, args); - float f; - if (!string_parse_float(result, f)) { - globalErrorStream() << "parsing float value failed: " << makeQuoted(result) << "\n"; - } - return f; +qtexture_t* evaluateTexture( const TextureExpression& texture, const ShaderParameters& params, const ShaderArguments& args, const LoadImageCallback& loader = GlobalTexturesCache().defaultLoader() ){ + StringOutputStream result( 64 ); + const char* expression = texture.c_str(); + const char* end = expression + string_length( expression ); + if ( !string_empty( expression ) ) { + for (;; ) + { + const char* best = end; + const char* bestParam = 0; + const char* bestArg = 0; + ShaderArguments::const_iterator j = args.begin(); + for ( ShaderParameters::const_iterator i = params.begin(); i != params.end(); ++i, ++j ) + { + const char* found = strstr( expression, ( *i ).c_str() ); + if ( found != 0 && found < best ) { + best = found; + bestParam = ( *i ).c_str(); + bestArg = ( *j ).c_str(); + } + } + if ( best != end ) { + result << StringRange( expression, best ); + result << PathCleaned( bestArg ); + expression = best + string_length( bestParam ); + } + else + { + break; + } + } + result << expression; + } + return GlobalTexturesCache().capture( loader, result.c_str() ); +} + +float evaluateFloat( const ShaderValue& value, const ShaderParameters& params, const ShaderArguments& args ){ + const char* result = evaluateShaderValue( value.c_str(), params, args ); + float f; + if ( !string_parse_float( result, f ) ) { + globalErrorStream() << "parsing float value failed: " << makeQuoted( result ) << "\n"; + } + return f; } -BlendFactor evaluateBlendFactor(const ShaderValue &value, const ShaderParameters ¶ms, const ShaderArguments &args) +BlendFactor evaluateBlendFactor( const ShaderValue& value, const ShaderParameters& params, const ShaderArguments& args ){ + const char* result = evaluateShaderValue( value.c_str(), params, args ); + + if ( string_equal_nocase( result, "gl_zero" ) ) { + return BLEND_ZERO; + } + if ( string_equal_nocase( result, "gl_one" ) ) { + return BLEND_ONE; + } + if ( string_equal_nocase( result, "gl_src_color" ) ) { + return BLEND_SRC_COLOUR; + } + if ( string_equal_nocase( result, "gl_one_minus_src_color" ) ) { + return BLEND_ONE_MINUS_SRC_COLOUR; + } + if ( string_equal_nocase( result, "gl_src_alpha" ) ) { + return BLEND_SRC_ALPHA; + } + if ( string_equal_nocase( result, "gl_one_minus_src_alpha" ) ) { + return BLEND_ONE_MINUS_SRC_ALPHA; + } + if ( string_equal_nocase( result, "gl_dst_color" ) ) { + return BLEND_DST_COLOUR; + } + if ( string_equal_nocase( result, "gl_one_minus_dst_color" ) ) { + return BLEND_ONE_MINUS_DST_COLOUR; + } + if ( string_equal_nocase( result, "gl_dst_alpha" ) ) { + return BLEND_DST_ALPHA; + } + if ( string_equal_nocase( result, "gl_one_minus_dst_alpha" ) ) { + return BLEND_ONE_MINUS_DST_ALPHA; + } + if ( string_equal_nocase( result, "gl_src_alpha_saturate" ) ) { + return BLEND_SRC_ALPHA_SATURATE; + } + + globalErrorStream() << "parsing blend-factor value failed: " << makeQuoted( result ) << "\n"; + return BLEND_ZERO; +} + +class CShader : public IShader { - const char *result = evaluateShaderValue(value.c_str(), params, args); - - if (string_equal_nocase(result, "gl_zero")) { - return BLEND_ZERO; - } - if (string_equal_nocase(result, "gl_one")) { - return BLEND_ONE; - } - if (string_equal_nocase(result, "gl_src_color")) { - return BLEND_SRC_COLOUR; - } - if (string_equal_nocase(result, "gl_one_minus_src_color")) { - return BLEND_ONE_MINUS_SRC_COLOUR; - } - if (string_equal_nocase(result, "gl_src_alpha")) { - return BLEND_SRC_ALPHA; - } - if (string_equal_nocase(result, "gl_one_minus_src_alpha")) { - return BLEND_ONE_MINUS_SRC_ALPHA; - } - if (string_equal_nocase(result, "gl_dst_color")) { - return BLEND_DST_COLOUR; - } - if (string_equal_nocase(result, "gl_one_minus_dst_color")) { - return BLEND_ONE_MINUS_DST_COLOUR; - } - if (string_equal_nocase(result, "gl_dst_alpha")) { - return BLEND_DST_ALPHA; - } - if (string_equal_nocase(result, "gl_one_minus_dst_alpha")) { - return BLEND_ONE_MINUS_DST_ALPHA; - } - if (string_equal_nocase(result, "gl_src_alpha_saturate")) { - return BLEND_SRC_ALPHA_SATURATE; - } - - globalErrorStream() << "parsing blend-factor value failed: " << makeQuoted(result) << "\n"; - return BLEND_ZERO; -} - -class CShader : public IShader { - std::size_t m_refcount; - - const ShaderTemplate &m_template; - const ShaderArguments &m_args; - const char *m_filename; -// name is shader-name, otherwise texture-name (if not a real shader) - CopiedString m_Name; - - qtexture_t *m_pTexture; - qtexture_t *m_notfound; - qtexture_t *m_pDiffuse; - float m_heightmapScale; - qtexture_t *m_pBump; - qtexture_t *m_pSpecular; - qtexture_t *m_pLightFalloffImage; - BlendFunc m_blendFunc; - - bool m_bInUse; +std::size_t m_refcount; +const ShaderTemplate& m_template; +const ShaderArguments& m_args; +const char* m_filename; +// name is shader-name, otherwise texture-name ( if not a real shader ) +CopiedString m_Name; -public: - static bool m_lightingEnabled; +qtexture_t* m_pTexture; +qtexture_t* m_notfound; +qtexture_t* m_pDiffuse; +float m_heightmapScale; +qtexture_t* m_pBump; +qtexture_t* m_pSpecular; +qtexture_t* m_pLightFalloffImage; +BlendFunc m_blendFunc; - CShader(const ShaderDefinition &definition) : - m_refcount(0), - m_template(*definition.shaderTemplate), - m_args(definition.args), - m_filename(definition.filename), - m_blendFunc(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA), - m_bInUse(false) - { - m_pTexture = 0; - m_pDiffuse = 0; - m_pBump = 0; - m_pSpecular = 0; +bool m_bInUse; - m_notfound = 0; - realise(); - } +public: +static bool m_lightingEnabled; + +CShader( const ShaderDefinition& definition ) : + m_refcount( 0 ), + m_template( *definition.shaderTemplate ), + m_args( definition.args ), + m_filename( definition.filename ), + m_blendFunc( BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA ), + m_bInUse( false ){ + m_pTexture = 0; + m_pDiffuse = 0; + m_pBump = 0; + m_pSpecular = 0; + + m_notfound = 0; + + realise(); +} - virtual ~CShader() - { - unrealise(); +virtual ~CShader(){ + unrealise(); - ASSERT_MESSAGE(m_refcount == 0, "deleting active shader"); - } + ASSERT_MESSAGE( m_refcount == 0, "deleting active shader" ); +} // IShaders implementation ----------------- - void IncRef() - { - ++m_refcount; - } - - void DecRef() - { - ASSERT_MESSAGE(m_refcount != 0, "shader reference-count going below zero"); - if (--m_refcount == 0) { - delete this; - } - } - - std::size_t refcount() - { - return m_refcount; - } +void IncRef(){ + ++m_refcount; +} + +void DecRef(){ + ASSERT_MESSAGE( m_refcount != 0, "shader reference-count going below zero" ); + if ( --m_refcount == 0 ) { + delete this; + } +} + +std::size_t refcount(){ + return m_refcount; +} // get/set the qtexture_t* Radiant uses to represent this shader object - qtexture_t *getTexture() const - { - return m_pTexture; - } - - qtexture_t *getDiffuse() const - { - return m_pDiffuse; - } - - qtexture_t *getBump() const - { - return m_pBump; - } - - qtexture_t *getSpecular() const - { - return m_pSpecular; - } +qtexture_t* getTexture() const { + return m_pTexture; +} + +qtexture_t* getDiffuse() const { + return m_pDiffuse; +} + +qtexture_t* getBump() const { + return m_pBump; +} + +qtexture_t* getSpecular() const { + return m_pSpecular; +} // get shader name - const char *getName() const - { - return m_Name.c_str(); - } - - bool IsInUse() const - { - return m_bInUse; - } - - void SetInUse(bool bInUse) - { - m_bInUse = bInUse; - g_ActiveShadersChangedNotify(); - } +const char* getName() const { + return m_Name.c_str(); +} + +bool IsInUse() const { + return m_bInUse; +} + +void SetInUse( bool bInUse ){ + m_bInUse = bInUse; + g_ActiveShadersChangedNotify(); +} // get the shader flags - int getFlags() const - { - return m_template.m_nFlags; - } +int getFlags() const { + return m_template.m_nFlags; +} // get the transparency value - float getTrans() const - { - return m_template.m_fTrans; - } +float getTrans() const { + return m_template.m_fTrans; +} // test if it's a true shader, or a default shader created to wrap around a texture - bool IsDefault() const - { - return string_empty(m_filename); - } +bool IsDefault() const { + return string_empty( m_filename ); +} // get the alphaFunc - void getAlphaFunc(EAlphaFunc *func, float *ref) - { - *func = m_template.m_AlphaFunc; - *ref = m_template.m_AlphaRef; - }; - - BlendFunc getBlendFunc() const - { - return m_blendFunc; - } +void getAlphaFunc( EAlphaFunc *func, float *ref ) { *func = m_template.m_AlphaFunc; *ref = m_template.m_AlphaRef; }; +BlendFunc getBlendFunc() const { + return m_blendFunc; +} // get the cull type - ECull getCull() - { - return m_template.m_Cull; - }; - -// get shader file name (ie the file where this one is defined) - const char *getShaderFileName() const - { - return m_filename; - } +ECull getCull(){ + return m_template.m_Cull; +}; + +// get shader file name ( ie the file where this one is defined ) +const char* getShaderFileName() const { + return m_filename; +} // ----------------------------------------- - void realise() - { - m_pTexture = evaluateTexture(m_template.m_textureName, m_template.m_params, m_args); - - if (m_pTexture->texture_number == 0) { - m_notfound = m_pTexture; - - { - m_pTexture = GlobalTexturesCache().capture(IsDefault() ? DEFAULT_NOTEX_NAME : DEFAULT_SHADERNOTEX_NAME); - } - } - - realiseLighting(); - } - - void unrealise() - { - GlobalTexturesCache().release(m_pTexture); - - if (m_notfound != 0) { - GlobalTexturesCache().release(m_notfound); - } - - unrealiseLighting(); - } - - void realiseLighting() - { - if (m_lightingEnabled) { - LoadImageCallback loader = GlobalTexturesCache().defaultLoader(); - if (!string_empty(m_template.m_heightmapScale.c_str())) { - m_heightmapScale = evaluateFloat(m_template.m_heightmapScale, m_template.m_params, m_args); - loader = LoadImageCallback(&m_heightmapScale, loadHeightmap); - } - m_pDiffuse = evaluateTexture(m_template.m_diffuse, m_template.m_params, m_args); - m_pBump = evaluateTexture(m_template.m_bump, m_template.m_params, m_args, loader); - m_pSpecular = evaluateTexture(m_template.m_specular, m_template.m_params, m_args); - m_pLightFalloffImage = evaluateTexture(m_template.m_lightFalloffImage, m_template.m_params, m_args); - - for (ShaderTemplate::MapLayers::const_iterator i = m_template.m_layers.begin(); - i != m_template.m_layers.end(); ++i) { - m_layers.push_back(evaluateLayer(*i, m_template.m_params, m_args)); - } - - if (m_layers.size() == 1) { - const BlendFuncExpression &blendFunc = m_template.m_layers.front().blendFunc(); - if (!string_empty(blendFunc.second.c_str())) { - m_blendFunc = BlendFunc( - evaluateBlendFactor(blendFunc.first.c_str(), m_template.m_params, m_args), - evaluateBlendFactor(blendFunc.second.c_str(), m_template.m_params, m_args) - ); - } else { - const char *blend = evaluateShaderValue(blendFunc.first.c_str(), m_template.m_params, m_args); - - if (string_equal_nocase(blend, "add")) { - m_blendFunc = BlendFunc(BLEND_ONE, BLEND_ONE); - } else if (string_equal_nocase(blend, "filter")) { - m_blendFunc = BlendFunc(BLEND_DST_COLOUR, BLEND_ZERO); - } else if (string_equal_nocase(blend, "blend")) { - m_blendFunc = BlendFunc(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); - } else { - globalErrorStream() << "parsing blend value failed: " << makeQuoted(blend) << "\n"; - } - } - } - } - } - - void unrealiseLighting() - { - if (m_lightingEnabled) { - GlobalTexturesCache().release(m_pDiffuse); - GlobalTexturesCache().release(m_pBump); - GlobalTexturesCache().release(m_pSpecular); - - GlobalTexturesCache().release(m_pLightFalloffImage); - - for (MapLayers::iterator i = m_layers.begin(); i != m_layers.end(); ++i) { - GlobalTexturesCache().release((*i).texture()); - } - m_layers.clear(); - - m_blendFunc = BlendFunc(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); - } - } +void realise(){ + m_pTexture = evaluateTexture( m_template.m_textureName, m_template.m_params, m_args ); + + if ( m_pTexture->texture_number == 0 ) { + m_notfound = m_pTexture; + + { + m_pTexture = GlobalTexturesCache().capture( IsDefault() ? DEFAULT_NOTEX_NAME : DEFAULT_SHADERNOTEX_NAME ); + } + } + + realiseLighting(); +} + +void unrealise(){ + GlobalTexturesCache().release( m_pTexture ); + + if ( m_notfound != 0 ) { + GlobalTexturesCache().release( m_notfound ); + } + + unrealiseLighting(); +} + +void realiseLighting(){ + if ( m_lightingEnabled ) { + LoadImageCallback loader = GlobalTexturesCache().defaultLoader(); + if ( !string_empty( m_template.m_heightmapScale.c_str() ) ) { + m_heightmapScale = evaluateFloat( m_template.m_heightmapScale, m_template.m_params, m_args ); + loader = LoadImageCallback( &m_heightmapScale, loadHeightmap ); + } + m_pDiffuse = evaluateTexture( m_template.m_diffuse, m_template.m_params, m_args ); + m_pBump = evaluateTexture( m_template.m_bump, m_template.m_params, m_args, loader ); + m_pSpecular = evaluateTexture( m_template.m_specular, m_template.m_params, m_args ); + m_pLightFalloffImage = evaluateTexture( m_template.m_lightFalloffImage, m_template.m_params, m_args ); + + for ( ShaderTemplate::MapLayers::const_iterator i = m_template.m_layers.begin(); i != m_template.m_layers.end(); ++i ) + { + m_layers.push_back( evaluateLayer( *i, m_template.m_params, m_args ) ); + } + + if ( m_layers.size() == 1 ) { + const BlendFuncExpression& blendFunc = m_template.m_layers.front().blendFunc(); + if ( !string_empty( blendFunc.second.c_str() ) ) { + m_blendFunc = BlendFunc( + evaluateBlendFactor( blendFunc.first.c_str(), m_template.m_params, m_args ), + evaluateBlendFactor( blendFunc.second.c_str(), m_template.m_params, m_args ) + ); + } + else + { + const char* blend = evaluateShaderValue( blendFunc.first.c_str(), m_template.m_params, m_args ); + + if ( string_equal_nocase( blend, "add" ) ) { + m_blendFunc = BlendFunc( BLEND_ONE, BLEND_ONE ); + } + else if ( string_equal_nocase( blend, "filter" ) ) { + m_blendFunc = BlendFunc( BLEND_DST_COLOUR, BLEND_ZERO ); + } + else if ( string_equal_nocase( blend, "blend" ) ) { + m_blendFunc = BlendFunc( BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA ); + } + else + { + globalErrorStream() << "parsing blend value failed: " << makeQuoted( blend ) << "\n"; + } + } + } + } +} + +void unrealiseLighting(){ + if ( m_lightingEnabled ) { + GlobalTexturesCache().release( m_pDiffuse ); + GlobalTexturesCache().release( m_pBump ); + GlobalTexturesCache().release( m_pSpecular ); + + GlobalTexturesCache().release( m_pLightFalloffImage ); + + for ( MapLayers::iterator i = m_layers.begin(); i != m_layers.end(); ++i ) + { + GlobalTexturesCache().release( ( *i ).texture() ); + } + m_layers.clear(); + + m_blendFunc = BlendFunc( BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA ); + } +} // set shader name - void setName(const char *name) - { - m_Name = name; - } - - class MapLayer : public ShaderLayer { - qtexture_t *m_texture; - BlendFunc m_blendFunc; - bool m_clampToBorder; - float m_alphaTest; - public: - MapLayer(qtexture_t *texture, BlendFunc blendFunc, bool clampToBorder, float alphaTest) : - m_texture(texture), - m_blendFunc(blendFunc), - m_clampToBorder(false), - m_alphaTest(alphaTest) - { - } - - qtexture_t *texture() const - { - return m_texture; - } - - BlendFunc blendFunc() const - { - return m_blendFunc; - } - - bool clampToBorder() const - { - return m_clampToBorder; - } - - float alphaTest() const - { - return m_alphaTest; - } - }; - - static MapLayer evaluateLayer(const ShaderTemplate::MapLayerTemplate &layerTemplate, const ShaderParameters ¶ms, - const ShaderArguments &args) - { - return MapLayer( - evaluateTexture(layerTemplate.texture(), params, args), - evaluateBlendFunc(layerTemplate.blendFunc(), params, args), - layerTemplate.clampToBorder(), - evaluateFloat(layerTemplate.alphaTest(), params, args) - ); - } - - typedef std::vector MapLayers; - MapLayers m_layers; - - const ShaderLayer *firstLayer() const - { - if (m_layers.empty()) { - return 0; - } - return &m_layers.front(); - } - - void forEachLayer(const ShaderLayerCallback &callback) const - { - for (MapLayers::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) { - callback(*i); - } - } - - qtexture_t *lightFalloffImage() const - { - if (!string_empty(m_template.m_lightFalloffImage.c_str())) { - return m_pLightFalloffImage; - } - return 0; - } +void setName( const char* name ){ + m_Name = name; +} + +class MapLayer : public ShaderLayer +{ +qtexture_t* m_texture; +BlendFunc m_blendFunc; +bool m_clampToBorder; +float m_alphaTest; +public: +MapLayer( qtexture_t* texture, BlendFunc blendFunc, bool clampToBorder, float alphaTest ) : + m_texture( texture ), + m_blendFunc( blendFunc ), + m_clampToBorder( false ), + m_alphaTest( alphaTest ){ +} + +qtexture_t* texture() const { + return m_texture; +} + +BlendFunc blendFunc() const { + return m_blendFunc; +} + +bool clampToBorder() const { + return m_clampToBorder; +} + +float alphaTest() const { + return m_alphaTest; +} +}; + +static MapLayer evaluateLayer( const ShaderTemplate::MapLayerTemplate& layerTemplate, const ShaderParameters& params, const ShaderArguments& args ){ + return MapLayer( + evaluateTexture( layerTemplate.texture(), params, args ), + evaluateBlendFunc( layerTemplate.blendFunc(), params, args ), + layerTemplate.clampToBorder(), + evaluateFloat( layerTemplate.alphaTest(), params, args ) + ); +} + +typedef std::vector MapLayers; +MapLayers m_layers; + +const ShaderLayer* firstLayer() const { + if ( m_layers.empty() ) { + return 0; + } + return &m_layers.front(); +} +void forEachLayer( const ShaderLayerCallback& callback ) const { + for ( MapLayers::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i ) + { + callback( *i ); + } +} + +qtexture_t* lightFalloffImage() const { + if ( !string_empty( m_template.m_lightFalloffImage.c_str() ) ) { + return m_pLightFalloffImage; + } + return 0; +} }; bool CShader::m_lightingEnabled = false; @@ -1148,378 +1129,396 @@ shaders_t g_ActiveShaders; static shaders_t::iterator g_ActiveShadersIterator; -void ActiveShaders_IteratorBegin() -{ - g_ActiveShadersIterator = g_ActiveShaders.begin(); +void ActiveShaders_IteratorBegin(){ + g_ActiveShadersIterator = g_ActiveShaders.begin(); } -bool ActiveShaders_IteratorAtEnd() -{ - return g_ActiveShadersIterator == g_ActiveShaders.end(); +bool ActiveShaders_IteratorAtEnd(){ + return g_ActiveShadersIterator == g_ActiveShaders.end(); } -IShader *ActiveShaders_IteratorCurrent() -{ - return static_cast( g_ActiveShadersIterator->second ); +IShader *ActiveShaders_IteratorCurrent(){ + return static_cast( g_ActiveShadersIterator->second ); } -void ActiveShaders_IteratorIncrement() -{ - ++g_ActiveShadersIterator; +void ActiveShaders_IteratorIncrement(){ + ++g_ActiveShadersIterator; } -void debug_check_shaders(shaders_t &shaders) -{ - for (shaders_t::iterator i = shaders.begin(); i != shaders.end(); ++i) { - ASSERT_MESSAGE(i->second->refcount() == 1, "orphan shader still referenced"); - } +void debug_check_shaders( shaders_t& shaders ){ + for ( shaders_t::iterator i = shaders.begin(); i != shaders.end(); ++i ) + { + ASSERT_MESSAGE( i->second->refcount() == 1, "orphan shader still referenced" ); + } } // will free all GL binded qtextures and shaders // NOTE: doesn't make much sense out of Radiant exit or called during a reload -void FreeShaders() -{ - // reload shaders - // empty the actives shaders list - debug_check_shaders(g_ActiveShaders); - g_ActiveShaders.clear(); - g_shaders.clear(); - g_shaderTemplates.clear(); - g_shaderDefinitions.clear(); - g_ActiveShadersChangedNotify(); +void FreeShaders(){ + // reload shaders + // empty the actives shaders list + debug_check_shaders( g_ActiveShaders ); + g_ActiveShaders.clear(); + g_shaders.clear(); + g_shaderTemplates.clear(); + g_shaderDefinitions.clear(); + g_ActiveShadersChangedNotify(); +} + +bool ShaderTemplate::parseQuake3( Tokeniser& tokeniser ){ + // name of the qtexture_t we'll use to represent this shader ( this one has the "textures\" before ) + m_textureName = m_Name.c_str(); + + tokeniser.nextLine(); + + // we need to read until we hit a balanced } + int depth = 0; + for (;; ) + { + tokeniser.nextLine(); + const char* token = tokeniser.getToken(); + + if ( token == 0 ) { + return false; + } + + if ( string_equal( token, "{" ) ) { + ++depth; + continue; + } + else if ( string_equal( token, "}" ) ) { + --depth; + if ( depth < 0 ) { // underflow + return false; + } + if ( depth == 0 ) { // end of shader + break; + } + + continue; + } + + if ( depth == 1 ) { + if ( string_equal_nocase( token, "qer_nocarve" ) ) { + m_nFlags |= QER_NOCARVE; + } + else if ( string_equal_nocase( token, "qer_trans" ) ) { + RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, m_fTrans ) ); + m_nFlags |= QER_TRANS; + } + else if ( string_equal_nocase( token, "qer_editorimage" ) ) { + RETURN_FALSE_IF_FAIL( Tokeniser_parseTextureName( tokeniser, m_textureName ) ); + } + else if ( string_equal_nocase( token, "qer_alphafunc" ) ) { + const char* alphafunc = tokeniser.getToken(); + + if ( alphafunc == 0 ) { + Tokeniser_unexpectedError( tokeniser, alphafunc, "#alphafunc" ); + return false; + } + + if ( string_equal_nocase( alphafunc, "equal" ) ) { + m_AlphaFunc = IShader::eEqual; + } + else if ( string_equal_nocase( alphafunc, "greater" ) ) { + m_AlphaFunc = IShader::eGreater; + } + else if ( string_equal_nocase( alphafunc, "less" ) ) { + m_AlphaFunc = IShader::eLess; + } + else if ( string_equal_nocase( alphafunc, "gequal" ) ) { + m_AlphaFunc = IShader::eGEqual; + } + else if ( string_equal_nocase( alphafunc, "lequal" ) ) { + m_AlphaFunc = IShader::eLEqual; + } + else + { + m_AlphaFunc = IShader::eAlways; + } + + m_nFlags |= QER_ALPHATEST; + + RETURN_FALSE_IF_FAIL( Tokeniser_getFloat( tokeniser, m_AlphaRef ) ); + } + else if ( string_equal_nocase( token, "cull" ) ) { + const char* cull = tokeniser.getToken(); + + if ( cull == 0 ) { + Tokeniser_unexpectedError( tokeniser, cull, "#cull" ); + return false; + } + + if ( string_equal_nocase( cull, "none" ) + || string_equal_nocase( cull, "twosided" ) + || string_equal_nocase( cull, "disable" ) ) { + m_Cull = IShader::eCullNone; + } + else if ( string_equal_nocase( cull, "back" ) + || string_equal_nocase( cull, "backside" ) + || string_equal_nocase( cull, "backsided" ) ) { + m_Cull = IShader::eCullBack; + } + else + { + m_Cull = IShader::eCullBack; + } + + m_nFlags |= QER_CULL; + } + else if ( string_equal_nocase( token, "surfaceparm" ) ) { + const char* surfaceparm = tokeniser.getToken(); + + if ( surfaceparm == 0 ) { + Tokeniser_unexpectedError( tokeniser, surfaceparm, "#surfaceparm" ); + return false; + } + + if ( string_equal_nocase( surfaceparm, "fog" ) ) { + m_nFlags |= QER_FOG; + if ( m_fTrans == 1.0f ) { // has not been explicitly set by qer_trans + m_fTrans = 0.35f; + } + } + else if ( string_equal_nocase( surfaceparm, "nodraw" ) ) { + m_nFlags |= QER_NODRAW; + } + else if ( string_equal_nocase( surfaceparm, "nonsolid" ) ) { + m_nFlags |= QER_NONSOLID; + } + else if ( string_equal_nocase( surfaceparm, "water" ) ) { + m_nFlags |= QER_WATER; + } + else if ( string_equal_nocase( surfaceparm, "lava" ) ) { + m_nFlags |= QER_LAVA; + } + else if ( string_equal_nocase( surfaceparm, "areaportal" ) ) { + m_nFlags |= QER_AREAPORTAL; + } + else if ( string_equal_nocase( surfaceparm, "playerclip" ) ) { + m_nFlags |= QER_CLIP; + } + else if ( string_equal_nocase( surfaceparm, "botclip" ) ) { + m_nFlags |= QER_BOTCLIP; + } + } + } + } + + return true; } -bool ShaderTemplate::parseQuake3(Tokeniser &tokeniser) +class Layer { - // name of the qtexture_t we'll use to represent this shader (this one has the "textures\" before) - m_textureName = m_Name.c_str(); - - tokeniser.nextLine(); - - // we need to read until we hit a balanced } - int depth = 0; - for (;;) { - tokeniser.nextLine(); - const char *token = tokeniser.getToken(); - - if (token == 0) { - return false; - } - - if (string_equal(token, "{")) { - ++depth; - continue; - } else if (string_equal(token, "}")) { - --depth; - if (depth < 0) { // underflow - return false; - } - if (depth == 0) { // end of shader - break; - } - - continue; - } - - if (depth == 1) { - if (string_equal_nocase(token, "qer_nocarve")) { - m_nFlags |= QER_NOCARVE; - } else if (string_equal_nocase(token, "qer_trans")) { - RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, m_fTrans)); - m_nFlags |= QER_TRANS; - } else if (string_equal_nocase(token, "qer_editorimage")) { - RETURN_FALSE_IF_FAIL(Tokeniser_parseTextureName(tokeniser, m_textureName)); - } else if (string_equal_nocase(token, "qer_alphafunc")) { - const char *alphafunc = tokeniser.getToken(); - - if (alphafunc == 0) { - Tokeniser_unexpectedError(tokeniser, alphafunc, "#alphafunc"); - return false; - } - - if (string_equal_nocase(alphafunc, "equal")) { - m_AlphaFunc = IShader::eEqual; - } else if (string_equal_nocase(alphafunc, "greater")) { - m_AlphaFunc = IShader::eGreater; - } else if (string_equal_nocase(alphafunc, "less")) { - m_AlphaFunc = IShader::eLess; - } else if (string_equal_nocase(alphafunc, "gequal")) { - m_AlphaFunc = IShader::eGEqual; - } else if (string_equal_nocase(alphafunc, "lequal")) { - m_AlphaFunc = IShader::eLEqual; - } else { - m_AlphaFunc = IShader::eAlways; - } - - m_nFlags |= QER_ALPHATEST; - - RETURN_FALSE_IF_FAIL(Tokeniser_getFloat(tokeniser, m_AlphaRef)); - } else if (string_equal_nocase(token, "cull")) { - const char *cull = tokeniser.getToken(); - - if (cull == 0) { - Tokeniser_unexpectedError(tokeniser, cull, "#cull"); - return false; - } - - if (string_equal_nocase(cull, "none") - || string_equal_nocase(cull, "twosided") - || string_equal_nocase(cull, "disable")) { - m_Cull = IShader::eCullNone; - } else if (string_equal_nocase(cull, "back") - || string_equal_nocase(cull, "backside") - || string_equal_nocase(cull, "backsided")) { - m_Cull = IShader::eCullBack; - } else { - m_Cull = IShader::eCullBack; - } - - m_nFlags |= QER_CULL; - } else if (string_equal_nocase(token, "surfaceparm")) { - const char *surfaceparm = tokeniser.getToken(); - - if (surfaceparm == 0) { - Tokeniser_unexpectedError(tokeniser, surfaceparm, "#surfaceparm"); - return false; - } - - if (string_equal_nocase(surfaceparm, "fog")) { - m_nFlags |= QER_FOG; - if (m_fTrans == 1.0f) { // has not been explicitly set by qer_trans - m_fTrans = 0.35f; - } - } else if (string_equal_nocase(surfaceparm, "nodraw")) { - m_nFlags |= QER_NODRAW; - } else if (string_equal_nocase(surfaceparm, "nonsolid")) { - m_nFlags |= QER_NONSOLID; - } else if (string_equal_nocase(surfaceparm, "water")) { - m_nFlags |= QER_WATER; - } else if (string_equal_nocase(surfaceparm, "lava")) { - m_nFlags |= QER_LAVA; - } else if (string_equal_nocase(surfaceparm, "areaportal")) { - m_nFlags |= QER_AREAPORTAL; - } else if (string_equal_nocase(surfaceparm, "playerclip")) { - m_nFlags |= QER_CLIP; - } else if (string_equal_nocase(surfaceparm, "botclip")) { - m_nFlags |= QER_BOTCLIP; - } - } - } - } - - return true; -} - -class Layer { public: - LayerTypeId m_type; - TextureExpression m_texture; - BlendFunc m_blendFunc; - bool m_clampToBorder; - float m_alphaTest; - float m_heightmapScale; - - Layer() : m_type(LAYER_NONE), m_blendFunc(BLEND_ONE, BLEND_ZERO), m_clampToBorder(false), m_alphaTest(-1), - m_heightmapScale(0) - { - } +LayerTypeId m_type; +TextureExpression m_texture; +BlendFunc m_blendFunc; +bool m_clampToBorder; +float m_alphaTest; +float m_heightmapScale; + +Layer() : m_type( LAYER_NONE ), m_blendFunc( BLEND_ONE, BLEND_ZERO ), m_clampToBorder( false ), m_alphaTest( -1 ), m_heightmapScale( 0 ){ +} }; std::list g_shaderFilenames; -void ParseShaderFile(Tokeniser &tokeniser, const char *filename) -{ - g_shaderFilenames.push_back(filename); - filename = g_shaderFilenames.back().c_str(); - tokeniser.nextLine(); - for (;;) { - const char *token = tokeniser.getToken(); - - if (token == 0) { - break; - } - - if (string_equal(token, "table")) { - if (tokeniser.getToken() == 0) { - Tokeniser_unexpectedError(tokeniser, 0, "#table-name"); - return; - } - if (!Tokeniser_parseToken(tokeniser, "{")) { - return; - } - for (;;) { - const char *option = tokeniser.getToken(); - if (string_equal(option, "{")) { - for (;;) { - const char *value = tokeniser.getToken(); - if (string_equal(value, "}")) { - break; - } - } - - if (!Tokeniser_parseToken(tokeniser, "}")) { - return; - } - break; - } - } - } else { - if (string_equal(token, "guide")) { - parseTemplateInstance(tokeniser, filename); - } else { - if (!string_equal(token, "material") - && !string_equal(token, "particle") - && !string_equal(token, "skin")) { - tokeniser.ungetToken(); - } - // first token should be the path + name.. (from base) - CopiedString name; - if (!Tokeniser_parseShaderName(tokeniser, name)) { - } - ShaderTemplatePointer shaderTemplate(new ShaderTemplate()); - shaderTemplate->setName(name.c_str()); - - g_shaders.insert(ShaderTemplateMap::value_type(shaderTemplate->getName(), shaderTemplate)); - - bool result = (g_shaderLanguage == SHADERLANGUAGE_QUAKE3) - ? shaderTemplate->parseQuake3(tokeniser) - : shaderTemplate->parseDoom3(tokeniser); - if (result) { - // do we already have this shader? - if (!g_shaderDefinitions.insert(ShaderDefinitionMap::value_type(shaderTemplate->getName(), - ShaderDefinition( - shaderTemplate.get(), - ShaderArguments(), - filename))).second) { +void ParseShaderFile( Tokeniser& tokeniser, const char* filename ){ + g_shaderFilenames.push_back( filename ); + filename = g_shaderFilenames.back().c_str(); + tokeniser.nextLine(); + for (;; ) + { + const char* token = tokeniser.getToken(); + + if ( token == 0 ) { + break; + } + + if ( string_equal( token, "table" ) ) { + if ( tokeniser.getToken() == 0 ) { + Tokeniser_unexpectedError( tokeniser, 0, "#table-name" ); + return; + } + if ( !Tokeniser_parseToken( tokeniser, "{" ) ) { + return; + } + for (;; ) + { + const char* option = tokeniser.getToken(); + if ( string_equal( option, "{" ) ) { + for (;; ) + { + const char* value = tokeniser.getToken(); + if ( string_equal( value, "}" ) ) { + break; + } + } + + if ( !Tokeniser_parseToken( tokeniser, "}" ) ) { + return; + } + break; + } + } + } + else + { + if ( string_equal( token, "guide" ) ) { + parseTemplateInstance( tokeniser, filename ); + } + else + { + if ( !string_equal( token, "material" ) + && !string_equal( token, "particle" ) + && !string_equal( token, "skin" ) ) { + tokeniser.ungetToken(); + } + // first token should be the path + name.. ( from base ) + CopiedString name; + if ( !Tokeniser_parseShaderName( tokeniser, name ) ) { + } + ShaderTemplatePointer shaderTemplate( new ShaderTemplate() ); + shaderTemplate->setName( name.c_str() ); + + g_shaders.insert( ShaderTemplateMap::value_type( shaderTemplate->getName(), shaderTemplate ) ); + + bool result = ( g_shaderLanguage == SHADERLANGUAGE_QUAKE3 ) + ? shaderTemplate->parseQuake3( tokeniser ) + : shaderTemplate->parseDoom3( tokeniser ); + if ( result ) { + // do we already have this shader? + if ( !g_shaderDefinitions.insert( ShaderDefinitionMap::value_type( shaderTemplate->getName(), ShaderDefinition( shaderTemplate.get(), ShaderArguments(), filename ) ) ).second ) { #if GDEF_DEBUG - globalOutputStream() << "WARNING: shader " << shaderTemplate->getName() - << " is already in memory, definition in " << filename << " ignored.\n"; + globalOutputStream() << "WARNING: shader " << shaderTemplate->getName() << " is already in memory, definition in " << filename << " ignored.\n"; #endif - } - } else { - globalErrorStream() << "Error parsing shader " << shaderTemplate->getName() << "\n"; - return; - } - } - } - } + } + } + else + { + globalErrorStream() << "Error parsing shader " << shaderTemplate->getName() << "\n"; + return; + } + } + } + } } -void parseGuideFile(Tokeniser &tokeniser, const char *filename) -{ - tokeniser.nextLine(); - for (;;) { - const char *token = tokeniser.getToken(); - - if (token == 0) { - break; - } - - if (string_equal(token, "guide")) { - // first token should be the path + name.. (from base) - ShaderTemplatePointer shaderTemplate(new ShaderTemplate); - shaderTemplate->parseTemplate(tokeniser); - if (!g_shaderTemplates.insert( - ShaderTemplateMap::value_type(shaderTemplate->getName(), shaderTemplate)).second) { - globalErrorStream() << "guide " << makeQuoted(shaderTemplate->getName()) - << ": already defined, second definition ignored\n"; - } - } else if (string_equal(token, "inlineGuide")) { - // skip entire inlineGuide definition - std::size_t depth = 0; - for (;;) { - tokeniser.nextLine(); - token = tokeniser.getToken(); - if (string_equal(token, "{")) { - ++depth; - } else if (string_equal(token, "}")) { - if (--depth == 0) { - break; - } - } - } - } - } -} - -void LoadShaderFile(const char *filename) -{ - ArchiveTextFile *file = GlobalFileSystem().openTextFile(filename); +void parseGuideFile( Tokeniser& tokeniser, const char* filename ){ + tokeniser.nextLine(); + for (;; ) + { + const char* token = tokeniser.getToken(); + + if ( token == 0 ) { + break; + } + + if ( string_equal( token, "guide" ) ) { + // first token should be the path + name.. ( from base ) + ShaderTemplatePointer shaderTemplate( new ShaderTemplate ); + shaderTemplate->parseTemplate( tokeniser ); + if ( !g_shaderTemplates.insert( ShaderTemplateMap::value_type( shaderTemplate->getName(), shaderTemplate ) ).second ) { + globalErrorStream() << "guide " << makeQuoted( shaderTemplate->getName() ) << ": already defined, second definition ignored\n"; + } + } + else if ( string_equal( token, "inlineGuide" ) ) { + // skip entire inlineGuide definition + std::size_t depth = 0; + for (;; ) + { + tokeniser.nextLine(); + token = tokeniser.getToken(); + if ( string_equal( token, "{" ) ) { + ++depth; + } + else if ( string_equal( token, "}" ) ) { + if ( --depth == 0 ) { + break; + } + } + } + } + } +} - if (file != 0) { - globalOutputStream() << "Parsing shaderfile " << filename << "\n"; +void LoadShaderFile( const char* filename ){ + ArchiveTextFile* file = GlobalFileSystem().openTextFile( filename ); - Tokeniser &tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser(file->getInputStream()); + if ( file != 0 ) { + globalOutputStream() << "Parsing shaderfile " << filename << "\n"; - ParseShaderFile(tokeniser, filename); + Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser( file->getInputStream() ); - tokeniser.release(); - file->release(); - } else { - globalOutputStream() << "Unable to read shaderfile " << filename << "\n"; - } + ParseShaderFile( tokeniser, filename ); + + tokeniser.release(); + file->release(); + } + else + { + globalOutputStream() << "Unable to read shaderfile " << filename << "\n"; + } } -void loadGuideFile(const char *filename) -{ - StringOutputStream fullname(256); - fullname << "guides/" << filename; - ArchiveTextFile *file = GlobalFileSystem().openTextFile(fullname.c_str()); +void loadGuideFile( const char* filename ){ + StringOutputStream fullname( 256 ); + fullname << "guides/" << filename; + ArchiveTextFile* file = GlobalFileSystem().openTextFile( fullname.c_str() ); - if (file != 0) { - globalOutputStream() << "Parsing guide file " << fullname.c_str() << "\n"; + if ( file != 0 ) { + globalOutputStream() << "Parsing guide file " << fullname.c_str() << "\n"; - Tokeniser &tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser(file->getInputStream()); + Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewScriptTokeniser( file->getInputStream() ); - parseGuideFile(tokeniser, fullname.c_str()); + parseGuideFile( tokeniser, fullname.c_str() ); - tokeniser.release(); - file->release(); - } else { - globalOutputStream() << "Unable to read guide file " << fullname.c_str() << "\n"; - } + tokeniser.release(); + file->release(); + } + else + { + globalOutputStream() << "Unable to read guide file " << fullname.c_str() << "\n"; + } } -CShader *Try_Shader_ForName(const char *name) -{ - { - shaders_t::iterator i = g_ActiveShaders.find(name); - if (i != g_ActiveShaders.end()) { - return (*i).second; - } - } - // active shader was not found - - // find matching shader definition - ShaderDefinitionMap::iterator i = g_shaderDefinitions.find(name); - if (i == g_shaderDefinitions.end()) { - // shader definition was not found - - // create new shader definition from default shader template - ShaderTemplatePointer shaderTemplate(new ShaderTemplate()); - shaderTemplate->CreateDefault(name); - g_shaderTemplates.insert(ShaderTemplateMap::value_type(shaderTemplate->getName(), shaderTemplate)); - - i = g_shaderDefinitions.insert(ShaderDefinitionMap::value_type(name, ShaderDefinition(shaderTemplate.get(), - ShaderArguments(), - ""))).first; - } - - // create shader from existing definition - ShaderPointer pShader(new CShader((*i).second)); - pShader->setName(name); - g_ActiveShaders.insert(shaders_t::value_type(name, pShader)); - g_ActiveShadersChangedNotify(); - return pShader; -} - -IShader *Shader_ForName(const char *name) -{ - ASSERT_NOTNULL(name); +CShader* Try_Shader_ForName( const char* name ){ + { + shaders_t::iterator i = g_ActiveShaders.find( name ); + if ( i != g_ActiveShaders.end() ) { + return ( *i ).second; + } + } + // active shader was not found + + // find matching shader definition + ShaderDefinitionMap::iterator i = g_shaderDefinitions.find( name ); + if ( i == g_shaderDefinitions.end() ) { + // shader definition was not found + + // create new shader definition from default shader template + ShaderTemplatePointer shaderTemplate( new ShaderTemplate() ); + shaderTemplate->CreateDefault( name ); + g_shaderTemplates.insert( ShaderTemplateMap::value_type( shaderTemplate->getName(), shaderTemplate ) ); + + i = g_shaderDefinitions.insert( ShaderDefinitionMap::value_type( name, ShaderDefinition( shaderTemplate.get(), ShaderArguments(), "" ) ) ).first; + } + + // create shader from existing definition + ShaderPointer pShader( new CShader( ( *i ).second ) ); + pShader->setName( name ); + g_ActiveShaders.insert( shaders_t::value_type( name, pShader ) ); + g_ActiveShadersChangedNotify(); + return pShader; +} + +IShader *Shader_ForName( const char *name ){ + ASSERT_NOTNULL( name ); - IShader *pShader = Try_Shader_ForName(name); - pShader->IncRef(); - return pShader; + IShader *pShader = Try_Shader_ForName( name ); + pShader->IncRef(); + return pShader; } @@ -1527,9 +1526,8 @@ IShader *Shader_ForName(const char *name) // those are listed in shaderlist file GSList *l_shaderfiles = 0; -GSList *Shaders_getShaderFileList() -{ - return l_shaderfiles; +GSList* Shaders_getShaderFileList(){ + return l_shaderfiles; } /* @@ -1538,49 +1536,48 @@ GSList *Shaders_getShaderFileList() usefull function: dumps the list of .shader files that are not referenced to the console ================== */ -void IfFound_dumpUnreferencedShader(bool &bFound, const char *filename) -{ - bool listed = false; - - for (GSList *sh = l_shaderfiles; sh != 0; sh = g_slist_next(sh)) { - if (!strcmp((char *) sh->data, filename)) { - listed = true; - break; - } - } - - if (!listed) { - if (!bFound) { - bFound = true; - globalOutputStream() << "Following shader files are not referenced in any shaderlist.txt:\n"; - } - globalOutputStream() << "\t" << filename << "\n"; - } +void IfFound_dumpUnreferencedShader( bool& bFound, const char* filename ){ + bool listed = false; + + for ( GSList* sh = l_shaderfiles; sh != 0; sh = g_slist_next( sh ) ) + { + if ( !strcmp( (char*)sh->data, filename ) ) { + listed = true; + break; + } + } + + if ( !listed ) { + if ( !bFound ) { + bFound = true; + globalOutputStream() << "Following shader files are not referenced in any shaderlist.txt:\n"; + } + globalOutputStream() << "\t" << filename << "\n"; + } } -typedef ReferenceCaller IfFoundDumpUnreferencedShaderCaller; +typedef ReferenceCaller IfFoundDumpUnreferencedShaderCaller; -void DumpUnreferencedShaders() -{ - bool bFound = false; - GlobalFileSystem().forEachFile(g_shadersDirectory, g_shadersExtension, IfFoundDumpUnreferencedShaderCaller(bFound)); +void DumpUnreferencedShaders(){ + bool bFound = false; + GlobalFileSystem().forEachFile( g_shadersDirectory, g_shadersExtension, IfFoundDumpUnreferencedShaderCaller( bFound ) ); } -void ShaderList_addShaderFile(const char *dirstring) -{ - bool found = false; - - for (GSList *tmp = l_shaderfiles; tmp != 0; tmp = tmp->next) { - if (string_equal_nocase(dirstring, (char *) tmp->data)) { - found = true; - globalOutputStream() << "duplicate entry \"" << (char *) tmp->data << "\" in shaderlist.txt\n"; - break; - } - } - - if (!found) { - l_shaderfiles = g_slist_append(l_shaderfiles, strdup(dirstring)); - } +void ShaderList_addShaderFile( const char* dirstring ){ + bool found = false; + + for ( GSList* tmp = l_shaderfiles; tmp != 0; tmp = tmp->next ) + { + if ( string_equal_nocase( dirstring, (char*)tmp->data ) ) { + found = true; + globalOutputStream() << "duplicate entry \"" << (char*)tmp->data << "\" in shaderlist.txt\n"; + break; + } + } + + if ( !found ) { + l_shaderfiles = g_slist_append( l_shaderfiles, strdup( dirstring ) ); + } } /* @@ -1589,264 +1586,244 @@ void ShaderList_addShaderFile(const char *dirstring) build a CStringList of shader names ================== */ -void BuildShaderList(TextInputStream &shaderlist) -{ - Tokeniser &tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser(shaderlist); - tokeniser.nextLine(); - const char *token = tokeniser.getToken(); - StringOutputStream shaderFile(64); - while (token != 0) { - // each token should be a shader filename - shaderFile << token << "." << g_shadersExtension; - - ShaderList_addShaderFile(shaderFile.c_str()); +void BuildShaderList( TextInputStream& shaderlist ){ + Tokeniser& tokeniser = GlobalScriptLibrary().m_pfnNewSimpleTokeniser( shaderlist ); + tokeniser.nextLine(); + const char* token = tokeniser.getToken(); + StringOutputStream shaderFile( 64 ); + while ( token != 0 ) + { + // each token should be a shader filename + shaderFile << token << "." << g_shadersExtension; + + ShaderList_addShaderFile( shaderFile.c_str() ); + + tokeniser.nextLine(); + token = tokeniser.getToken(); + + shaderFile.clear(); + } + tokeniser.release(); +} - tokeniser.nextLine(); - token = tokeniser.getToken(); +void FreeShaderList(){ + while ( l_shaderfiles != 0 ) + { + free( l_shaderfiles->data ); + l_shaderfiles = g_slist_remove( l_shaderfiles, l_shaderfiles->data ); + } +} - shaderFile.clear(); - } - tokeniser.release(); +void ShaderList_addFromArchive( const char *archivename ){ + const char *shaderpath = GlobalRadiant().getGameDescriptionKeyValue( "shaderpath" ); + if ( string_empty( shaderpath ) ) { + return; + } + + StringOutputStream shaderlist( 256 ); + shaderlist << DirectoryCleaned( shaderpath ) << "shaderlist.txt"; + + Archive *archive = GlobalFileSystem().getArchive( archivename, false ); + if ( archive ) { + ArchiveTextFile *file = archive->openTextFile( shaderlist.c_str() ); + if ( file ) { + globalOutputStream() << "Found shaderlist.txt in " << archivename << "\n"; + BuildShaderList( file->getInputStream() ); + file->release(); + } + } } -void FreeShaderList() -{ - while (l_shaderfiles != 0) { - free(l_shaderfiles->data); - l_shaderfiles = g_slist_remove(l_shaderfiles, l_shaderfiles->data); - } +#include "stream/filestream.h" + +bool shaderlist_findOrInstall( const char* enginePath, const char* toolsPath, const char* shaderPath, const char* gamename ){ + StringOutputStream absShaderList( 256 ); + absShaderList << enginePath << gamename << '/' << shaderPath << "shaderlist.txt"; + if ( file_exists( absShaderList.c_str() ) ) { + return true; + } + { + StringOutputStream directory( 256 ); + directory << enginePath << gamename << '/' << shaderPath; + if ( !file_exists( directory.c_str() ) && !Q_mkdir( directory.c_str() ) ) { + return false; + } + } + { + StringOutputStream defaultShaderList( 256 ); + defaultShaderList << toolsPath << gamename << '/' << "default_shaderlist.txt"; + if ( file_exists( defaultShaderList.c_str() ) ) { + return file_copy( defaultShaderList.c_str(), absShaderList.c_str() ); + } + } + return false; } -void ShaderList_addFromArchive(const char *archivename) -{ - const char *shaderpath = GlobalRadiant().getGameDescriptionKeyValue("shaderpath"); - if (string_empty(shaderpath)) { - return; - } +void Shaders_Load(){ + if ( g_shaderLanguage == SHADERLANGUAGE_QUAKE4 ) { + GlobalFileSystem().forEachFile("guides/", "guide", makeCallbackF(loadGuideFile), 0); + } - StringOutputStream shaderlist(256); - shaderlist << DirectoryCleaned(shaderpath) << "shaderlist.txt"; + const char* shaderPath = GlobalRadiant().getGameDescriptionKeyValue( "shaderpath" ); + if ( !string_empty( shaderPath ) ) { + StringOutputStream path( 256 ); + path << DirectoryCleaned( shaderPath ); - Archive *archive = GlobalFileSystem().getArchive(archivename, false); - if (archive) { - ArchiveTextFile *file = archive->openTextFile(shaderlist.c_str()); - if (file) { - globalOutputStream() << "Found shaderlist.txt in " << archivename << "\n"; - BuildShaderList(file->getInputStream()); - file->release(); - } - } -} + if ( g_useShaderList ) { + // preload shader files that have been listed in shaderlist.txt + const char* basegame = GlobalRadiant().getRequiredGameDescriptionKeyValue( "basegame" ); + const char* gamename = GlobalRadiant().getGameName(); + const char* enginePath = GlobalRadiant().getEnginePath(); + const char* toolsPath = GlobalRadiant().getGameToolsPath(); -#include "stream/filestream.h" + bool isMod = !string_equal( basegame, gamename ); -bool -shaderlist_findOrInstall(const char *enginePath, const char *toolsPath, const char *shaderPath, const char *gamename) -{ - StringOutputStream absShaderList(256); - absShaderList << enginePath << gamename << '/' << shaderPath << "shaderlist.txt"; - if (file_exists(absShaderList.c_str())) { - return true; - } - { - StringOutputStream directory(256); - directory << enginePath << gamename << '/' << shaderPath; - if (!file_exists(directory.c_str()) && !Q_mkdir(directory.c_str())) { - return false; - } - } - { - StringOutputStream defaultShaderList(256); - defaultShaderList << toolsPath << gamename << '/' << "default_shaderlist.txt"; - if (file_exists(defaultShaderList.c_str())) { - return file_copy(defaultShaderList.c_str(), absShaderList.c_str()); - } - } - return false; -} - -void Shaders_Load() -{ - if (g_shaderLanguage == SHADERLANGUAGE_QUAKE4) { - GlobalFileSystem().forEachFile("guides/", "guide", makeCallbackF(loadGuideFile), 0); - } - - const char *shaderPath = GlobalRadiant().getGameDescriptionKeyValue("shaderpath"); - if (!string_empty(shaderPath)) { - StringOutputStream path(256); - path << DirectoryCleaned(shaderPath); - - if (g_useShaderList) { - // preload shader files that have been listed in shaderlist.txt - const char *basegame = GlobalRadiant().getRequiredGameDescriptionKeyValue("basegame"); - const char *gamename = GlobalRadiant().getGameName(); - const char *enginePath = GlobalRadiant().getEnginePath(); - const char *toolsPath = GlobalRadiant().getGameToolsPath(); - - bool isMod = !string_equal(basegame, gamename); - - if (!isMod || !shaderlist_findOrInstall(enginePath, toolsPath, path.c_str(), gamename)) { - gamename = basegame; - shaderlist_findOrInstall(enginePath, toolsPath, path.c_str(), gamename); - } - - GlobalFileSystem().forEachArchive(makeCallbackF(ShaderList_addFromArchive), false, true); - DumpUnreferencedShaders(); - } else { - GlobalFileSystem().forEachFile(path.c_str(), g_shadersExtension, makeCallbackF(ShaderList_addShaderFile), - 0); - } - - GSList *lst = l_shaderfiles; - StringOutputStream shadername(256); - while (lst) { - shadername << path.c_str() << reinterpret_cast( lst->data ); - LoadShaderFile(shadername.c_str()); - shadername.clear(); - lst = lst->next; - } - } - - //StringPool_analyse(ShaderPool::instance()); -} - -void Shaders_Free() -{ - FreeShaders(); - FreeShaderList(); - g_shaderFilenames.clear(); + if ( !isMod || !shaderlist_findOrInstall( enginePath, toolsPath, path.c_str(), gamename ) ) { + gamename = basegame; + shaderlist_findOrInstall( enginePath, toolsPath, path.c_str(), gamename ); + } + + GlobalFileSystem().forEachArchive(makeCallbackF(ShaderList_addFromArchive), false, true); + DumpUnreferencedShaders(); + } + else + { + GlobalFileSystem().forEachFile(path.c_str(), g_shadersExtension, makeCallbackF(ShaderList_addShaderFile), 0); + } + + GSList *lst = l_shaderfiles; + StringOutputStream shadername( 256 ); + while ( lst ) + { + shadername << path.c_str() << reinterpret_cast( lst->data ); + LoadShaderFile( shadername.c_str() ); + shadername.clear(); + lst = lst->next; + } + } + + //StringPool_analyse( ShaderPool::instance() ); +} + +void Shaders_Free(){ + FreeShaders(); + FreeShaderList(); + g_shaderFilenames.clear(); } ModuleObservers g_observers; std::size_t g_shaders_unrealised = 1; // wait until filesystem and is realised before loading anything -bool Shaders_realised() -{ - return g_shaders_unrealised == 0; +bool Shaders_realised(){ + return g_shaders_unrealised == 0; } -void Shaders_Realise() -{ - if (--g_shaders_unrealised == 0) { - Shaders_Load(); - g_observers.realise(); - } +void Shaders_Realise(){ + if ( --g_shaders_unrealised == 0 ) { + Shaders_Load(); + g_observers.realise(); + } } -void Shaders_Unrealise() -{ - if (++g_shaders_unrealised == 1) { - g_observers.unrealise(); - Shaders_Free(); - } +void Shaders_Unrealise(){ + if ( ++g_shaders_unrealised == 1 ) { + g_observers.unrealise(); + Shaders_Free(); + } } -void Shaders_Refresh() -{ - Shaders_Unrealise(); - Shaders_Realise(); +void Shaders_Refresh(){ + Shaders_Unrealise(); + Shaders_Realise(); } -class Quake3ShaderSystem : public ShaderSystem, public ModuleObserver { +class Quake3ShaderSystem : public ShaderSystem, public ModuleObserver +{ public: - void realise() - { - Shaders_Realise(); - } - - void unrealise() - { - Shaders_Unrealise(); - } - - void refresh() - { - Shaders_Refresh(); - } - - IShader *getShaderForName(const char *name) - { - return Shader_ForName(name); - } - - void foreachShaderName(const ShaderNameCallback &callback) - { - for (ShaderDefinitionMap::const_iterator i = g_shaderDefinitions.begin(); i != g_shaderDefinitions.end(); ++i) { - callback((*i).first.c_str()); - } - } - - void beginActiveShadersIterator() - { - ActiveShaders_IteratorBegin(); - } - - bool endActiveShadersIterator() - { - return ActiveShaders_IteratorAtEnd(); - } - - IShader *dereferenceActiveShadersIterator() - { - return ActiveShaders_IteratorCurrent(); - } - - void incrementActiveShadersIterator() - { - ActiveShaders_IteratorIncrement(); - } - - void setActiveShadersChangedNotify(const Callback ¬ify) - { - g_ActiveShadersChangedNotify = notify; - } - - void attach(ModuleObserver &observer) - { - g_observers.attach(observer); - } - - void detach(ModuleObserver &observer) - { - g_observers.detach(observer); - } - - void setLightingEnabled(bool enabled) - { - if (CShader::m_lightingEnabled != enabled) { - for (shaders_t::const_iterator i = g_ActiveShaders.begin(); i != g_ActiveShaders.end(); ++i) { - (*i).second->unrealiseLighting(); - } - CShader::m_lightingEnabled = enabled; - for (shaders_t::const_iterator i = g_ActiveShaders.begin(); i != g_ActiveShaders.end(); ++i) { - (*i).second->realiseLighting(); - } - } - } - - const char *getTexturePrefix() const - { - return g_texturePrefix; - } +void realise(){ + Shaders_Realise(); +} + +void unrealise(){ + Shaders_Unrealise(); +} + +void refresh(){ + Shaders_Refresh(); +} + +IShader* getShaderForName( const char* name ){ + return Shader_ForName( name ); +} + +void foreachShaderName( const ShaderNameCallback& callback ){ + for ( ShaderDefinitionMap::const_iterator i = g_shaderDefinitions.begin(); i != g_shaderDefinitions.end(); ++i ) + { + callback( ( *i ).first.c_str() ); + } +} + +void beginActiveShadersIterator(){ + ActiveShaders_IteratorBegin(); +} + +bool endActiveShadersIterator(){ + return ActiveShaders_IteratorAtEnd(); +} + +IShader* dereferenceActiveShadersIterator(){ + return ActiveShaders_IteratorCurrent(); +} + +void incrementActiveShadersIterator(){ + ActiveShaders_IteratorIncrement(); +} + +void setActiveShadersChangedNotify( const Callback& notify ){ + g_ActiveShadersChangedNotify = notify; +} + +void attach( ModuleObserver& observer ){ + g_observers.attach( observer ); +} + +void detach( ModuleObserver& observer ){ + g_observers.detach( observer ); +} + +void setLightingEnabled( bool enabled ){ + if ( CShader::m_lightingEnabled != enabled ) { + for ( shaders_t::const_iterator i = g_ActiveShaders.begin(); i != g_ActiveShaders.end(); ++i ) + { + ( *i ).second->unrealiseLighting(); + } + CShader::m_lightingEnabled = enabled; + for ( shaders_t::const_iterator i = g_ActiveShaders.begin(); i != g_ActiveShaders.end(); ++i ) + { + ( *i ).second->realiseLighting(); + } + } +} + +const char* getTexturePrefix() const { + return g_texturePrefix; +} }; Quake3ShaderSystem g_Quake3ShaderSystem; -ShaderSystem &GetShaderSystem() -{ - return g_Quake3ShaderSystem; +ShaderSystem& GetShaderSystem(){ + return g_Quake3ShaderSystem; } -void Shaders_Construct() -{ - GlobalFileSystem().attach(g_Quake3ShaderSystem); +void Shaders_Construct(){ + GlobalFileSystem().attach( g_Quake3ShaderSystem ); } -void Shaders_Destroy() -{ - GlobalFileSystem().detach(g_Quake3ShaderSystem); +void Shaders_Destroy(){ + GlobalFileSystem().detach( g_Quake3ShaderSystem ); - if (Shaders_realised()) { - Shaders_Free(); - } + if ( Shaders_realised() ) { + Shaders_Free(); + } } diff --git a/radiant/brush.h b/radiant/brush.h index 96401a02..21e7d9ca 100644 --- a/radiant/brush.h +++ b/radiant/brush.h @@ -66,16 +66,17 @@ #include "brush_primit.h" const unsigned int BRUSH_DETAIL_FLAG = 27; -const unsigned int BRUSH_DETAIL_MASK = (1 << BRUSH_DETAIL_FLAG); - -enum EBrushType { - eBrushTypeQuake, - eBrushTypeQuake2, - eBrushTypeQuake3, - eBrushTypeQuake3BP, - eBrushTypeDoom3, - eBrushTypeQuake4, - eBrushTypeHalfLife, +const unsigned int BRUSH_DETAIL_MASK = ( 1 << BRUSH_DETAIL_FLAG ); + +enum EBrushType +{ + eBrushTypeQuake, + eBrushTypeQuake2, + eBrushTypeQuake3, + eBrushTypeQuake3BP, + eBrushTypeDoom3, + eBrushTypeQuake4, + eBrushTypeHalfLife, }; @@ -83,79 +84,76 @@ enum EBrushType { #define BRUSH_DEGENERATE_DEBUG 0 template -inline TextOuputStreamType &ostream_write(TextOuputStreamType &ostream, const Matrix4 &m) -{ - return ostream << "(" << m[0] << " " << m[1] << " " << m[2] << " " << m[3] << ", " - << m[4] << " " << m[5] << " " << m[6] << " " << m[7] << ", " - << m[8] << " " << m[9] << " " << m[10] << " " << m[11] << ", " - << m[12] << " " << m[13] << " " << m[14] << " " << m[15] << ")"; +inline TextOuputStreamType& ostream_write( TextOuputStreamType& ostream, const Matrix4& m ){ + return ostream << "(" << m[0] << " " << m[1] << " " << m[2] << " " << m[3] << ", " + << m[4] << " " << m[5] << " " << m[6] << " " << m[7] << ", " + << m[8] << " " << m[9] << " " << m[10] << " " << m[11] << ", " + << m[12] << " " << m[13] << " " << m[14] << " " << m[15] << ")"; } -inline void print_vector3(const Vector3 &v) -{ - globalOutputStream() << "( " << v.x() << " " << v.y() << " " << v.z() << " )\n"; +inline void print_vector3( const Vector3& v ){ + globalOutputStream() << "( " << v.x() << " " << v.y() << " " << v.z() << " )\n"; } -inline void print_3x3(const Matrix4 &m) -{ - globalOutputStream() << "( " << m.xx() << " " << m.xy() << " " << m.xz() << " ) " - << "( " << m.yx() << " " << m.yy() << " " << m.yz() << " ) " - << "( " << m.zx() << " " << m.zy() << " " << m.zz() << " )\n"; +inline void print_3x3( const Matrix4& m ){ + globalOutputStream() << "( " << m.xx() << " " << m.xy() << " " << m.xz() << " ) " + << "( " << m.yx() << " " << m.yy() << " " << m.yz() << " ) " + << "( " << m.zx() << " " << m.zy() << " " << m.zz() << " )\n"; } -inline bool texdef_sane(const texdef_t &texdef) -{ - return fabs(texdef.shift[0]) < (1 << 16) - && fabs(texdef.shift[1]) < (1 << 16); +inline bool texdef_sane( const texdef_t& texdef ){ + return fabs( texdef.shift[0] ) < ( 1 << 16 ) + && fabs( texdef.shift[1] ) < ( 1 << 16 ); } -inline void Winding_DrawWireframe(const Winding &winding) -{ - glVertexPointer(3, GL_FLOAT, sizeof(WindingVertex), &winding.points.data()->vertex); - glDrawArrays(GL_LINE_LOOP, 0, GLsizei(winding.numpoints)); +inline void Winding_DrawWireframe( const Winding& winding ){ + glVertexPointer( 3, GL_FLOAT, sizeof( WindingVertex ), &winding.points.data()->vertex ); + glDrawArrays( GL_LINE_LOOP, 0, GLsizei( winding.numpoints ) ); } -inline void Winding_Draw(const Winding &winding, const Vector3 &normal, RenderStateFlags state) -{ - glVertexPointer(3, GL_FLOAT, sizeof(WindingVertex), &winding.points.data()->vertex); - - if ((state & RENDER_BUMP) != 0) { - Vector3 normals[c_brush_maxFaces]; - typedef Vector3 *Vector3Iter; - for (Vector3Iter i = normals, end = normals + winding.numpoints; i != end; ++i) { - *i = normal; - } - if (GlobalShaderCache().useShaderLanguage()) { - glNormalPointer(GL_FLOAT, sizeof(Vector3), normals); - glVertexAttribPointerARB(c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof(WindingVertex), - &winding.points.data()->texcoord); - glVertexAttribPointerARB(c_attr_Tangent, 3, GL_FLOAT, 0, sizeof(WindingVertex), - &winding.points.data()->tangent); - glVertexAttribPointerARB(c_attr_Binormal, 3, GL_FLOAT, 0, sizeof(WindingVertex), - &winding.points.data()->bitangent); - } else { - glVertexAttribPointerARB(11, 3, GL_FLOAT, 0, sizeof(Vector3), normals); - glVertexAttribPointerARB(8, 2, GL_FLOAT, 0, sizeof(WindingVertex), &winding.points.data()->texcoord); - glVertexAttribPointerARB(9, 3, GL_FLOAT, 0, sizeof(WindingVertex), &winding.points.data()->tangent); - glVertexAttribPointerARB(10, 3, GL_FLOAT, 0, sizeof(WindingVertex), &winding.points.data()->bitangent); - } - } else { - if (state & RENDER_LIGHTING) { - Vector3 normals[c_brush_maxFaces]; - typedef Vector3 *Vector3Iter; - for (Vector3Iter i = normals, last = normals + winding.numpoints; i != last; ++i) { - *i = normal; - } - glNormalPointer(GL_FLOAT, sizeof(Vector3), normals); - } - - if (state & RENDER_TEXTURE) { - glTexCoordPointer(2, GL_FLOAT, sizeof(WindingVertex), &winding.points.data()->texcoord); - } - } +inline void Winding_Draw( const Winding& winding, const Vector3& normal, RenderStateFlags state ){ + glVertexPointer( 3, GL_FLOAT, sizeof( WindingVertex ), &winding.points.data()->vertex ); + + if ( ( state & RENDER_BUMP ) != 0 ) { + Vector3 normals[c_brush_maxFaces]; + typedef Vector3* Vector3Iter; + for ( Vector3Iter i = normals, end = normals + winding.numpoints; i != end; ++i ) + { + *i = normal; + } + if ( GlobalShaderCache().useShaderLanguage() ) { + glNormalPointer( GL_FLOAT, sizeof( Vector3 ), normals ); + glVertexAttribPointerARB( c_attr_TexCoord0, 2, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->texcoord ); + glVertexAttribPointerARB( c_attr_Tangent, 3, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->tangent ); + glVertexAttribPointerARB( c_attr_Binormal, 3, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->bitangent ); + } + else + { + glVertexAttribPointerARB( 11, 3, GL_FLOAT, 0, sizeof( Vector3 ), normals ); + glVertexAttribPointerARB( 8, 2, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->texcoord ); + glVertexAttribPointerARB( 9, 3, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->tangent ); + glVertexAttribPointerARB( 10, 3, GL_FLOAT, 0, sizeof( WindingVertex ), &winding.points.data()->bitangent ); + } + } + else + { + if ( state & RENDER_LIGHTING ) { + Vector3 normals[c_brush_maxFaces]; + typedef Vector3* Vector3Iter; + for ( Vector3Iter i = normals, last = normals + winding.numpoints; i != last; ++i ) + { + *i = normal; + } + glNormalPointer( GL_FLOAT, sizeof( Vector3 ), normals ); + } + + if ( state & RENDER_TEXTURE ) { + glTexCoordPointer( 2, GL_FLOAT, sizeof( WindingVertex ), &winding.points.data()->texcoord ); + } + } #if 0 - if ( state & RENDER_FILL ) { + if ( state & RENDER_FILL ) { glDrawArrays( GL_TRIANGLE_FAN, 0, GLsizei( winding.numpoints ) ); } else @@ -163,11 +161,11 @@ inline void Winding_Draw(const Winding &winding, const Vector3 &normal, RenderSt glDrawArrays( GL_LINE_LOOP, 0, GLsizei( winding.numpoints ) ); } #else - glDrawArrays(GL_POLYGON, 0, GLsizei(winding.numpoints)); + glDrawArrays( GL_POLYGON, 0, GLsizei( winding.numpoints ) ); #endif #if 0 - const Winding& winding = winding; + const Winding& winding = winding; if ( state & RENDER_FILL ) { glBegin( GL_POLYGON ); @@ -197,1285 +195,1180 @@ inline void Winding_Draw(const Winding &winding, const Vector3 &normal, RenderSt typedef DoubleVector3 PlanePoints[3]; -inline bool planepts_equal(const PlanePoints planepts, const PlanePoints other) -{ - return planepts[0] == other[0] && planepts[1] == other[1] && planepts[2] == other[2]; +inline bool planepts_equal( const PlanePoints planepts, const PlanePoints other ){ + return planepts[0] == other[0] && planepts[1] == other[1] && planepts[2] == other[2]; } -inline void planepts_assign(PlanePoints planepts, const PlanePoints other) -{ - planepts[0] = other[0]; - planepts[1] = other[1]; - planepts[2] = other[2]; +inline void planepts_assign( PlanePoints planepts, const PlanePoints other ){ + planepts[0] = other[0]; + planepts[1] = other[1]; + planepts[2] = other[2]; } -inline void planepts_quantise(PlanePoints planepts, double snap) -{ - vector3_snap(planepts[0], snap); - vector3_snap(planepts[1], snap); - vector3_snap(planepts[2], snap); +inline void planepts_quantise( PlanePoints planepts, double snap ){ + vector3_snap( planepts[0], snap ); + vector3_snap( planepts[1], snap ); + vector3_snap( planepts[2], snap ); } -inline float vector3_max_component(const Vector3 &vec3) -{ - return std::max(fabsf(vec3[0]), std::max(fabsf(vec3[1]), fabsf(vec3[2]))); +inline float vector3_max_component( const Vector3& vec3 ){ + return std::max( fabsf( vec3[0] ), std::max( fabsf( vec3[1] ), fabsf( vec3[2] ) ) ); } -inline void edge_snap(Vector3 &edge, double snap) -{ - float scale = static_cast( ceil(fabs(snap / vector3_max_component(edge)))); - if (scale > 0.0f) { - vector3_scale(edge, scale); - } - vector3_snap(edge, snap); +inline void edge_snap( Vector3& edge, double snap ){ + float scale = static_cast( ceil( fabs( snap / vector3_max_component( edge ) ) ) ); + if ( scale > 0.0f ) { + vector3_scale( edge, scale ); + } + vector3_snap( edge, snap ); } -inline void planepts_snap(PlanePoints planepts, double snap) -{ - Vector3 edge01(vector3_subtracted(planepts[1], planepts[0])); - Vector3 edge12(vector3_subtracted(planepts[2], planepts[1])); - Vector3 edge20(vector3_subtracted(planepts[0], planepts[2])); - - double length_squared_01 = vector3_dot(edge01, edge01); - double length_squared_12 = vector3_dot(edge12, edge12); - double length_squared_20 = vector3_dot(edge20, edge20); - - vector3_snap(planepts[0], snap); - - if (length_squared_01 < length_squared_12) { - if (length_squared_12 < length_squared_20) { - edge_snap(edge01, snap); - edge_snap(edge12, snap); - planepts[1] = vector3_added(planepts[0], edge01); - planepts[2] = vector3_added(planepts[1], edge12); - } else { - edge_snap(edge20, snap); - edge_snap(edge01, snap); - planepts[1] = vector3_added(planepts[0], edge20); - planepts[2] = vector3_added(planepts[1], edge01); - } - } else { - if (length_squared_01 < length_squared_20) { - edge_snap(edge01, snap); - edge_snap(edge12, snap); - planepts[1] = vector3_added(planepts[0], edge01); - planepts[2] = vector3_added(planepts[1], edge12); - } else { - edge_snap(edge12, snap); - edge_snap(edge20, snap); - planepts[1] = vector3_added(planepts[0], edge12); - planepts[2] = vector3_added(planepts[1], edge20); - } - } -} - -inline PointVertex pointvertex_for_planept(const DoubleVector3 &point, const Colour4b &colour) -{ - return PointVertex( - Vertex3f( - static_cast( point.x()), - static_cast( point.y()), - static_cast( point.z()) - ), - colour - ); +inline void planepts_snap( PlanePoints planepts, double snap ){ + Vector3 edge01( vector3_subtracted( planepts[1], planepts[0] ) ); + Vector3 edge12( vector3_subtracted( planepts[2], planepts[1] ) ); + Vector3 edge20( vector3_subtracted( planepts[0], planepts[2] ) ); + + double length_squared_01 = vector3_dot( edge01, edge01 ); + double length_squared_12 = vector3_dot( edge12, edge12 ); + double length_squared_20 = vector3_dot( edge20, edge20 ); + + vector3_snap( planepts[0], snap ); + + if ( length_squared_01 < length_squared_12 ) { + if ( length_squared_12 < length_squared_20 ) { + edge_snap( edge01, snap ); + edge_snap( edge12, snap ); + planepts[1] = vector3_added( planepts[0], edge01 ); + planepts[2] = vector3_added( planepts[1], edge12 ); + } + else + { + edge_snap( edge20, snap ); + edge_snap( edge01, snap ); + planepts[1] = vector3_added( planepts[0], edge20 ); + planepts[2] = vector3_added( planepts[1], edge01 ); + } + } + else + { + if ( length_squared_01 < length_squared_20 ) { + edge_snap( edge01, snap ); + edge_snap( edge12, snap ); + planepts[1] = vector3_added( planepts[0], edge01 ); + planepts[2] = vector3_added( planepts[1], edge12 ); + } + else + { + edge_snap( edge12, snap ); + edge_snap( edge20, snap ); + planepts[1] = vector3_added( planepts[0], edge12 ); + planepts[2] = vector3_added( planepts[1], edge20 ); + } + } } -inline PointVertex pointvertex_for_windingpoint(const Vector3 &point, const Colour4b &colour) -{ - return PointVertex( - vertex3f_for_vector3(point), - colour - ); +inline PointVertex pointvertex_for_planept( const DoubleVector3& point, const Colour4b& colour ){ + return PointVertex( + Vertex3f( + static_cast( point.x() ), + static_cast( point.y() ), + static_cast( point.z() ) + ), + colour + ); } -inline bool check_plane_is_integer(const PlanePoints &planePoints) -{ - return !float_is_integer(planePoints[0][0]) - || !float_is_integer(planePoints[0][1]) - || !float_is_integer(planePoints[0][2]) - || !float_is_integer(planePoints[1][0]) - || !float_is_integer(planePoints[1][1]) - || !float_is_integer(planePoints[1][2]) - || !float_is_integer(planePoints[2][0]) - || !float_is_integer(planePoints[2][1]) - || !float_is_integer(planePoints[2][2]); -} - -inline void brush_check_shader(const char *name) -{ - if (!shader_valid(name)) { - globalErrorStream() << "brush face has invalid texture name: '" << name << "'\n"; - } +inline PointVertex pointvertex_for_windingpoint( const Vector3& point, const Colour4b& colour ){ + return PointVertex( + vertex3f_for_vector3( point ), + colour + ); +} + +inline bool check_plane_is_integer( const PlanePoints& planePoints ){ + return !float_is_integer( planePoints[0][0] ) + || !float_is_integer( planePoints[0][1] ) + || !float_is_integer( planePoints[0][2] ) + || !float_is_integer( planePoints[1][0] ) + || !float_is_integer( planePoints[1][1] ) + || !float_is_integer( planePoints[1][2] ) + || !float_is_integer( planePoints[2][0] ) + || !float_is_integer( planePoints[2][1] ) + || !float_is_integer( planePoints[2][2] ); +} + +inline void brush_check_shader( const char* name ){ + if ( !shader_valid( name ) ) { + globalErrorStream() << "brush face has invalid texture name: '" << name << "'\n"; + } } -class FaceShaderObserver { +class FaceShaderObserver +{ public: - virtual void realiseShader() = 0; +virtual void realiseShader() = 0; - virtual void unrealiseShader() = 0; +virtual void unrealiseShader() = 0; }; typedef ReferencePair FaceShaderObserverPair; -class ContentsFlagsValue { +class ContentsFlagsValue +{ public: - ContentsFlagsValue() - { - } - - ContentsFlagsValue(int surfaceFlags, int contentFlags, int value, bool specified) : - m_surfaceFlags(surfaceFlags), - m_contentFlags(contentFlags), - m_value(value), - m_specified(specified) - { - } - - int m_surfaceFlags; - int m_contentFlags; - int m_value; - bool m_specified; +ContentsFlagsValue(){ +} + +ContentsFlagsValue( int surfaceFlags, int contentFlags, int value, bool specified ) : + m_surfaceFlags( surfaceFlags ), + m_contentFlags( contentFlags ), + m_value( value ), + m_specified( specified ){ +} + +int m_surfaceFlags; +int m_contentFlags; +int m_value; +bool m_specified; }; -inline void ContentsFlagsValue_assignMasked(ContentsFlagsValue &flags, const ContentsFlagsValue &other) -{ - bool detail = bitfield_enabled(flags.m_contentFlags, BRUSH_DETAIL_MASK); - flags = other; - if (detail) { - flags.m_contentFlags = bitfield_enable(flags.m_contentFlags, BRUSH_DETAIL_MASK); - } else { - flags.m_contentFlags = bitfield_disable(flags.m_contentFlags, BRUSH_DETAIL_MASK); - } +inline void ContentsFlagsValue_assignMasked( ContentsFlagsValue& flags, const ContentsFlagsValue& other ){ + bool detail = bitfield_enabled( flags.m_contentFlags, BRUSH_DETAIL_MASK ); + flags = other; + if ( detail ) { + flags.m_contentFlags = bitfield_enable( flags.m_contentFlags, BRUSH_DETAIL_MASK ); + } + else + { + flags.m_contentFlags = bitfield_disable( flags.m_contentFlags, BRUSH_DETAIL_MASK ); + } } -class FaceShader : public ModuleObserver { +class FaceShader : public ModuleObserver +{ +public: +class SavedState +{ public: - class SavedState { - public: - CopiedString m_shader; - ContentsFlagsValue m_flags; - - SavedState(const FaceShader &faceShader) - { - m_shader = faceShader.getShader(); - m_flags = faceShader.m_flags; - } - - void exportState(FaceShader &faceShader) const - { - faceShader.setShader(m_shader.c_str()); - faceShader.m_flags = m_flags; - } - }; - - CopiedString m_shader; - Shader *m_state; - ContentsFlagsValue m_flags; - FaceShaderObserverPair m_observers; - bool m_instanced; - bool m_realised; - - FaceShader(const char *shader, const ContentsFlagsValue &flags = ContentsFlagsValue(0, 0, 0, false)) : - m_shader(shader), - m_state(0), - m_flags(flags), - m_instanced(false), - m_realised(false) - { - captureShader(); - } - - ~FaceShader() - { - releaseShader(); - } +CopiedString m_shader; +ContentsFlagsValue m_flags; + +SavedState( const FaceShader& faceShader ){ + m_shader = faceShader.getShader(); + m_flags = faceShader.m_flags; +} + +void exportState( FaceShader& faceShader ) const { + faceShader.setShader( m_shader.c_str() ); + faceShader.setFlags( m_flags ); +} +}; + +CopiedString m_shader; +Shader* m_state; +ContentsFlagsValue m_flags; +FaceShaderObserverPair m_observers; +bool m_instanced; +bool m_realised; + +FaceShader( const char* shader, const ContentsFlagsValue& flags = ContentsFlagsValue( 0, 0, 0, false ) ) : + m_shader( shader ), + m_state( 0 ), + m_flags( flags ), + m_instanced( false ), + m_realised( false ){ + captureShader(); +} + +~FaceShader(){ + releaseShader(); +} // copy-construction not supported - FaceShader(const FaceShader &other); - - void instanceAttach() - { - m_instanced = true; - m_state->incrementUsed(); - } - - void instanceDetach() - { - m_state->decrementUsed(); - m_instanced = false; - } - - void captureShader() - { - ASSERT_MESSAGE(m_state == 0, "shader cannot be captured"); - brush_check_shader(m_shader.c_str()); - m_state = GlobalShaderCache().capture(m_shader.c_str()); - m_state->attach(*this); - } - - void releaseShader() - { - ASSERT_MESSAGE(m_state != 0, "shader cannot be released"); - m_state->detach(*this); - GlobalShaderCache().release(m_shader.c_str()); - m_state = 0; - } - - void realise() - { - ASSERT_MESSAGE(!m_realised, "FaceTexdef::realise: already realised"); - m_realised = true; - m_observers.forEach([](FaceShaderObserver &observer) { - observer.realiseShader(); - }); - } - - void unrealise() - { - ASSERT_MESSAGE(m_realised, "FaceTexdef::unrealise: already unrealised"); - m_observers.forEach([](FaceShaderObserver &observer) { - observer.unrealiseShader(); - }); - m_realised = false; - } - - void attach(FaceShaderObserver &observer) - { - m_observers.attach(observer); - if (m_realised) { - observer.realiseShader(); - } - } - - void detach(FaceShaderObserver &observer) - { - if (m_realised) { - observer.unrealiseShader(); - } - m_observers.detach(observer); - } - - const char *getShader() const - { - return m_shader.c_str(); - } - - void setShader(const char *name) - { - if (m_instanced) { - m_state->decrementUsed(); - } - releaseShader(); - m_shader = name; - captureShader(); - if (m_instanced) { - m_state->incrementUsed(); - } - } - - ContentsFlagsValue getFlags() const - { - ASSERT_MESSAGE(m_realised, "FaceShader::getFlags: flags not valid when unrealised"); - if (!m_flags.m_specified) { - return ContentsFlagsValue( - m_state->getTexture().surfaceFlags, - m_state->getTexture().contentFlags, - m_state->getTexture().value, - true - ); - } - return m_flags; - } - - void setFlags(const ContentsFlagsValue &flags) - { - ASSERT_MESSAGE(m_realised, "FaceShader::setFlags: flags not valid when unrealised"); - ContentsFlagsValue_assignMasked(m_flags, flags); - } - - Shader *state() const - { - return m_state; - } - - std::size_t width() const - { - if (m_realised) { - return m_state->getTexture().width; - } - return 1; - } - - std::size_t height() const - { - if (m_realised) { - return m_state->getTexture().height; - } - return 1; - } - - unsigned int shaderFlags() const - { - if (m_realised) { - return m_state->getFlags(); - } - return 0; - } +FaceShader( const FaceShader& other ); + +void instanceAttach(){ + m_instanced = true; + m_state->incrementUsed(); +} + +void instanceDetach(){ + m_state->decrementUsed(); + m_instanced = false; +} + +void captureShader(){ + ASSERT_MESSAGE( m_state == 0, "shader cannot be captured" ); + brush_check_shader( m_shader.c_str() ); + m_state = GlobalShaderCache().capture( m_shader.c_str() ); + m_state->attach( *this ); +} + +void releaseShader(){ + ASSERT_MESSAGE( m_state != 0, "shader cannot be released" ); + m_state->detach( *this ); + GlobalShaderCache().release( m_shader.c_str() ); + m_state = 0; +} + +void realise(){ + ASSERT_MESSAGE( !m_realised, "FaceTexdef::realise: already realised" ); + m_realised = true; + m_observers.forEach([](FaceShaderObserver &observer) { + observer.realiseShader(); + }); +} + +void unrealise(){ + ASSERT_MESSAGE( m_realised, "FaceTexdef::unrealise: already unrealised" ); + m_observers.forEach([](FaceShaderObserver &observer) { + observer.unrealiseShader(); + }); + m_realised = false; +} + +void attach( FaceShaderObserver& observer ){ + m_observers.attach( observer ); + if ( m_realised ) { + observer.realiseShader(); + } +} + +void detach( FaceShaderObserver& observer ){ + if ( m_realised ) { + observer.unrealiseShader(); + } + m_observers.detach( observer ); +} + +const char* getShader() const { + return m_shader.c_str(); +} +void setShader( const char* name ){ + if ( m_instanced ) { + m_state->decrementUsed(); + } + releaseShader(); + m_shader = name; + captureShader(); + if ( m_instanced ) { + m_state->incrementUsed(); + } +} + +ContentsFlagsValue getFlags() const { + ASSERT_MESSAGE( m_realised, "FaceShader::getFlags: flags not valid when unrealised" ); + if ( !m_flags.m_specified ) { + return ContentsFlagsValue( + m_state->getTexture().surfaceFlags, + m_state->getTexture().contentFlags, + m_state->getTexture().value, + true + ); + } + return m_flags; +} + +void setFlags( const ContentsFlagsValue& flags ){ + ASSERT_MESSAGE( m_realised, "FaceShader::setFlags: flags not valid when unrealised" ); + ContentsFlagsValue_assignMasked( m_flags, flags ); +} + +Shader* state() const { + return m_state; +} + +std::size_t width() const { + if ( m_realised ) { + return m_state->getTexture().width; + } + return 1; +} + +std::size_t height() const { + if ( m_realised ) { + return m_state->getTexture().height; + } + return 1; +} + +unsigned int shaderFlags() const { + if ( m_realised ) { + return m_state->getFlags(); + } + return 0; +} }; -class FaceTexdef : public FaceShaderObserver { +class FaceTexdef : public FaceShaderObserver +{ // not copyable - FaceTexdef(const FaceTexdef &other); +FaceTexdef( const FaceTexdef& other ); // not assignable - FaceTexdef &operator=(const FaceTexdef &other); +FaceTexdef& operator=( const FaceTexdef& other ); public: - class SavedState { - public: - TextureProjection m_projection; - - SavedState(const FaceTexdef &faceTexdef) - { - m_projection = faceTexdef.m_projection; - } - - void exportState(FaceTexdef &faceTexdef) const - { - Texdef_Assign(faceTexdef.m_projection, m_projection); - } - }; - - FaceShader &m_shader; - TextureProjection m_projection; - bool m_projectionInitialised; - bool m_scaleApplied; - - FaceTexdef( - FaceShader &shader, - const TextureProjection &projection, - bool projectionInitialised = true - ) : - m_shader(shader), - m_projection(projection), - m_projectionInitialised(projectionInitialised), - m_scaleApplied(false) - { - m_shader.attach(*this); - } - - ~FaceTexdef() - { - m_shader.detach(*this); - } - - void addScale() - { - ASSERT_MESSAGE(!m_scaleApplied, "texture scale aready added"); - m_scaleApplied = true; - m_projection.m_brushprimit_texdef.addScale(m_shader.width(), m_shader.height()); - } - - void removeScale() - { - ASSERT_MESSAGE(m_scaleApplied, "texture scale aready removed"); - m_scaleApplied = false; - m_projection.m_brushprimit_texdef.removeScale(m_shader.width(), m_shader.height()); - } - - void realiseShader() - { - if (m_projectionInitialised && !m_scaleApplied) { - addScale(); - } - } - - void unrealiseShader() - { - if (m_projectionInitialised && m_scaleApplied) { - removeScale(); - } - } - - void setTexdef(const TextureProjection &projection) - { - removeScale(); - Texdef_Assign(m_projection, projection); - addScale(); - } - - void shift(float s, float t) - { - ASSERT_MESSAGE(texdef_sane(m_projection.m_texdef), "FaceTexdef::shift: bad texdef"); - removeScale(); - Texdef_Shift(m_projection, s, t); - addScale(); - } - - void scale(float s, float t) - { - removeScale(); - Texdef_Scale(m_projection, s, t); - addScale(); - } - - void rotate(float angle) - { - removeScale(); - Texdef_Rotate(m_projection, angle); - addScale(); - } - - void fit(const Vector3 &normal, const Winding &winding, float s_repeat, float t_repeat) - { - Texdef_FitTexture(m_projection, m_shader.width(), m_shader.height(), normal, winding, s_repeat, t_repeat); - } - - void emitTextureCoordinates(Winding &winding, const Vector3 &normal, const Matrix4 &localToWorld) - { - Texdef_EmitTextureCoordinates(m_projection, m_shader.width(), m_shader.height(), winding, normal, localToWorld); - } - - void transform(const Plane3 &plane, const Matrix4 &matrix) - { - removeScale(); - Texdef_transformLocked(m_projection, m_shader.width(), m_shader.height(), plane, matrix); - addScale(); - } - - TextureProjection normalised() const - { - brushprimit_texdef_t tmp(m_projection.m_brushprimit_texdef); - tmp.removeScale(m_shader.width(), m_shader.height()); - return TextureProjection(m_projection.m_texdef, tmp, m_projection.m_basis_s, m_projection.m_basis_t); - } - - void setBasis(const Vector3 &normal) - { - Matrix4 basis; - Normal_GetTransform(normal, basis); - m_projection.m_basis_s = Vector3(basis.xx(), basis.yx(), basis.zx()); - m_projection.m_basis_t = Vector3(-basis.xy(), -basis.yy(), -basis.zy()); - } +class SavedState +{ +public: +TextureProjection m_projection; + +SavedState( const FaceTexdef& faceTexdef ){ + m_projection = faceTexdef.m_projection; +} + +void exportState( FaceTexdef& faceTexdef ) const { + Texdef_Assign( faceTexdef.m_projection, m_projection ); +} }; -inline void planepts_print(const PlanePoints &planePoints, TextOutputStream &ostream) -{ - ostream << "( " << planePoints[0][0] << " " << planePoints[0][1] << " " << planePoints[0][2] << " ) " - << "( " << planePoints[1][0] << " " << planePoints[1][1] << " " << planePoints[1][2] << " ) " - << "( " << planePoints[2][0] << " " << planePoints[2][1] << " " << planePoints[2][2] << " )"; +FaceShader& m_shader; +TextureProjection m_projection; +bool m_projectionInitialised; +bool m_scaleApplied; + +FaceTexdef( + FaceShader& shader, + const TextureProjection& projection, + bool projectionInitialised = true + ) : + m_shader( shader ), + m_projection( projection ), + m_projectionInitialised( projectionInitialised ), + m_scaleApplied( false ){ + m_shader.attach( *this ); } +~FaceTexdef(){ + m_shader.detach( *this ); +} -inline Plane3 Plane3_applyTranslation(const Plane3 &plane, const Vector3 &translation) -{ - Plane3 tmp(plane3_translated(Plane3(plane.normal(), -plane.dist()), translation)); - return Plane3(tmp.normal(), -tmp.dist()); +void addScale(){ + ASSERT_MESSAGE( !m_scaleApplied, "texture scale aready added" ); + m_scaleApplied = true; + m_projection.m_brushprimit_texdef.addScale( m_shader.width(), m_shader.height() ); +} + +void removeScale(){ + ASSERT_MESSAGE( m_scaleApplied, "texture scale aready removed" ); + m_scaleApplied = false; + m_projection.m_brushprimit_texdef.removeScale( m_shader.width(), m_shader.height() ); +} + +void realiseShader(){ + if ( m_projectionInitialised && !m_scaleApplied ) { + addScale(); + } +} + +void unrealiseShader(){ + if ( m_projectionInitialised && m_scaleApplied ) { + removeScale(); + } +} + +void setTexdef( const TextureProjection& projection ){ + removeScale(); + Texdef_Assign( m_projection, projection ); + addScale(); +} + +void shift( float s, float t ){ + ASSERT_MESSAGE( texdef_sane( m_projection.m_texdef ), "FaceTexdef::shift: bad texdef" ); + removeScale(); + Texdef_Shift( m_projection, s, t ); + addScale(); +} + +void scale( float s, float t ){ + removeScale(); + Texdef_Scale( m_projection, s, t ); + addScale(); +} + +void rotate( float angle ){ + removeScale(); + Texdef_Rotate( m_projection, angle ); + addScale(); +} + +void fit( const Vector3& normal, const Winding& winding, float s_repeat, float t_repeat ){ + Texdef_FitTexture( m_projection, m_shader.width(), m_shader.height(), normal, winding, s_repeat, t_repeat ); +} + +void emitTextureCoordinates( Winding& winding, const Vector3& normal, const Matrix4& localToWorld ){ + Texdef_EmitTextureCoordinates( m_projection, m_shader.width(), m_shader.height(), winding, normal, localToWorld ); +} + +void transform( const Plane3& plane, const Matrix4& matrix ){ + removeScale(); + Texdef_transformLocked( m_projection, m_shader.width(), m_shader.height(), plane, matrix ); + addScale(); } -inline Plane3 Plane3_applyTransform(const Plane3 &plane, const Matrix4 &matrix) +TextureProjection normalised() const { + brushprimit_texdef_t tmp( m_projection.m_brushprimit_texdef ); + tmp.removeScale( m_shader.width(), m_shader.height() ); + return TextureProjection( m_projection.m_texdef, tmp, m_projection.m_basis_s, m_projection.m_basis_t ); +} + +void setBasis( const Vector3& normal ){ + Matrix4 basis; + Normal_GetTransform( normal, basis ); + m_projection.m_basis_s = Vector3( basis.xx(), basis.yx(), basis.zx() ); + m_projection.m_basis_t = Vector3( -basis.xy(), -basis.yy(), -basis.zy() ); +} +}; + +inline void planepts_print( const PlanePoints& planePoints, TextOutputStream& ostream ){ + ostream << "( " << planePoints[0][0] << " " << planePoints[0][1] << " " << planePoints[0][2] << " ) " + << "( " << planePoints[1][0] << " " << planePoints[1][1] << " " << planePoints[1][2] << " ) " + << "( " << planePoints[2][0] << " " << planePoints[2][1] << " " << planePoints[2][2] << " )"; +} + + +inline Plane3 Plane3_applyTranslation( const Plane3& plane, const Vector3& translation ){ + Plane3 tmp( plane3_translated( Plane3( plane.normal(), -plane.dist() ), translation ) ); + return Plane3( tmp.normal(), -tmp.dist() ); +} + +inline Plane3 Plane3_applyTransform( const Plane3& plane, const Matrix4& matrix ){ + Plane3 tmp( plane3_transformed( Plane3( plane.normal(), -plane.dist() ), matrix ) ); + return Plane3( tmp.normal(), -tmp.dist() ); +} + +class FacePlane { - Plane3 tmp(plane3_transformed(Plane3(plane.normal(), -plane.dist()), matrix)); - return Plane3(tmp.normal(), -tmp.dist()); +PlanePoints m_planepts; +Plane3 m_planeCached; +Plane3 m_plane; +public: +Vector3 m_funcStaticOrigin; + +static EBrushType m_type; + +static bool isDoom3Plane(){ + return FacePlane::m_type == eBrushTypeDoom3 || FacePlane::m_type == eBrushTypeQuake4; } -class FacePlane { - PlanePoints m_planepts; - Plane3 m_planeCached; - Plane3 m_plane; +class SavedState +{ public: - Vector3 m_funcStaticOrigin; - - static EBrushType m_type; - - static bool isDoom3Plane() - { - return FacePlane::m_type == eBrushTypeDoom3 || FacePlane::m_type == eBrushTypeQuake4; - } - - class SavedState { - public: - PlanePoints m_planepts; - Plane3 m_plane; - - SavedState(const FacePlane &facePlane) - { - if (facePlane.isDoom3Plane()) { - m_plane = facePlane.m_plane; - } else { - planepts_assign(m_planepts, facePlane.planePoints()); - } - } - - void exportState(FacePlane &facePlane) const - { - if (facePlane.isDoom3Plane()) { - facePlane.m_plane = m_plane; - facePlane.updateTranslated(); - } else { - planepts_assign(facePlane.planePoints(), m_planepts); - facePlane.MakePlane(); - } - } - }; - - FacePlane() : m_funcStaticOrigin(0, 0, 0) - { - } - - FacePlane(const FacePlane &other) : m_funcStaticOrigin(0, 0, 0) - { - if (!isDoom3Plane()) { - planepts_assign(m_planepts, other.m_planepts); - MakePlane(); - } else { - m_plane = other.m_plane; - updateTranslated(); - } - } - - void MakePlane() - { - if (!isDoom3Plane()) { +PlanePoints m_planepts; +Plane3 m_plane; + +SavedState( const FacePlane& facePlane ){ + if ( facePlane.isDoom3Plane() ) { + m_plane = facePlane.m_plane; + } + else + { + planepts_assign( m_planepts, facePlane.planePoints() ); + } +} + +void exportState( FacePlane& facePlane ) const { + if ( facePlane.isDoom3Plane() ) { + facePlane.m_plane = m_plane; + facePlane.updateTranslated(); + } + else + { + planepts_assign( facePlane.planePoints(), m_planepts ); + facePlane.MakePlane(); + } +} +}; + +FacePlane() : m_funcStaticOrigin( 0, 0, 0 ){ +} + +FacePlane( const FacePlane& other ) : m_funcStaticOrigin( 0, 0, 0 ){ + if ( !isDoom3Plane() ) { + planepts_assign( m_planepts, other.m_planepts ); + MakePlane(); + } + else + { + m_plane = other.m_plane; + updateTranslated(); + } +} + +void MakePlane(){ + if ( !isDoom3Plane() ) { #if 0 - if ( check_plane_is_integer( m_planepts ) ) { + if ( check_plane_is_integer( m_planepts ) ) { globalErrorStream() << "non-integer planepts: "; planepts_print( m_planepts, globalErrorStream() ); globalErrorStream() << "\n"; } #endif - m_planeCached = plane3_for_points(m_planepts); - } - } - - void reverse() - { - if (!isDoom3Plane()) { - vector3_swap(m_planepts[0], m_planepts[2]); - MakePlane(); - } else { - m_planeCached = plane3_flipped(m_plane); - updateSource(); - } - } - - void transform(const Matrix4 &matrix, bool mirror) - { - if (!isDoom3Plane()) { + m_planeCached = plane3_for_points( m_planepts ); + } +} + +void reverse(){ + if ( !isDoom3Plane() ) { + vector3_swap( m_planepts[0], m_planepts[2] ); + MakePlane(); + } + else + { + m_planeCached = plane3_flipped( m_plane ); + updateSource(); + } +} + +void transform( const Matrix4& matrix, bool mirror ){ + if ( !isDoom3Plane() ) { #if 0 - bool off = check_plane_is_integer( planePoints() ); + bool off = check_plane_is_integer( planePoints() ); #endif - matrix4_transform_point(matrix, m_planepts[0]); - matrix4_transform_point(matrix, m_planepts[1]); - matrix4_transform_point(matrix, m_planepts[2]); + matrix4_transform_point( matrix, m_planepts[0] ); + matrix4_transform_point( matrix, m_planepts[1] ); + matrix4_transform_point( matrix, m_planepts[2] ); - if (mirror) { - reverse(); - } + if ( mirror ) { + reverse(); + } #if 0 - if ( check_plane_is_integer( planePoints() ) ) { + if ( check_plane_is_integer( planePoints() ) ) { if ( !off ) { globalErrorStream() << "caused by transform\n"; } } #endif - MakePlane(); - } else { - m_planeCached = Plane3_applyTransform(m_planeCached, matrix); - updateSource(); - } - } - - void offset(float offset) - { - if (!isDoom3Plane()) { - Vector3 move(vector3_scaled(m_planeCached.normal(), -offset)); - - vector3_subtract(m_planepts[0], move); - vector3_subtract(m_planepts[1], move); - vector3_subtract(m_planepts[2], move); - - MakePlane(); - } else { - m_planeCached.d += offset; - updateSource(); - } - } - - void updateTranslated() - { - m_planeCached = Plane3_applyTranslation(m_plane, m_funcStaticOrigin); - } - - void updateSource() - { - m_plane = Plane3_applyTranslation(m_planeCached, vector3_negated(m_funcStaticOrigin)); - } - - - PlanePoints &planePoints() - { - return m_planepts; - } - - const PlanePoints &planePoints() const - { - return m_planepts; - } - - const Plane3 &plane3() const - { - return m_planeCached; - } - - void setDoom3Plane(const Plane3 &plane) - { - m_plane = plane; - updateTranslated(); - } - - const Plane3 &getDoom3Plane() const - { - return m_plane; - } - - void copy(const FacePlane &other) - { - if (!isDoom3Plane()) { - planepts_assign(m_planepts, other.m_planepts); - MakePlane(); - } else { - m_planeCached = other.m_plane; - updateSource(); - } - } - - void copy(const Vector3 &p0, const Vector3 &p1, const Vector3 &p2) - { - if (!isDoom3Plane()) { - m_planepts[0] = p0; - m_planepts[1] = p1; - m_planepts[2] = p2; - MakePlane(); - } else { - m_planeCached = plane3_for_points(p2, p1, p0); - updateSource(); - } - } + MakePlane(); + } + else + { + m_planeCached = Plane3_applyTransform( m_planeCached, matrix ); + updateSource(); + } +} + +void offset( float offset ){ + if ( !isDoom3Plane() ) { + Vector3 move( vector3_scaled( m_planeCached.normal(), -offset ) ); + + vector3_subtract( m_planepts[0], move ); + vector3_subtract( m_planepts[1], move ); + vector3_subtract( m_planepts[2], move ); + + MakePlane(); + } + else + { + m_planeCached.d += offset; + updateSource(); + } +} + +void updateTranslated(){ + m_planeCached = Plane3_applyTranslation( m_plane, m_funcStaticOrigin ); +} + +void updateSource(){ + m_plane = Plane3_applyTranslation( m_planeCached, vector3_negated( m_funcStaticOrigin ) ); +} + + +PlanePoints& planePoints(){ + return m_planepts; +} + +const PlanePoints& planePoints() const { + return m_planepts; +} + +const Plane3& plane3() const { + return m_planeCached; +} + +void setDoom3Plane( const Plane3& plane ){ + m_plane = plane; + updateTranslated(); +} + +const Plane3& getDoom3Plane() const { + return m_plane; +} + +void copy( const FacePlane& other ){ + if ( !isDoom3Plane() ) { + planepts_assign( m_planepts, other.m_planepts ); + MakePlane(); + } + else + { + m_planeCached = other.m_plane; + updateSource(); + } +} + +void copy( const Vector3& p0, const Vector3& p1, const Vector3& p2 ){ + if ( !isDoom3Plane() ) { + m_planepts[0] = p0; + m_planepts[1] = p1; + m_planepts[2] = p2; + MakePlane(); + } + else + { + m_planeCached = plane3_for_points( p2, p1, p0 ); + updateSource(); + } +} }; -inline void Winding_testSelect(Winding &winding, SelectionTest &test, SelectionIntersection &best) -{ - test.TestPolygon(VertexPointer(reinterpret_cast( &winding.points.data()->vertex ), - sizeof(WindingVertex)), winding.numpoints, best); +inline void Winding_testSelect( Winding& winding, SelectionTest& test, SelectionIntersection& best ){ + test.TestPolygon( VertexPointer( reinterpret_cast( &winding.points.data()->vertex ), sizeof( WindingVertex ) ), winding.numpoints, best ); } const double GRID_MIN = 0.125; -inline double quantiseInteger(double f) -{ - return float_to_integer(f); +inline double quantiseInteger( double f ){ + return float_to_integer( f ); } -inline double quantiseFloating(double f) -{ - return float_snapped(f, 1.f / (1 << 16)); +inline double quantiseFloating( double f ){ + return float_snapped( f, 1.f / ( 1 << 16 ) ); } -typedef double ( *QuantiseFunc )(double f); +typedef double ( *QuantiseFunc )( double f ); class Face; -class FaceFilter { +class FaceFilter +{ public: - virtual bool filter(const Face &face) const = 0; +virtual bool filter( const Face& face ) const = 0; }; -bool face_filtered(Face &face); +bool face_filtered( Face& face ); -void add_face_filter(FaceFilter &filter, int mask, bool invert = false); +void add_face_filter( FaceFilter& filter, int mask, bool invert = false ); -void Brush_addTextureChangedCallback(const SignalHandler &callback); +void Brush_addTextureChangedCallback( const SignalHandler& callback ); void Brush_textureChanged(); extern bool g_brush_texturelock_enabled; -class FaceObserver { +class FaceObserver +{ public: - virtual void planeChanged() = 0; +virtual void planeChanged() = 0; - virtual void connectivityChanged() = 0; +virtual void connectivityChanged() = 0; - virtual void shaderChanged() = 0; +virtual void shaderChanged() = 0; - virtual void evaluateTransform() = 0; +virtual void evaluateTransform() = 0; }; class Face : - public OpenGLRenderable, - public Filterable, - public Undoable, - public FaceShaderObserver { - std::size_t m_refcount; - - class SavedState : public UndoMemento { - public: - FacePlane::SavedState m_planeState; - FaceTexdef::SavedState m_texdefState; - FaceShader::SavedState m_shaderState; - - SavedState(const Face &face) : m_planeState(face.getPlane()), m_texdefState(face.getTexdef()), - m_shaderState(face.getShader()) - { - } - - void exportState(Face &face) const - { - m_planeState.exportState(face.getPlane()); - m_shaderState.exportState(face.getShader()); - m_texdefState.exportState(face.getTexdef()); - } - - void release() - { - delete this; - } - }; + public OpenGLRenderable, + public Filterable, + public Undoable, + public FaceShaderObserver +{ +std::size_t m_refcount; + +class SavedState : public UndoMemento +{ +public: +FacePlane::SavedState m_planeState; +FaceTexdef::SavedState m_texdefState; +FaceShader::SavedState m_shaderState; + +SavedState( const Face& face ) : m_planeState( face.getPlane() ), m_texdefState( face.getTexdef() ), m_shaderState( face.getShader() ){ +} + +void exportState( Face& face ) const { + m_planeState.exportState( face.getPlane() ); + m_shaderState.exportState( face.getShader() ); + m_texdefState.exportState( face.getTexdef() ); +} + +void release(){ + delete this; +} +}; public: - static QuantiseFunc m_quantise; - static EBrushType m_type; +static QuantiseFunc m_quantise; +static EBrushType m_type; - PlanePoints m_move_planepts; - PlanePoints m_move_planeptsTransformed; +PlanePoints m_move_planepts; +PlanePoints m_move_planeptsTransformed; private: - FacePlane m_plane; - FacePlane m_planeTransformed; - FaceShader m_shader; - FaceTexdef m_texdef; - TextureProjection m_texdefTransformed; +FacePlane m_plane; +FacePlane m_planeTransformed; +FaceShader m_shader; +FaceTexdef m_texdef; +TextureProjection m_texdefTransformed; - Winding m_winding; - Vector3 m_centroid; - bool m_filtered; +Winding m_winding; +Vector3 m_centroid; +bool m_filtered; - FaceObserver *m_observer; - UndoObserver *m_undoable_observer; - MapFile *m_map; +FaceObserver* m_observer; +UndoObserver* m_undoable_observer; +MapFile* m_map; // assignment not supported - Face &operator=(const Face &other); +Face& operator=( const Face& other ); // copy-construction not supported - Face(const Face &other); +Face( const Face& other ); public: - Face(FaceObserver *observer) : - m_refcount(0), - m_shader(texdef_name_default()), - m_texdef(m_shader, TextureProjection(), false), - m_filtered(false), - m_observer(observer), - m_undoable_observer(0), - m_map(0) - { - m_shader.attach(*this); - m_plane.copy(Vector3(0, 0, 0), Vector3(64, 0, 0), Vector3(0, 64, 0)); - m_texdef.setBasis(m_plane.plane3().normal()); - planeChanged(); - } - - Face( - const Vector3 &p0, - const Vector3 &p1, - const Vector3 &p2, - const char *shader, - const TextureProjection &projection, - FaceObserver *observer - ) : - m_refcount(0), - m_shader(shader), - m_texdef(m_shader, projection), - m_observer(observer), - m_undoable_observer(0), - m_map(0) - { - m_shader.attach(*this); - m_plane.copy(p0, p1, p2); - m_texdef.setBasis(m_plane.plane3().normal()); - planeChanged(); - updateFiltered(); - } - - Face(const Face &other, FaceObserver *observer) : - m_refcount(0), - m_shader(other.m_shader.getShader(), other.m_shader.m_flags), - m_texdef(m_shader, other.getTexdef().normalised()), - m_observer(observer), - m_undoable_observer(0), - m_map(0) - { - m_shader.attach(*this); - m_plane.copy(other.m_plane); - planepts_assign(m_move_planepts, other.m_move_planepts); - m_texdef.setBasis(m_plane.plane3().normal()); - planeChanged(); - updateFiltered(); - } - - ~Face() - { - m_shader.detach(*this); - } - - void planeChanged() - { - revertTransform(); - m_observer->planeChanged(); - } - - void realiseShader() - { - m_observer->shaderChanged(); - } - - void unrealiseShader() - { - } - - void instanceAttach(MapFile *map) - { - m_shader.instanceAttach(); - m_map = map; - m_undoable_observer = GlobalUndoSystem().observer(this); - GlobalFilterSystem().registerFilterable(*this); - } - - void instanceDetach(MapFile *map) - { - GlobalFilterSystem().unregisterFilterable(*this); - m_undoable_observer = 0; - GlobalUndoSystem().release(this); - m_map = 0; - m_shader.instanceDetach(); - } - - void render(RenderStateFlags state) const - { - Winding_Draw(m_winding, m_planeTransformed.plane3().normal(), state); - } - - void updateFiltered() - { - m_filtered = face_filtered(*this); - } - - bool isFiltered() const - { - return m_filtered; - } - - void undoSave() - { - if (m_map != 0) { - m_map->changed(); - } - if (m_undoable_observer != 0) { - m_undoable_observer->save(this); - } - } +Face( FaceObserver* observer ) : + m_refcount( 0 ), + m_shader( texdef_name_default() ), + m_texdef( m_shader, TextureProjection(), false ), + m_filtered( false ), + m_observer( observer ), + m_undoable_observer( 0 ), + m_map( 0 ){ + m_shader.attach( *this ); + m_plane.copy( Vector3( 0, 0, 0 ), Vector3( 64, 0, 0 ), Vector3( 0, 64, 0 ) ); + m_texdef.setBasis( m_plane.plane3().normal() ); + planeChanged(); +} -// undoable - UndoMemento *exportState() const - { - return new SavedState(*this); - } - - void importState(const UndoMemento *data) - { - undoSave(); - - static_cast( data )->exportState(*this); - - planeChanged(); - m_observer->connectivityChanged(); - texdefChanged(); - m_observer->shaderChanged(); - updateFiltered(); - } - - void IncRef() - { - ++m_refcount; - } - - void DecRef() - { - if (--m_refcount == 0) { - delete this; - } - } - - void flipWinding() - { - m_plane.reverse(); - planeChanged(); - } - - bool intersectVolume(const VolumeTest &volume, const Matrix4 &localToWorld) const - { - return volume.TestPlane(Plane3(plane3().normal(), -plane3().dist()), localToWorld); - } - - void render(Renderer &renderer, const Matrix4 &localToWorld) const - { - renderer.SetState(m_shader.state(), Renderer::eFullMaterials); - renderer.addRenderable(*this, localToWorld); - } - - void transform(const Matrix4 &matrix, bool mirror) - { - if (g_brush_texturelock_enabled) { - Texdef_transformLocked(m_texdefTransformed, m_shader.width(), m_shader.height(), m_plane.plane3(), matrix); - } - - m_planeTransformed.transform(matrix, mirror); +Face( + const Vector3& p0, + const Vector3& p1, + const Vector3& p2, + const char* shader, + const TextureProjection& projection, + FaceObserver* observer + ) : + m_refcount( 0 ), + m_shader( shader ), + m_texdef( m_shader, projection ), + m_observer( observer ), + m_undoable_observer( 0 ), + m_map( 0 ){ + m_shader.attach( *this ); + m_plane.copy( p0, p1, p2 ); + m_texdef.setBasis( m_plane.plane3().normal() ); + planeChanged(); + updateFiltered(); +} -#if 0 - ASSERT_MESSAGE( projectionaxis_for_normal( normal ) == projectionaxis_for_normal( plane3().normal() ), "bleh" ); -#endif - m_observer->planeChanged(); +Face( const Face& other, FaceObserver* observer ) : + m_refcount( 0 ), + m_shader( other.m_shader.getShader(), other.m_shader.m_flags ), + m_texdef( m_shader, other.getTexdef().normalised() ), + m_observer( observer ), + m_undoable_observer( 0 ), + m_map( 0 ){ + m_shader.attach( *this ); + m_plane.copy( other.m_plane ); + planepts_assign( m_move_planepts, other.m_move_planepts ); + m_texdef.setBasis( m_plane.plane3().normal() ); + planeChanged(); + updateFiltered(); +} - if (g_brush_texturelock_enabled) { - Brush_textureChanged(); - } - } +~Face(){ + m_shader.detach( *this ); +} - void assign_planepts(const PlanePoints planepts) - { - m_planeTransformed.copy(planepts[0], planepts[1], planepts[2]); - m_observer->planeChanged(); - } +void planeChanged(){ + revertTransform(); + m_observer->planeChanged(); +} + +void realiseShader(){ + m_observer->shaderChanged(); +} + +void unrealiseShader(){ +} + +void instanceAttach( MapFile* map ){ + m_shader.instanceAttach(); + m_map = map; + m_undoable_observer = GlobalUndoSystem().observer( this ); + GlobalFilterSystem().registerFilterable( *this ); +} +void instanceDetach( MapFile* map ){ + GlobalFilterSystem().unregisterFilterable( *this ); + m_undoable_observer = 0; + GlobalUndoSystem().release( this ); + m_map = 0; + m_shader.instanceDetach(); +} + +void render( RenderStateFlags state ) const { + Winding_Draw( m_winding, m_planeTransformed.plane3().normal(), state ); +} + +void updateFiltered(){ + m_filtered = face_filtered( *this ); +} + +bool isFiltered() const { + return m_filtered; +} + +void undoSave(){ + if ( m_map != 0 ) { + m_map->changed(); + } + if ( m_undoable_observer != 0 ) { + m_undoable_observer->save( this ); + } +} + +// undoable +UndoMemento* exportState() const { + return new SavedState( *this ); +} + +void importState( const UndoMemento* data ){ + undoSave(); + + static_cast( data )->exportState( *this ); + + planeChanged(); + m_observer->connectivityChanged(); + texdefChanged(); + m_observer->shaderChanged(); + updateFiltered(); +} + +void IncRef(){ + ++m_refcount; +} + +void DecRef(){ + if ( --m_refcount == 0 ) { + delete this; + } +} + +void flipWinding(){ + m_plane.reverse(); + planeChanged(); +} + +bool intersectVolume( const VolumeTest& volume, const Matrix4& localToWorld ) const { + return volume.TestPlane( Plane3( plane3().normal(), -plane3().dist() ), localToWorld ); +} + +void render( Renderer& renderer, const Matrix4& localToWorld ) const { + renderer.SetState( m_shader.state(), Renderer::eFullMaterials ); + renderer.addRenderable( *this, localToWorld ); +} + +void transform( const Matrix4& matrix, bool mirror ){ + if ( g_brush_texturelock_enabled ) { + Texdef_transformLocked( m_texdefTransformed, m_shader.width(), m_shader.height(), m_plane.plane3(), matrix ); + } + + m_planeTransformed.transform( matrix, mirror ); + +#if 0 + ASSERT_MESSAGE( projectionaxis_for_normal( normal ) == projectionaxis_for_normal( plane3().normal() ), "bleh" ); +#endif + m_observer->planeChanged(); + + if ( g_brush_texturelock_enabled ) { + Brush_textureChanged(); + } +} + +void assign_planepts( const PlanePoints planepts ){ + m_planeTransformed.copy( planepts[0], planepts[1], planepts[2] ); + m_observer->planeChanged(); +} /// \brief Reverts the transformable state of the brush to identity. - void revertTransform() - { - m_planeTransformed = m_plane; - planepts_assign(m_move_planeptsTransformed, m_move_planepts); - m_texdefTransformed = m_texdef.m_projection; - } - - void freezeTransform() - { - undoSave(); - m_plane = m_planeTransformed; - planepts_assign(m_move_planepts, m_move_planeptsTransformed); - m_texdef.m_projection = m_texdefTransformed; - } - - void update_move_planepts_vertex(std::size_t index, PlanePoints planePoints) - { - std::size_t numpoints = getWinding().numpoints; - ASSERT_MESSAGE(index < numpoints, "update_move_planepts_vertex: invalid index"); - - std::size_t opposite = Winding_Opposite(getWinding(), index); - std::size_t adjacent = Winding_wrap(getWinding(), opposite + numpoints - 1); - planePoints[0] = getWinding()[opposite].vertex; - planePoints[1] = getWinding()[index].vertex; - planePoints[2] = getWinding()[adjacent].vertex; - // winding points are very inaccurate, so they must be quantised before using them to generate the face-plane - planepts_quantise(planePoints, GRID_MIN); - } - - void snapto(float snap) - { - if (contributes()) { +void revertTransform(){ + m_planeTransformed = m_plane; + planepts_assign( m_move_planeptsTransformed, m_move_planepts ); + m_texdefTransformed = m_texdef.m_projection; +} + +void freezeTransform(){ + undoSave(); + m_plane = m_planeTransformed; + planepts_assign( m_move_planepts, m_move_planeptsTransformed ); + m_texdef.m_projection = m_texdefTransformed; +} + +void update_move_planepts_vertex( std::size_t index, PlanePoints planePoints ){ + std::size_t numpoints = getWinding().numpoints; + ASSERT_MESSAGE( index < numpoints, "update_move_planepts_vertex: invalid index" ); + + std::size_t opposite = Winding_Opposite( getWinding(), index ); + std::size_t adjacent = Winding_wrap( getWinding(), opposite + numpoints - 1 ); + planePoints[0] = getWinding()[opposite].vertex; + planePoints[1] = getWinding()[index].vertex; + planePoints[2] = getWinding()[adjacent].vertex; + // winding points are very inaccurate, so they must be quantised before using them to generate the face-plane + planepts_quantise( planePoints, GRID_MIN ); +} + +void snapto( float snap ){ + if ( contributes() ) { #if 0 - ASSERT_MESSAGE( plane3_valid( m_plane.plane3() ), "invalid plane before snap to grid" ); + ASSERT_MESSAGE( plane3_valid( m_plane.plane3() ), "invalid plane before snap to grid" ); planepts_snap( m_plane.planePoints(), snap ); ASSERT_MESSAGE( plane3_valid( m_plane.plane3() ), "invalid plane after snap to grid" ); #else - PlanePoints planePoints; - update_move_planepts_vertex(0, planePoints); - vector3_snap(planePoints[0], snap); - vector3_snap(planePoints[1], snap); - vector3_snap(planePoints[2], snap); - assign_planepts(planePoints); - freezeTransform(); + PlanePoints planePoints; + update_move_planepts_vertex( 0, planePoints ); + vector3_snap( planePoints[0], snap ); + vector3_snap( planePoints[1], snap ); + vector3_snap( planePoints[2], snap ); + assign_planepts( planePoints ); + freezeTransform(); #endif - SceneChangeNotify(); - if (!plane3_valid(m_plane.plane3())) { - globalErrorStream() << "WARNING: invalid plane after snap to grid\n"; - } - } - } - - void testSelect(SelectionTest &test, SelectionIntersection &best) - { - Winding_testSelect(m_winding, test, best); - } - - void testSelect_centroid(SelectionTest &test, SelectionIntersection &best) - { - test.TestPoint(m_centroid, best); - } - - void shaderChanged() - { - EmitTextureCoordinates(); - Brush_textureChanged(); - m_observer->shaderChanged(); - updateFiltered(); - planeChanged(); - SceneChangeNotify(); - } - - const char *GetShader() const - { - return m_shader.getShader(); - } - - void SetShader(const char *name) - { - undoSave(); - m_shader.setShader(name); - shaderChanged(); - } - - void revertTexdef() - { - m_texdefTransformed = m_texdef.m_projection; - } - - void texdefChanged() - { - revertTexdef(); - EmitTextureCoordinates(); - Brush_textureChanged(); - } - - void GetTexdef(TextureProjection &projection) const - { - projection = m_texdef.normalised(); - } - - void SetTexdef(const TextureProjection &projection) - { - undoSave(); - m_texdef.setTexdef(projection); - texdefChanged(); - } - - void GetFlags(ContentsFlagsValue &flags) const - { - flags = m_shader.getFlags(); - } - - void SetFlags(const ContentsFlagsValue &flags) - { - undoSave(); - m_shader.setFlags(flags); - m_observer->shaderChanged(); - updateFiltered(); - } - - void ShiftTexdef(float s, float t) - { - undoSave(); - m_texdef.shift(s, t); - texdefChanged(); - } - - void ScaleTexdef(float s, float t) - { - undoSave(); - m_texdef.scale(s, t); - texdefChanged(); - } - - void RotateTexdef(float angle) - { - undoSave(); - m_texdef.rotate(angle); - texdefChanged(); - } - - void FitTexture(float s_repeat, float t_repeat) - { - undoSave(); - m_texdef.fit(m_plane.plane3().normal(), m_winding, s_repeat, t_repeat); - texdefChanged(); - } - - void EmitTextureCoordinates() - { - Texdef_EmitTextureCoordinates(m_texdefTransformed, m_shader.width(), m_shader.height(), m_winding, - plane3().normal(), g_matrix4_identity); - } - - - const Vector3 ¢roid() const - { - return m_centroid; - } - - void construct_centroid() - { - Winding_Centroid(m_winding, plane3(), m_centroid); - } - - const Winding &getWinding() const - { - return m_winding; - } - - Winding &getWinding() - { - return m_winding; - } - - const Plane3 &plane3() const - { - m_observer->evaluateTransform(); - return m_planeTransformed.plane3(); - } - - FacePlane &getPlane() - { - return m_plane; - } - - const FacePlane &getPlane() const - { - return m_plane; - } - - FaceTexdef &getTexdef() - { - return m_texdef; - } - - const FaceTexdef &getTexdef() const - { - return m_texdef; - } - - FaceShader &getShader() - { - return m_shader; - } - - const FaceShader &getShader() const - { - return m_shader; - } - - bool isDetail() const - { - return (m_shader.m_flags.m_contentFlags & BRUSH_DETAIL_MASK) != 0; - } - - void setDetail(bool detail) - { - undoSave(); - if (detail && !isDetail()) { - m_shader.m_flags.m_contentFlags |= BRUSH_DETAIL_MASK; - } else if (!detail && isDetail()) { - m_shader.m_flags.m_contentFlags &= ~BRUSH_DETAIL_MASK; - } - m_observer->shaderChanged(); - } - - bool contributes() const - { - return m_winding.numpoints > 2; - } - - bool is_bounded() const - { - for (Winding::const_iterator i = m_winding.begin(); i != m_winding.end(); ++i) { - if ((*i).adjacent == c_brush_maxFaces) { - return false; - } - } - return true; - } + SceneChangeNotify(); + if ( !plane3_valid( m_plane.plane3() ) ) { + globalErrorStream() << "WARNING: invalid plane after snap to grid\n"; + } + } +} + +void testSelect( SelectionTest& test, SelectionIntersection& best ){ + Winding_testSelect( m_winding, test, best ); +} + +void testSelect_centroid( SelectionTest& test, SelectionIntersection& best ){ + test.TestPoint( m_centroid, best ); +} + +void shaderChanged(){ + EmitTextureCoordinates(); + Brush_textureChanged(); + m_observer->shaderChanged(); + updateFiltered(); + planeChanged(); + SceneChangeNotify(); +} + +const char* GetShader() const { + return m_shader.getShader(); +} + +void SetShader( const char* name ){ + undoSave(); + m_shader.setShader( name ); + shaderChanged(); +} + +void revertTexdef(){ + m_texdefTransformed = m_texdef.m_projection; +} + +void texdefChanged(){ + revertTexdef(); + EmitTextureCoordinates(); + Brush_textureChanged(); +} + +void GetTexdef( TextureProjection& projection ) const { + projection = m_texdef.normalised(); +} + +void SetTexdef( const TextureProjection& projection ){ + undoSave(); + m_texdef.setTexdef( projection ); + texdefChanged(); +} + +void GetFlags( ContentsFlagsValue& flags ) const { + flags = m_shader.getFlags(); +} + +void SetFlags( const ContentsFlagsValue& flags ){ + undoSave(); + m_shader.setFlags( flags ); + m_observer->shaderChanged(); + updateFiltered(); +} + +void ShiftTexdef( float s, float t ){ + undoSave(); + m_texdef.shift( s, t ); + texdefChanged(); +} + +void ScaleTexdef( float s, float t ){ + undoSave(); + m_texdef.scale( s, t ); + texdefChanged(); +} + +void RotateTexdef( float angle ){ + undoSave(); + m_texdef.rotate( angle ); + texdefChanged(); +} + +void FitTexture( float s_repeat, float t_repeat ){ + undoSave(); + m_texdef.fit( m_plane.plane3().normal(), m_winding, s_repeat, t_repeat ); + texdefChanged(); +} + +void EmitTextureCoordinates(){ + Texdef_EmitTextureCoordinates( m_texdefTransformed, m_shader.width(), m_shader.height(), m_winding, plane3().normal(), g_matrix4_identity ); +} + + +const Vector3& centroid() const { + return m_centroid; +} + +void construct_centroid(){ + Winding_Centroid( m_winding, plane3(), m_centroid ); +} + +const Winding& getWinding() const { + return m_winding; +} + +Winding& getWinding(){ + return m_winding; +} + +const Plane3& plane3() const { + m_observer->evaluateTransform(); + return m_planeTransformed.plane3(); +} + +FacePlane& getPlane(){ + return m_plane; +} + +const FacePlane& getPlane() const { + return m_plane; +} + +FaceTexdef& getTexdef(){ + return m_texdef; +} + +const FaceTexdef& getTexdef() const { + return m_texdef; +} + +FaceShader& getShader(){ + return m_shader; +} + +const FaceShader& getShader() const { + return m_shader; +} + +bool isDetail() const { + return ( m_shader.m_flags.m_contentFlags & BRUSH_DETAIL_MASK ) != 0; +} + +void setDetail( bool detail ){ + undoSave(); + if ( detail && !isDetail() ) { + m_shader.m_flags.m_contentFlags |= BRUSH_DETAIL_MASK; + } + else if ( !detail && isDetail() ) { + m_shader.m_flags.m_contentFlags &= ~BRUSH_DETAIL_MASK; + } + m_observer->shaderChanged(); +} + +bool contributes() const { + return m_winding.numpoints > 2; +} + +bool is_bounded() const { + for ( Winding::const_iterator i = m_winding.begin(); i != m_winding.end(); ++i ) + { + if ( ( *i ).adjacent == c_brush_maxFaces ) { + return false; + } + } + return true; +} }; -class FaceVertexId { - std::size_t m_face; - std::size_t m_vertex; +class FaceVertexId +{ +std::size_t m_face; +std::size_t m_vertex; public: - FaceVertexId(std::size_t face, std::size_t vertex) - : m_face(face), m_vertex(vertex) - { - } - - std::size_t getFace() const - { - return m_face; - } - - std::size_t getVertex() const - { - return m_vertex; - } +FaceVertexId( std::size_t face, std::size_t vertex ) + : m_face( face ), m_vertex( vertex ){ +} + +std::size_t getFace() const { + return m_face; +} + +std::size_t getVertex() const { + return m_vertex; +} }; typedef std::size_t faceIndex_t; -struct EdgeRenderIndices { - RenderIndex first; - RenderIndex second; +struct EdgeRenderIndices +{ + RenderIndex first; + RenderIndex second; - EdgeRenderIndices() - : first(0), second(0) - { - } + EdgeRenderIndices() + : first( 0 ), second( 0 ){ + } - EdgeRenderIndices(const RenderIndex _first, const RenderIndex _second) - : first(_first), second(_second) - { - } + EdgeRenderIndices( const RenderIndex _first, const RenderIndex _second ) + : first( _first ), second( _second ){ + } }; -struct EdgeFaces { - faceIndex_t first; - faceIndex_t second; +struct EdgeFaces +{ + faceIndex_t first; + faceIndex_t second; - EdgeFaces() - : first(c_brush_maxFaces), second(c_brush_maxFaces) - { - } + EdgeFaces() + : first( c_brush_maxFaces ), second( c_brush_maxFaces ){ + } - EdgeFaces(const faceIndex_t _first, const faceIndex_t _second) - : first(_first), second(_second) - { - } + EdgeFaces( const faceIndex_t _first, const faceIndex_t _second ) + : first( _first ), second( _second ){ + } }; -class RenderableWireframe : public OpenGLRenderable { +class RenderableWireframe : public OpenGLRenderable +{ public: - void render(RenderStateFlags state) const - { +void render( RenderStateFlags state ) const { #if 1 - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &m_vertices->colour); - glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &m_vertices->vertex); - glDrawElements(GL_LINES, GLsizei(m_size << 1), RenderIndexTypeID, m_faceVertex.data()); + glColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( PointVertex ), &m_vertices->colour ); + glVertexPointer( 3, GL_FLOAT, sizeof( PointVertex ), &m_vertices->vertex ); + glDrawElements( GL_LINES, GLsizei( m_size << 1 ), RenderIndexTypeID, m_faceVertex.data() ); #else - glBegin( GL_LINES ); + glBegin( GL_LINES ); for ( std::size_t i = 0; i < m_size; ++i ) { glVertex3fv( &m_vertices[m_faceVertex[i].first].vertex.x ); @@ -1483,2581 +1376,2457 @@ public: } glEnd(); #endif - } +} - Array m_faceVertex; - std::size_t m_size; - const PointVertex *m_vertices; +Array m_faceVertex; +std::size_t m_size; +const PointVertex* m_vertices; }; class Brush; -typedef std::vector brush_vector_t; +typedef std::vector brush_vector_t; -class BrushFilter { +class BrushFilter +{ public: - virtual bool filter(const Brush &brush) const = 0; +virtual bool filter( const Brush& brush ) const = 0; }; -bool brush_filtered(Brush &brush); +bool brush_filtered( Brush& brush ); -void add_brush_filter(BrushFilter &filter, int mask, bool invert = false); +void add_brush_filter( BrushFilter& filter, int mask, bool invert = false ); /// \brief Returns true if 'self' takes priority when building brush b-rep. -inline bool plane3_inside(const Plane3 &self, const Plane3 &other, bool selfIsLater) -{ - if (vector3_equal_epsilon(self.normal(), other.normal(), 0.001)) { - // same plane? prefer the one with smaller index - if (self.dist() == other.dist()) { - return selfIsLater; - } - return self.dist() < other.dist(); - } - return true; +inline bool plane3_inside( const Plane3& self, const Plane3& other, bool selfIsLater ){ + if ( vector3_equal_epsilon( self.normal(), other.normal(), 0.001 ) ) { + // same plane? prefer the one with smaller index + if ( self.dist() == other.dist() ) { + return selfIsLater; + } + return self.dist() < other.dist(); + } + return true; } typedef SmartPointer FaceSmartPointer; typedef std::vector Faces; /// \brief Returns the unique-id of the edge adjacent to \p faceVertex in the edge-pair for the set of \p faces. -inline FaceVertexId next_edge(const Faces &faces, FaceVertexId faceVertex) -{ - std::size_t adjacent_face = faces[faceVertex.getFace()]->getWinding()[faceVertex.getVertex()].adjacent; - std::size_t adjacent_vertex = Winding_FindAdjacent(faces[adjacent_face]->getWinding(), faceVertex.getFace()); +inline FaceVertexId next_edge( const Faces& faces, FaceVertexId faceVertex ){ + std::size_t adjacent_face = faces[faceVertex.getFace()]->getWinding()[faceVertex.getVertex()].adjacent; + std::size_t adjacent_vertex = Winding_FindAdjacent( faces[adjacent_face]->getWinding(), faceVertex.getFace() ); - ASSERT_MESSAGE(adjacent_vertex != c_brush_maxFaces, "connectivity data invalid"); - if (adjacent_vertex == c_brush_maxFaces) { - return faceVertex; - } + ASSERT_MESSAGE( adjacent_vertex != c_brush_maxFaces, "connectivity data invalid" ); + if ( adjacent_vertex == c_brush_maxFaces ) { + return faceVertex; + } - return FaceVertexId(adjacent_face, adjacent_vertex); + return FaceVertexId( adjacent_face, adjacent_vertex ); } /// \brief Returns the unique-id of the vertex adjacent to \p faceVertex in the vertex-ring for the set of \p faces. -inline FaceVertexId next_vertex(const Faces &faces, FaceVertexId faceVertex) -{ - FaceVertexId nextEdge = next_edge(faces, faceVertex); - return FaceVertexId(nextEdge.getFace(), - Winding_next(faces[nextEdge.getFace()]->getWinding(), nextEdge.getVertex())); +inline FaceVertexId next_vertex( const Faces& faces, FaceVertexId faceVertex ){ + FaceVertexId nextEdge = next_edge( faces, faceVertex ); + return FaceVertexId( nextEdge.getFace(), Winding_next( faces[nextEdge.getFace()]->getWinding(), nextEdge.getVertex() ) ); } -class SelectableEdge { - Vector3 getEdge() const - { - const Winding &winding = getFace().getWinding(); - return vector3_mid(winding[m_faceVertex.getVertex()].vertex, - winding[Winding_next(winding, m_faceVertex.getVertex())].vertex); - } +class SelectableEdge +{ +Vector3 getEdge() const { + const Winding& winding = getFace().getWinding(); + return vector3_mid( winding[m_faceVertex.getVertex()].vertex, winding[Winding_next( winding, m_faceVertex.getVertex() )].vertex ); +} public: - Faces &m_faces; - FaceVertexId m_faceVertex; - - SelectableEdge(Faces &faces, FaceVertexId faceVertex) - : m_faces(faces), m_faceVertex(faceVertex) - { - } - - SelectableEdge &operator=(const SelectableEdge &other) - { - m_faceVertex = other.m_faceVertex; - return *this; - } - - Face &getFace() const - { - return *m_faces[m_faceVertex.getFace()]; - } - - void testSelect(SelectionTest &test, SelectionIntersection &best) - { - test.TestPoint(getEdge(), best); - } +Faces& m_faces; +FaceVertexId m_faceVertex; + +SelectableEdge( Faces& faces, FaceVertexId faceVertex ) + : m_faces( faces ), m_faceVertex( faceVertex ){ +} + +SelectableEdge& operator=( const SelectableEdge& other ){ + m_faceVertex = other.m_faceVertex; + return *this; +} + +Face& getFace() const { + return *m_faces[m_faceVertex.getFace()]; +} + +void testSelect( SelectionTest& test, SelectionIntersection& best ){ + test.TestPoint( getEdge(), best ); +} }; -class SelectableVertex { - Vector3 getVertex() const - { - return getFace().getWinding()[m_faceVertex.getVertex()].vertex; - } +class SelectableVertex +{ +Vector3 getVertex() const { + return getFace().getWinding()[m_faceVertex.getVertex()].vertex; +} public: - Faces &m_faces; - FaceVertexId m_faceVertex; - - SelectableVertex(Faces &faces, FaceVertexId faceVertex) - : m_faces(faces), m_faceVertex(faceVertex) - { - } - - SelectableVertex &operator=(const SelectableVertex &other) - { - m_faceVertex = other.m_faceVertex; - return *this; - } - - Face &getFace() const - { - return *m_faces[m_faceVertex.getFace()]; - } - - void testSelect(SelectionTest &test, SelectionIntersection &best) - { - test.TestPoint(getVertex(), best); - } +Faces& m_faces; +FaceVertexId m_faceVertex; + +SelectableVertex( Faces& faces, FaceVertexId faceVertex ) + : m_faces( faces ), m_faceVertex( faceVertex ){ +} + +SelectableVertex& operator=( const SelectableVertex& other ){ + m_faceVertex = other.m_faceVertex; + return *this; +} + +Face& getFace() const { + return *m_faces[m_faceVertex.getFace()]; +} + +void testSelect( SelectionTest& test, SelectionIntersection& best ){ + test.TestPoint( getVertex(), best ); +} }; -class BrushObserver { +class BrushObserver +{ public: - virtual void reserve(std::size_t size) = 0; +virtual void reserve( std::size_t size ) = 0; - virtual void clear() = 0; +virtual void clear() = 0; - virtual void push_back(Face &face) = 0; +virtual void push_back( Face& face ) = 0; - virtual void pop_back() = 0; +virtual void pop_back() = 0; - virtual void erase(std::size_t index) = 0; +virtual void erase( std::size_t index ) = 0; - virtual void connectivityChanged() = 0; +virtual void connectivityChanged() = 0; - virtual void edge_clear() = 0; +virtual void edge_clear() = 0; - virtual void edge_push_back(SelectableEdge &edge) = 0; +virtual void edge_push_back( SelectableEdge& edge ) = 0; - virtual void vertex_clear() = 0; +virtual void vertex_clear() = 0; - virtual void vertex_push_back(SelectableVertex &vertex) = 0; +virtual void vertex_push_back( SelectableVertex& vertex ) = 0; - virtual void DEBUG_verify() const = 0; +virtual void DEBUG_verify() const = 0; }; -class BrushVisitor { +class BrushVisitor +{ public: - virtual void visit(Face &face) const = 0; +virtual void visit( Face& face ) const = 0; }; class Brush : - public TransformNode, - public Bounded, - public Cullable, - public Snappable, - public Undoable, - public FaceObserver, - public Filterable, - public Nameable, - public BrushDoom3 { + public TransformNode, + public Bounded, + public Cullable, + public Snappable, + public Undoable, + public FaceObserver, + public Filterable, + public Nameable, + public BrushDoom3 +{ private: - scene::Node *m_node; - typedef UniqueSet Observers; - Observers m_observers; - UndoObserver *m_undoable_observer; - MapFile *m_map; +scene::Node* m_node; +typedef UniqueSet Observers; +Observers m_observers; +UndoObserver* m_undoable_observer; +MapFile* m_map; // state - Faces m_faces; +Faces m_faces; // ---- // cached data compiled from state - Array m_faceCentroidPoints; - RenderablePointArray m_render_faces; +Array m_faceCentroidPoints; +RenderablePointArray m_render_faces; + +Array m_uniqueVertexPoints; +typedef std::vector SelectableVertices; +SelectableVertices m_select_vertices; +RenderablePointArray m_render_vertices; + +Array m_uniqueEdgePoints; +typedef std::vector SelectableEdges; +SelectableEdges m_select_edges; +RenderablePointArray m_render_edges; + +Array m_edge_indices; +Array m_edge_faces; + +AABB m_aabb_local; +// ---- + +Callback m_evaluateTransform; +Callback m_boundsChanged; + +mutable bool m_planeChanged; // b-rep evaluation required +mutable bool m_transformChanged; // transform evaluation required +// ---- + +public: +STRING_CONSTANT( Name, "Brush" ); + +Callback m_lightsChanged; + +// static data +static Shader* m_state_point; +// ---- + +static EBrushType m_type; +static double m_maxWorldCoord; + +Brush( scene::Node& node, const Callback& evaluateTransform, const Callback& boundsChanged ) : + m_node( &node ), + m_undoable_observer( 0 ), + m_map( 0 ), + m_render_faces( m_faceCentroidPoints, GL_POINTS ), + m_render_vertices( m_uniqueVertexPoints, GL_POINTS ), + m_render_edges( m_uniqueEdgePoints, GL_POINTS ), + m_evaluateTransform( evaluateTransform ), + m_boundsChanged( boundsChanged ), + m_planeChanged( false ), + m_transformChanged( false ){ + planeChanged(); +} +Brush( const Brush& other, scene::Node& node, const Callback& evaluateTransform, const Callback& boundsChanged ) : + m_node( &node ), + m_undoable_observer( 0 ), + m_map( 0 ), + m_render_faces( m_faceCentroidPoints, GL_POINTS ), + m_render_vertices( m_uniqueVertexPoints, GL_POINTS ), + m_render_edges( m_uniqueEdgePoints, GL_POINTS ), + m_evaluateTransform( evaluateTransform ), + m_boundsChanged( boundsChanged ), + m_planeChanged( false ), + m_transformChanged( false ){ + copy( other ); +} + +Brush( const Brush& other ) : + TransformNode( other ), + Bounded( other ), + Cullable( other ), + Snappable(), + Undoable( other ), + FaceObserver( other ), + Filterable( other ), + Nameable( other ), + BrushDoom3( other ), + m_node( 0 ), + m_undoable_observer( 0 ), + m_map( 0 ), + m_render_faces( m_faceCentroidPoints, GL_POINTS ), + m_render_vertices( m_uniqueVertexPoints, GL_POINTS ), + m_render_edges( m_uniqueEdgePoints, GL_POINTS ), + m_planeChanged( false ), + m_transformChanged( false ){ + copy( other ); +} + +~Brush(){ + ASSERT_MESSAGE( m_observers.empty(), "Brush::~Brush: observers still attached" ); +} + +// assignment not supported +Brush& operator=( const Brush& other ); + +void setDoom3GroupOrigin( const Vector3& origin ){ + //globalOutputStream() << "func_static origin before: " << m_funcStaticOrigin << " after: " << origin << "\n"; + for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) + { + ( *i )->getPlane().m_funcStaticOrigin = origin; + ( *i )->getPlane().updateTranslated(); + ( *i )->planeChanged(); + } + planeChanged(); +} + +void attach( BrushObserver& observer ){ + for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) + { + observer.push_back( *( *i ) ); + } + + for ( SelectableEdges::iterator i = m_select_edges.begin(); i != m_select_edges.end(); ++i ) + { + observer.edge_push_back( *i ); + } + + for ( SelectableVertices::iterator i = m_select_vertices.begin(); i != m_select_vertices.end(); ++i ) + { + observer.vertex_push_back( *i ); + } + + m_observers.insert( &observer ); +} + +void detach( BrushObserver& observer ){ + m_observers.erase( &observer ); +} + +void forEachFace( const BrushVisitor& visitor ) const { + for ( Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i ) + { + visitor.visit( *( *i ) ); + } +} + +void forEachFace_instanceAttach( MapFile* map ) const { + for ( Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i ) + { + ( *i )->instanceAttach( map ); + } +} + +void forEachFace_instanceDetach( MapFile* map ) const { + for ( Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i ) + { + ( *i )->instanceDetach( map ); + } +} + +InstanceCounter m_instanceCounter; + +void instanceAttach( const scene::Path& path ){ + if ( ++m_instanceCounter.m_count == 1 ) { + m_map = path_find_mapfile( path.begin(), path.end() ); + m_undoable_observer = GlobalUndoSystem().observer( this ); + GlobalFilterSystem().registerFilterable( *this ); + forEachFace_instanceAttach( m_map ); + } + else + { + ASSERT_MESSAGE( path_find_mapfile( path.begin(), path.end() ) == m_map, "node is instanced across more than one file" ); + } +} + +void instanceDetach( const scene::Path& path ){ + if ( --m_instanceCounter.m_count == 0 ) { + forEachFace_instanceDetach( m_map ); + GlobalFilterSystem().unregisterFilterable( *this ); + m_map = 0; + m_undoable_observer = 0; + GlobalUndoSystem().release( this ); + } +} + +// nameable +const char* name() const { + return "brush"; +} + +void attach( const NameCallback& callback ){ +} + +void detach( const NameCallback& callback ){ +} + +// filterable +void updateFiltered(){ + if ( m_node != 0 ) { + if ( brush_filtered( *this ) ) { + m_node->enable( scene::Node::eFiltered ); + } + else + { + m_node->disable( scene::Node::eFiltered ); + } + } +} + +// observer +void planeChanged(){ + m_planeChanged = true; + aabbChanged(); + m_lightsChanged(); +} + +void shaderChanged(){ + updateFiltered(); + planeChanged(); +} + +void evaluateBRep() const { + if ( m_planeChanged ) { + m_planeChanged = false; + const_cast( this )->buildBRep(); + } +} + +void transformChanged(){ + m_transformChanged = true; + planeChanged(); +} + +typedef MemberCaller TransformChangedCaller; + +void evaluateTransform(){ + if ( m_transformChanged ) { + m_transformChanged = false; + revertTransform(); + m_evaluateTransform(); + } +} - Array m_uniqueVertexPoints; - typedef std::vector SelectableVertices; - SelectableVertices m_select_vertices; - RenderablePointArray m_render_vertices; +const Matrix4& localToParent() const { + return g_matrix4_identity; +} + +void aabbChanged(){ + m_boundsChanged(); +} + +const AABB& localAABB() const { + evaluateBRep(); + return m_aabb_local; +} + +VolumeIntersectionValue intersectVolume( const VolumeTest& test, const Matrix4& localToWorld ) const { + return test.TestAABB( m_aabb_local, localToWorld ); +} + +void renderComponents( SelectionSystem::EComponentMode mode, Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { + switch ( mode ) + { + case SelectionSystem::eVertex: + renderer.addRenderable( m_render_vertices, localToWorld ); + break; + case SelectionSystem::eEdge: + renderer.addRenderable( m_render_edges, localToWorld ); + break; + case SelectionSystem::eFace: + renderer.addRenderable( m_render_faces, localToWorld ); + break; + default: + break; + } +} + +void transform( const Matrix4& matrix ){ + bool mirror = matrix4_handedness( matrix ) == MATRIX4_LEFTHANDED; + + for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) + { + ( *i )->transform( matrix, mirror ); + } +} + +void snapto( float snap ){ + for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) + { + ( *i )->snapto( snap ); + } +} + +void revertTransform(){ + for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) + { + ( *i )->revertTransform(); + } +} + +void freezeTransform(){ + for ( Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i ) + { + ( *i )->freezeTransform(); + } +} + +/// \brief Returns the absolute index of the \p faceVertex. +std::size_t absoluteIndex( FaceVertexId faceVertex ){ + std::size_t index = 0; + for ( std::size_t i = 0; i < faceVertex.getFace(); ++i ) + { + index += m_faces[i]->getWinding().numpoints; + } + return index + faceVertex.getVertex(); +} + +void appendFaces( const Faces& other ){ + clear(); + for ( Faces::const_iterator i = other.begin(); i != other.end(); ++i ) + { + push_back( *i ); + } +} + +/// \brief The undo memento for a brush stores only the list of face references - the faces are not copied. +class BrushUndoMemento : public UndoMemento +{ +public: +BrushUndoMemento( const Faces& faces ) : m_faces( faces ){ +} + +void release(){ + delete this; +} + +Faces m_faces; +}; + +void undoSave(){ + if ( m_map != 0 ) { + m_map->changed(); + } + if ( m_undoable_observer != 0 ) { + m_undoable_observer->save( this ); + } +} + +UndoMemento* exportState() const { + return new BrushUndoMemento( m_faces ); +} + +void importState( const UndoMemento* state ){ + undoSave(); + appendFaces( static_cast( state )->m_faces ); + planeChanged(); + + for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) + { + ( *i )->DEBUG_verify(); + } +} + +bool isDetail(){ + return !m_faces.empty() && m_faces.front()->isDetail(); +} + +/// \brief Appends a copy of \p face to the end of the face list. +Face* addFace( const Face& face ){ + if ( m_faces.size() == c_brush_maxFaces ) { + return 0; + } + undoSave(); + push_back( FaceSmartPointer( new Face( face, this ) ) ); + m_faces.back()->setDetail( isDetail() ); + planeChanged(); + return m_faces.back(); +} + +/// \brief Appends a new face constructed from the parameters to the end of the face list. +Face* addPlane( const Vector3& p0, const Vector3& p1, const Vector3& p2, const char* shader, const TextureProjection& projection ){ + if ( m_faces.size() == c_brush_maxFaces ) { + return 0; + } + undoSave(); + push_back( FaceSmartPointer( new Face( p0, p1, p2, shader, projection, this ) ) ); + m_faces.back()->setDetail( isDetail() ); + planeChanged(); + return m_faces.back(); +} + +static void constructStatic( EBrushType type ){ + m_type = type; + Face::m_type = type; + FacePlane::m_type = type; + + g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_QUAKE; + if ( m_type == eBrushTypeQuake3BP || m_type == eBrushTypeDoom3 || m_type == eBrushTypeQuake4 ) { + g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_BRUSHPRIMITIVES; + // g_brush_texturelock_enabled = true; // bad idea, this overrides user setting + } + else if ( m_type == eBrushTypeHalfLife ) { + g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_HALFLIFE; + // g_brush_texturelock_enabled = true; // bad idea, this overrides user setting + } + + Face::m_quantise = ( m_type == eBrushTypeQuake ) ? quantiseInteger : quantiseFloating; + + m_state_point = GlobalShaderCache().capture( "$POINT" ); +} + +static void destroyStatic(){ + GlobalShaderCache().release( "$POINT" ); +} + +std::size_t DEBUG_size(){ + return m_faces.size(); +} + +typedef Faces::const_iterator const_iterator; + +const_iterator begin() const { + return m_faces.begin(); +} + +const_iterator end() const { + return m_faces.end(); +} + +Face* back(){ + return m_faces.back(); +} + +const Face* back() const { + return m_faces.back(); +} + +void reserve( std::size_t count ){ + m_faces.reserve( count ); + for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) + { + ( *i )->reserve( count ); + } +} + +void push_back( Faces::value_type face ){ + m_faces.push_back( face ); + if ( m_instanceCounter.m_count != 0 ) { + m_faces.back()->instanceAttach( m_map ); + } + for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) + { + ( *i )->push_back( *face ); + ( *i )->DEBUG_verify(); + } +} + +void pop_back(){ + if ( m_instanceCounter.m_count != 0 ) { + m_faces.back()->instanceDetach( m_map ); + } + m_faces.pop_back(); + for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) + { + ( *i )->pop_back(); + ( *i )->DEBUG_verify(); + } +} + +void erase( std::size_t index ){ + if ( m_instanceCounter.m_count != 0 ) { + m_faces[index]->instanceDetach( m_map ); + } + m_faces.erase( m_faces.begin() + index ); + for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) + { + ( *i )->erase( index ); + ( *i )->DEBUG_verify(); + } +} + +void connectivityChanged(){ + for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) + { + ( *i )->connectivityChanged(); + } +} + + +void clear(){ + undoSave(); + if ( m_instanceCounter.m_count != 0 ) { + forEachFace_instanceDetach( m_map ); + } + m_faces.clear(); + for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) + { + ( *i )->clear(); + ( *i )->DEBUG_verify(); + } +} + +std::size_t size() const { + return m_faces.size(); +} + +bool empty() const { + return m_faces.empty(); +} + +/// \brief Returns true if any face of the brush contributes to the final B-Rep. +bool hasContributingFaces() const { + for ( const_iterator i = begin(); i != end(); ++i ) + { + if ( ( *i )->contributes() ) { + return true; + } + } + return false; +} + +/// \brief Removes faces that do not contribute to the brush. This is useful for cleaning up after CSG operations on the brush. +/// Note: removal of empty faces is not performed during direct brush manipulations, because it would make a manipulation irreversible if it created an empty face. +void removeEmptyFaces(){ + evaluateBRep(); + + { + std::size_t i = 0; + while ( i < m_faces.size() ) + { + if ( !m_faces[i]->contributes() ) { + erase( i ); + planeChanged(); + } + else + { + ++i; + } + } + } +} + +/// \brief Constructs \p winding from the intersection of \p plane with the other planes of the brush. +void windingForClipPlane( Winding& winding, const Plane3& plane ) const { + FixedWinding buffer[2]; + bool swap = false; + + // get a poly that covers an effectively infinite area + Winding_createInfinite( buffer[swap], plane, m_maxWorldCoord + 1 ); + + // chop the poly by all of the other faces + { + for ( std::size_t i = 0; i < m_faces.size(); ++i ) + { + const Face& clip = *m_faces[i]; + + if ( plane3_equal( clip.plane3(), plane ) + || !plane3_valid( clip.plane3() ) || !plane_unique( i ) + || plane3_opposing( plane, clip.plane3() ) ) { + continue; + } + + buffer[!swap].clear(); + +#if BRUSH_CONNECTIVITY_DEBUG + globalOutputStream() << "clip vs face: " << i << "\n"; +#endif + + { + // flip the plane, because we want to keep the back side + Plane3 clipPlane( vector3_negated( clip.plane3().normal() ), -clip.plane3().dist() ); + Winding_Clip( buffer[swap], plane, clipPlane, i, buffer[!swap] ); + } + +#if BRUSH_CONNECTIVITY_DEBUG + for ( FixedWinding::Points::iterator k = buffer[!swap].points.begin(), j = buffer[!swap].points.end() - 1; k != buffer[!swap].points.end(); j = k, ++k ) + { + if ( vector3_length_squared( vector3_subtracted( ( *k ).vertex, ( *j ).vertex ) ) < 1 ) { + globalOutputStream() << "v: " << std::distance( buffer[!swap].points.begin(), j ) << " tiny edge adjacent to face " << ( *j ).adjacent << "\n"; + } + } +#endif + + //ASSERT_MESSAGE(buffer[!swap].numpoints != 1, "created single-point winding"); + + swap = !swap; + } + } + + Winding_forFixedWinding( winding, buffer[swap] ); + +#if BRUSH_CONNECTIVITY_DEBUG + Winding_printConnectivity( winding ); + + for ( Winding::iterator i = winding.begin(), j = winding.end() - 1; i != winding.end(); j = i, ++i ) + { + if ( vector3_length_squared( vector3_subtracted( ( *i ).vertex, ( *j ).vertex ) ) < 1 ) { + globalOutputStream() << "v: " << std::distance( winding.begin(), j ) << " tiny edge adjacent to face " << ( *j ).adjacent << "\n"; + } + } +#endif +} + +void update_wireframe( RenderableWireframe& wire, const bool* faces_visible ) const { + wire.m_faceVertex.resize( m_edge_indices.size() ); + wire.m_vertices = m_uniqueVertexPoints.data(); + wire.m_size = 0; + for ( std::size_t i = 0; i < m_edge_faces.size(); ++i ) + { + if ( faces_visible[m_edge_faces[i].first] + || faces_visible[m_edge_faces[i].second] ) { + wire.m_faceVertex[wire.m_size++] = m_edge_indices[i]; + } + } +} + + +void update_faces_wireframe( Array& wire, const bool* faces_visible ) const { + std::size_t count = 0; + for ( std::size_t i = 0; i < m_faceCentroidPoints.size(); ++i ) + { + if ( faces_visible[i] ) { + ++count; + } + } + + wire.resize( count ); + Array::iterator p = wire.begin(); + for ( std::size_t i = 0; i < m_faceCentroidPoints.size(); ++i ) + { + if ( faces_visible[i] ) { + *p++ = m_faceCentroidPoints[i]; + } + } +} + +/// \brief Makes this brush a deep-copy of the \p other. +void copy( const Brush& other ){ + for ( Faces::const_iterator i = other.m_faces.begin(); i != other.m_faces.end(); ++i ) + { + addFace( *( *i ) ); + } + planeChanged(); +} + +private: +void edge_push_back( FaceVertexId faceVertex ){ + m_select_edges.push_back( SelectableEdge( m_faces, faceVertex ) ); + for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) + { + ( *i )->edge_push_back( m_select_edges.back() ); + } +} + +void edge_clear(){ + m_select_edges.clear(); + for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) + { + ( *i )->edge_clear(); + } +} + +void vertex_push_back( FaceVertexId faceVertex ){ + m_select_vertices.push_back( SelectableVertex( m_faces, faceVertex ) ); + for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) + { + ( *i )->vertex_push_back( m_select_vertices.back() ); + } +} + +void vertex_clear(){ + m_select_vertices.clear(); + for ( Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i ) + { + ( *i )->vertex_clear(); + } +} + +/// \brief Returns true if the face identified by \p index is preceded by another plane that takes priority over it. +bool plane_unique( std::size_t index ) const { + // duplicate plane + for ( std::size_t i = 0; i < m_faces.size(); ++i ) + { + if ( index != i && !plane3_inside( m_faces[index]->plane3(), m_faces[i]->plane3(), index < i ) ) { + return false; + } + } + return true; +} + +/// \brief Removes edges that are smaller than the tolerance used when generating brush windings. +void removeDegenerateEdges(){ + for ( std::size_t i = 0; i < m_faces.size(); ++i ) + { + Winding& winding = m_faces[i]->getWinding(); + for ( Winding::iterator j = winding.begin(); j != winding.end(); ) + { + std::size_t index = std::distance( winding.begin(), j ); + std::size_t next = Winding_next( winding, index ); + if ( Edge_isDegenerate( winding[index].vertex, winding[next].vertex ) ) { +#if BRUSH_DEGENERATE_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << i << ": degenerate edge adjacent to " << winding[index].adjacent << "\n"; +#endif + Winding& other = m_faces[winding[index].adjacent]->getWinding(); + std::size_t adjacent = Winding_FindAdjacent( other, i ); + if ( adjacent != c_brush_maxFaces ) { + other.erase( other.begin() + adjacent ); + } + winding.erase( j ); + } + else + { + ++j; + } + } + } +} + +/// \brief Invalidates faces that have only two vertices in their winding, while preserving edge-connectivity information. +void removeDegenerateFaces(){ + // save adjacency info for degenerate faces + for ( std::size_t i = 0; i < m_faces.size(); ++i ) + { + Winding& degen = m_faces[i]->getWinding(); + + if ( degen.numpoints == 2 ) { +#if BRUSH_DEGENERATE_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << i << ": degenerate winding adjacent to " << degen[0].adjacent << ", " << degen[1].adjacent << "\n"; +#endif + // this is an "edge" face, where the plane touches the edge of the brush + { + Winding& winding = m_faces[degen[0].adjacent]->getWinding(); + std::size_t index = Winding_FindAdjacent( winding, i ); + if ( index != c_brush_maxFaces ) { +#if BRUSH_DEGENERATE_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << degen[0].adjacent << ": remapping adjacent " << winding[index].adjacent << " to " << degen[1].adjacent << "\n"; +#endif + winding[index].adjacent = degen[1].adjacent; + } + } + + { + Winding& winding = m_faces[degen[1].adjacent]->getWinding(); + std::size_t index = Winding_FindAdjacent( winding, i ); + if ( index != c_brush_maxFaces ) { +#if BRUSH_DEGENERATE_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << degen[1].adjacent << ": remapping adjacent " << winding[index].adjacent << " to " << degen[0].adjacent << "\n"; +#endif + winding[index].adjacent = degen[0].adjacent; + } + } + + degen.resize( 0 ); + } + } +} + +/// \brief Removes edges that have the same adjacent-face as their immediate neighbour. +void removeDuplicateEdges(){ + // verify face connectivity graph + for ( std::size_t i = 0; i < m_faces.size(); ++i ) + { + //if(m_faces[i]->contributes()) + { + Winding& winding = m_faces[i]->getWinding(); + for ( std::size_t j = 0; j != winding.numpoints; ) + { + std::size_t next = Winding_next( winding, j ); + if ( winding[j].adjacent == winding[next].adjacent ) { +#if BRUSH_DEGENERATE_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << i << ": removed duplicate edge adjacent to face " << winding[j].adjacent << "\n"; +#endif + winding.erase( winding.begin() + next ); + } + else + { + ++j; + } + } + } + } +} + +/// \brief Removes edges that do not have a matching pair in their adjacent-face. +void verifyConnectivityGraph(){ + // verify face connectivity graph + for ( std::size_t i = 0; i < m_faces.size(); ++i ) + { + //if(m_faces[i]->contributes()) + { + Winding& winding = m_faces[i]->getWinding(); + for ( Winding::iterator j = winding.begin(); j != winding.end(); ) + { +#if BRUSH_CONNECTIVITY_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << i << ": adjacent to face " << ( *j ).adjacent << "\n"; +#endif + // remove unidirectional graph edges + if ( ( *j ).adjacent == c_brush_maxFaces + || Winding_FindAdjacent( m_faces[( *j ).adjacent]->getWinding(), i ) == c_brush_maxFaces ) { +#if BRUSH_CONNECTIVITY_DEBUG + globalOutputStream() << "Brush::buildWindings: face " << i << ": removing unidirectional connectivity graph edge adjacent to face " << ( *j ).adjacent << "\n"; +#endif + winding.erase( j ); + } + else + { + ++j; + } + } + } + } +} + +/// \brief Returns true if the brush is a finite volume. A brush without a finite volume extends past the maximum world bounds and is not valid. +bool isBounded(){ + for ( const_iterator i = begin(); i != end(); ++i ) + { + if ( !( *i )->is_bounded() ) { + return false; + } + } + return true; +} + +/// \brief Constructs the polygon windings for each face of the brush. Also updates the brush bounding-box and face texture-coordinates. +bool buildWindings(){ + + { + m_aabb_local = AABB(); + + for ( std::size_t i = 0; i < m_faces.size(); ++i ) + { + Face& f = *m_faces[i]; + + if ( !plane3_valid( f.plane3() ) || !plane_unique( i ) ) { + f.getWinding().resize( 0 ); + } + else + { +#if BRUSH_CONNECTIVITY_DEBUG + globalOutputStream() << "face: " << i << "\n"; +#endif + windingForClipPlane( f.getWinding(), f.plane3() ); + + // update brush bounds + const Winding& winding = f.getWinding(); + for ( Winding::const_iterator i = winding.begin(); i != winding.end(); ++i ) + { + aabb_extend_by_point_safe( m_aabb_local, ( *i ).vertex ); + } + + // update texture coordinates + f.EmitTextureCoordinates(); + } + } + } + + bool degenerate = !isBounded(); + + if ( !degenerate ) { + // clean up connectivity information. + // these cleanups must be applied in a specific order. + removeDegenerateEdges(); + removeDegenerateFaces(); + removeDuplicateEdges(); + verifyConnectivityGraph(); + } + + return degenerate; +} + +/// \brief Constructs the face windings and updates anything that depends on them. +void buildBRep(); +}; + + +class FaceInstance; + +class FaceInstanceSet +{ +typedef SelectionList FaceInstances; +FaceInstances m_faceInstances; +public: +void insert( FaceInstance& faceInstance ){ + m_faceInstances.append( faceInstance ); +} + +void erase( FaceInstance& faceInstance ){ + m_faceInstances.erase( faceInstance ); +} + +template +void foreach( Functor functor ){ + for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + functor( *( *i ) ); + } +} + +bool empty() const { + return m_faceInstances.empty(); +} + +FaceInstance& last() const { + return m_faceInstances.back(); +} +}; + +extern FaceInstanceSet g_SelectedFaceInstances; + +typedef std::list VertexSelection; + +inline VertexSelection::iterator VertexSelection_find( VertexSelection& self, std::size_t value ){ + return std::find( self.begin(), self.end(), value ); +} + +inline VertexSelection::const_iterator VertexSelection_find( const VertexSelection& self, std::size_t value ){ + return std::find( self.begin(), self.end(), value ); +} + +inline VertexSelection::iterator VertexSelection_insert( VertexSelection& self, std::size_t value ){ + VertexSelection::iterator i = VertexSelection_find( self, value ); + if ( i == self.end() ) { + self.push_back( value ); + return --self.end(); + } + return i; +} + +inline void VertexSelection_erase( VertexSelection& self, std::size_t value ){ + VertexSelection::iterator i = VertexSelection_find( self, value ); + if ( i != self.end() ) { + self.erase( i ); + } +} + +inline bool triangle_reversed( std::size_t x, std::size_t y, std::size_t z ){ + return !( ( x < y && y < z ) || ( z < x && x < y ) || ( y < z && z < x ) ); +} + +template +inline Vector3 triangle_cross( const BasicVector3& x, const BasicVector3 y, const BasicVector3& z ){ + return vector3_cross( y - x, z - x ); +} + +template +inline bool triangles_same_winding( const BasicVector3& x1, const BasicVector3 y1, const BasicVector3& z1, const BasicVector3& x2, const BasicVector3 y2, const BasicVector3& z2 ){ + return vector3_dot( triangle_cross( x1, y1, z1 ), triangle_cross( x2, y2, z2 ) ) > 0; +} + + +typedef const Plane3* PlanePointer; +typedef PlanePointer* PlanesIterator; + +class VectorLightList : public LightList +{ +typedef std::vector Lights; +Lights m_lights; +public: +void addLight( const RendererLight& light ){ + m_lights.push_back( &light ); +} + +void clear(){ + m_lights.clear(); +} + +void evaluateLights() const { +} + +void lightsChanged() const { +} + +void forEachLight( const RendererLightCallback& callback ) const { + for ( Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i ) + { + callback( *( *i ) ); + } +} +}; + +class FaceInstance +{ +Face* m_face; +ObservedSelectable m_selectable; +ObservedSelectable m_selectableVertices; +ObservedSelectable m_selectableEdges; +SelectionChangeCallback m_selectionChanged; + +VertexSelection m_vertexSelection; +VertexSelection m_edgeSelection; + +public: +mutable VectorLightList m_lights; + +FaceInstance( Face& face, const SelectionChangeCallback& observer ) : + m_face( &face ), + m_selectable( SelectedChangedCaller( *this ) ), + m_selectableVertices( observer ), + m_selectableEdges( observer ), + m_selectionChanged( observer ){ +} + +FaceInstance( const FaceInstance& other ) : + m_face( other.m_face ), + m_selectable( SelectedChangedCaller( *this ) ), + m_selectableVertices( other.m_selectableVertices ), + m_selectableEdges( other.m_selectableEdges ), + m_selectionChanged( other.m_selectionChanged ){ +} + +FaceInstance& operator=( const FaceInstance& other ){ + m_face = other.m_face; + return *this; +} + +Face& getFace(){ + return *m_face; +} + +const Face& getFace() const { + return *m_face; +} + +void selectedChanged( const Selectable& selectable ){ + if ( selectable.isSelected() ) { + g_SelectedFaceInstances.insert( *this ); + } + else + { + g_SelectedFaceInstances.erase( *this ); + } + m_selectionChanged( selectable ); +} + +typedef MemberCaller SelectedChangedCaller; + +bool selectedVertices() const { + return !m_vertexSelection.empty(); +} + +bool selectedEdges() const { + return !m_edgeSelection.empty(); +} + +bool isSelected() const { + return m_selectable.isSelected(); +} + +bool selectedComponents() const { + return selectedVertices() || selectedEdges() || isSelected(); +} + +bool selectedComponents( SelectionSystem::EComponentMode mode ) const { + switch ( mode ) + { + case SelectionSystem::eVertex: + return selectedVertices(); + case SelectionSystem::eEdge: + return selectedEdges(); + case SelectionSystem::eFace: + return isSelected(); + default: + return false; + } +} + +void setSelected( SelectionSystem::EComponentMode mode, bool select ){ + switch ( mode ) + { + case SelectionSystem::eFace: + m_selectable.setSelected( select ); + break; + case SelectionSystem::eVertex: + ASSERT_MESSAGE( !select, "select-all not supported" ); + + m_vertexSelection.clear(); + m_selectableVertices.setSelected( false ); + break; + case SelectionSystem::eEdge: + ASSERT_MESSAGE( !select, "select-all not supported" ); + + m_edgeSelection.clear(); + m_selectableEdges.setSelected( false ); + break; + default: + break; + } +} + +template +void SelectedVertices_foreach( Functor functor ) const { + for ( VertexSelection::const_iterator i = m_vertexSelection.begin(); i != m_vertexSelection.end(); ++i ) + { + std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *i ); + if ( index != c_brush_maxFaces ) { + functor( getFace().getWinding()[index].vertex ); + } + } +} + +template +void SelectedEdges_foreach( Functor functor ) const { + for ( VertexSelection::const_iterator i = m_edgeSelection.begin(); i != m_edgeSelection.end(); ++i ) + { + std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *i ); + if ( index != c_brush_maxFaces ) { + const Winding& winding = getFace().getWinding(); + std::size_t adjacent = Winding_next( winding, index ); + functor( vector3_mid( winding[index].vertex, winding[adjacent].vertex ) ); + } + } +} + +template +void SelectedFaces_foreach( Functor functor ) const { + if ( isSelected() ) { + functor( centroid() ); + } +} + +template +void SelectedComponents_foreach( Functor functor ) const { + SelectedVertices_foreach( functor ); + SelectedEdges_foreach( functor ); + SelectedFaces_foreach( functor ); +} + +void iterate_selected( AABB& aabb ) const { + SelectedComponents_foreach([&](const Vector3 &point) { + aabb_extend_by_point_safe(aabb, point); + }); +} + +void iterate_selected( RenderablePointVector& points ) const { + SelectedComponents_foreach([&](const Vector3 &point) { + const Colour4b colour_selected(0, 0, 255, 255); + points.push_back(pointvertex_for_windingpoint(point, colour_selected)); + }); +} + +bool intersectVolume( const VolumeTest& volume, const Matrix4& localToWorld ) const { + return m_face->intersectVolume( volume, localToWorld ); +} + +void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { + if ( !m_face->isFiltered() && m_face->contributes() && intersectVolume( volume, localToWorld ) ) { + renderer.PushState(); + if ( selectedComponents() ) { + renderer.Highlight( Renderer::eFace ); + } + m_face->render( renderer, localToWorld ); + renderer.PopState(); + } +} + +void testSelect( SelectionTest& test, SelectionIntersection& best ){ + if ( !m_face->isFiltered() ) { + m_face->testSelect( test, best ); + } +} + +void testSelect( Selector& selector, SelectionTest& test ){ + SelectionIntersection best; + testSelect( test, best ); + if ( best.valid() ) { + Selector_add( selector, m_selectable, best ); + } +} + +void testSelect_centroid( Selector& selector, SelectionTest& test ){ + if ( m_face->contributes() && !m_face->isFiltered() ) { + SelectionIntersection best; + m_face->testSelect_centroid( test, best ); + if ( best.valid() ) { + Selector_add( selector, m_selectable, best ); + } + } +} + +void selectPlane( Selector& selector, const Line& line, PlanesIterator first, PlanesIterator last, const PlaneCallback& selectedPlaneCallback ){ + for ( Winding::const_iterator i = getFace().getWinding().begin(); i != getFace().getWinding().end(); ++i ) + { + Vector3 v( vector3_subtracted( line_closest_point( line, ( *i ).vertex ), ( *i ).vertex ) ); + double dot = vector3_dot( getFace().plane3().normal(), v ); + if ( dot <= 0 ) { + return; + } + } + + Selector_add( selector, m_selectable ); + + selectedPlaneCallback( getFace().plane3() ); +} + +void selectReversedPlane( Selector& selector, const SelectedPlanes& selectedPlanes ){ + if ( selectedPlanes.contains( plane3_flipped( getFace().plane3() ) ) ) { + Selector_add( selector, m_selectable ); + } +} + +void transformComponents( const Matrix4& matrix ){ + if ( isSelected() ) { + m_face->transform( matrix, false ); + } + if ( selectedVertices() ) { + if ( m_vertexSelection.size() == 1 ) { + matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] ); + m_face->assign_planepts( m_face->m_move_planeptsTransformed ); + } + else if ( m_vertexSelection.size() == 2 ) { + matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] ); + matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[2] ); + m_face->assign_planepts( m_face->m_move_planeptsTransformed ); + } + else if ( m_vertexSelection.size() >= 3 ) { + matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[0] ); + matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] ); + matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[2] ); + m_face->assign_planepts( m_face->m_move_planeptsTransformed ); + } + } + if ( selectedEdges() ) { + if ( m_edgeSelection.size() == 1 ) { + matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[0] ); + matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] ); + m_face->assign_planepts( m_face->m_move_planeptsTransformed ); + } + else if ( m_edgeSelection.size() >= 2 ) { + matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[0] ); + matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[1] ); + matrix4_transform_point( matrix, m_face->m_move_planeptsTransformed[2] ); + m_face->assign_planepts( m_face->m_move_planeptsTransformed ); + } + } +} + +void snapto( float snap ){ + m_face->snapto( snap ); +} + +void snapComponents( float snap ){ + if ( isSelected() ) { + snapto( snap ); + } + if ( selectedVertices() ) { + vector3_snap( m_face->m_move_planepts[0], snap ); + vector3_snap( m_face->m_move_planepts[1], snap ); + vector3_snap( m_face->m_move_planepts[2], snap ); + m_face->assign_planepts( m_face->m_move_planepts ); + planepts_assign( m_face->m_move_planeptsTransformed, m_face->m_move_planepts ); + m_face->freezeTransform(); + } + if ( selectedEdges() ) { + vector3_snap( m_face->m_move_planepts[0], snap ); + vector3_snap( m_face->m_move_planepts[1], snap ); + vector3_snap( m_face->m_move_planepts[2], snap ); + m_face->assign_planepts( m_face->m_move_planepts ); + planepts_assign( m_face->m_move_planeptsTransformed, m_face->m_move_planepts ); + m_face->freezeTransform(); + } +} + +void update_move_planepts_vertex( std::size_t index ){ + m_face->update_move_planepts_vertex( index, m_face->m_move_planepts ); +} + +void update_move_planepts_vertex2( std::size_t index, std::size_t other ){ + const std::size_t numpoints = m_face->getWinding().numpoints; + ASSERT_MESSAGE( index < numpoints, "select_vertex: invalid index" ); + + const std::size_t opposite = Winding_Opposite( m_face->getWinding(), index, other ); + + if ( triangle_reversed( index, other, opposite ) ) { + std::swap( index, other ); + } + + ASSERT_MESSAGE( + triangles_same_winding( + m_face->getWinding()[opposite].vertex, + m_face->getWinding()[index].vertex, + m_face->getWinding()[other].vertex, + m_face->getWinding()[0].vertex, + m_face->getWinding()[1].vertex, + m_face->getWinding()[2].vertex + ), + "update_move_planepts_vertex2: error" + ); + + m_face->m_move_planepts[0] = m_face->getWinding()[opposite].vertex; + m_face->m_move_planepts[1] = m_face->getWinding()[index].vertex; + m_face->m_move_planepts[2] = m_face->getWinding()[other].vertex; + planepts_quantise( m_face->m_move_planepts, GRID_MIN ); // winding points are very inaccurate +} + +void update_selection_vertex(){ + if ( m_vertexSelection.size() == 0 ) { + m_selectableVertices.setSelected( false ); + } + else + { + m_selectableVertices.setSelected( true ); + + if ( m_vertexSelection.size() == 1 ) { + std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *m_vertexSelection.begin() ); + + if ( index != c_brush_maxFaces ) { + update_move_planepts_vertex( index ); + } + } + else if ( m_vertexSelection.size() == 2 ) { + std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *m_vertexSelection.begin() ); + std::size_t other = Winding_FindAdjacent( getFace().getWinding(), *( ++m_vertexSelection.begin() ) ); + + if ( index != c_brush_maxFaces + && other != c_brush_maxFaces ) { + update_move_planepts_vertex2( index, other ); + } + } + } +} + +void select_vertex( std::size_t index, bool select ){ + if ( select ) { + VertexSelection_insert( m_vertexSelection, getFace().getWinding()[index].adjacent ); + } + else + { + VertexSelection_erase( m_vertexSelection, getFace().getWinding()[index].adjacent ); + } + + SceneChangeNotify(); + update_selection_vertex(); +} + +bool selected_vertex( std::size_t index ) const { + return VertexSelection_find( m_vertexSelection, getFace().getWinding()[index].adjacent ) != m_vertexSelection.end(); +} + +void update_move_planepts_edge( std::size_t index ){ + std::size_t numpoints = m_face->getWinding().numpoints; + ASSERT_MESSAGE( index < numpoints, "select_edge: invalid index" ); + + std::size_t adjacent = Winding_next( m_face->getWinding(), index ); + std::size_t opposite = Winding_Opposite( m_face->getWinding(), index ); + m_face->m_move_planepts[0] = m_face->getWinding()[index].vertex; + m_face->m_move_planepts[1] = m_face->getWinding()[adjacent].vertex; + m_face->m_move_planepts[2] = m_face->getWinding()[opposite].vertex; + planepts_quantise( m_face->m_move_planepts, GRID_MIN ); // winding points are very inaccurate +} + +void update_selection_edge(){ + if ( m_edgeSelection.size() == 0 ) { + m_selectableEdges.setSelected( false ); + } + else + { + m_selectableEdges.setSelected( true ); + + if ( m_edgeSelection.size() == 1 ) { + std::size_t index = Winding_FindAdjacent( getFace().getWinding(), *m_edgeSelection.begin() ); + + if ( index != c_brush_maxFaces ) { + update_move_planepts_edge( index ); + } + } + } +} + +void select_edge( std::size_t index, bool select ){ + if ( select ) { + VertexSelection_insert( m_edgeSelection, getFace().getWinding()[index].adjacent ); + } + else + { + VertexSelection_erase( m_edgeSelection, getFace().getWinding()[index].adjacent ); + } + + SceneChangeNotify(); + update_selection_edge(); +} + +bool selected_edge( std::size_t index ) const { + return VertexSelection_find( m_edgeSelection, getFace().getWinding()[index].adjacent ) != m_edgeSelection.end(); +} + +const Vector3& centroid() const { + return m_face->centroid(); +} + +void connectivityChanged(){ + // This occurs when a face is added or removed. + // The current vertex and edge selections no longer valid and must be cleared. + m_vertexSelection.clear(); + m_selectableVertices.setSelected( false ); + m_edgeSelection.clear(); + m_selectableEdges.setSelected( false ); +} +}; + +class BrushClipPlane : public OpenGLRenderable +{ +Plane3 m_plane; +Winding m_winding; +static Shader* m_state; +public: +static void constructStatic(){ + m_state = GlobalShaderCache().capture( "$CLIPPER_OVERLAY" ); +} + +static void destroyStatic(){ + GlobalShaderCache().release( "$CLIPPER_OVERLAY" ); +} + +void setPlane( const Brush& brush, const Plane3& plane ){ + m_plane = plane; + if ( plane3_valid( m_plane ) ) { + brush.windingForClipPlane( m_winding, m_plane ); + } + else + { + m_winding.resize( 0 ); + } +} + +void render( RenderStateFlags state ) const { + if ( ( state & RENDER_FILL ) != 0 ) { + Winding_Draw( m_winding, m_plane.normal(), state ); + } + else + { + Winding_DrawWireframe( m_winding ); + + // also draw a line indicating the direction of the cut + Vector3 lineverts[2]; + Winding_Centroid( m_winding, m_plane, lineverts[0] ); + lineverts[1] = vector3_added( lineverts[0], vector3_scaled( m_plane.normal(), Brush::m_maxWorldCoord * 4 ) ); + + glVertexPointer( 3, GL_FLOAT, sizeof( Vector3 ), &lineverts[0] ); + glDrawArrays( GL_LINES, 0, GLsizei( 2 ) ); + } +} + +void render( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { + renderer.SetState( m_state, Renderer::eWireframeOnly ); + renderer.SetState( m_state, Renderer::eFullMaterials ); + renderer.addRenderable( *this, localToWorld ); +} +}; + +inline void Face_addLight( const FaceInstance& face, const Matrix4& localToWorld, const RendererLight& light ){ + const Plane3& facePlane = face.getFace().plane3(); + const Vector3& origin = light.aabb().origin; + Plane3 tmp( plane3_transformed( Plane3( facePlane.normal(), -facePlane.dist() ), localToWorld ) ); + if ( !plane3_test_point( tmp, origin ) + || !plane3_test_point( tmp, vector3_added( origin, light.offset() ) ) ) { + face.m_lights.addLight( light ); + } +} + + +typedef std::vector FaceInstances; + +class EdgeInstance : public Selectable +{ +FaceInstances& m_faceInstances; +SelectableEdge* m_edge; + +void select_edge( bool select ){ + FaceVertexId faceVertex = m_edge->m_faceVertex; + m_faceInstances[faceVertex.getFace()].select_edge( faceVertex.getVertex(), select ); + faceVertex = next_edge( m_edge->m_faces, faceVertex ); + m_faceInstances[faceVertex.getFace()].select_edge( faceVertex.getVertex(), select ); +} + +bool selected_edge() const { + FaceVertexId faceVertex = m_edge->m_faceVertex; + if ( !m_faceInstances[faceVertex.getFace()].selected_edge( faceVertex.getVertex() ) ) { + return false; + } + faceVertex = next_edge( m_edge->m_faces, faceVertex ); + if ( !m_faceInstances[faceVertex.getFace()].selected_edge( faceVertex.getVertex() ) ) { + return false; + } + + return true; +} + +public: +EdgeInstance( FaceInstances& faceInstances, SelectableEdge& edge ) + : m_faceInstances( faceInstances ), m_edge( &edge ){ +} +EdgeInstance& operator=( const EdgeInstance& other ){ + m_edge = other.m_edge; + return *this; +} + +void setSelected( bool select ){ + select_edge( select ); +} + +bool isSelected() const { + return selected_edge(); +} + + +void testSelect( Selector& selector, SelectionTest& test ){ + SelectionIntersection best; + m_edge->testSelect( test, best ); + if ( best.valid() ) { + Selector_add( selector, *this, best ); + } +} +}; + +class VertexInstance : public Selectable +{ +FaceInstances& m_faceInstances; +SelectableVertex* m_vertex; + +void select_vertex( bool select ){ + FaceVertexId faceVertex = m_vertex->m_faceVertex; + do + { + m_faceInstances[faceVertex.getFace()].select_vertex( faceVertex.getVertex(), select ); + faceVertex = next_vertex( m_vertex->m_faces, faceVertex ); + } + while ( faceVertex.getFace() != m_vertex->m_faceVertex.getFace() ); +} + +bool selected_vertex() const { + FaceVertexId faceVertex = m_vertex->m_faceVertex; + do + { + if ( !m_faceInstances[faceVertex.getFace()].selected_vertex( faceVertex.getVertex() ) ) { + return false; + } + faceVertex = next_vertex( m_vertex->m_faces, faceVertex ); + } + while ( faceVertex.getFace() != m_vertex->m_faceVertex.getFace() ); + return true; +} + +public: +VertexInstance( FaceInstances& faceInstances, SelectableVertex& vertex ) + : m_faceInstances( faceInstances ), m_vertex( &vertex ){ +} +VertexInstance& operator=( const VertexInstance& other ){ + m_vertex = other.m_vertex; + return *this; +} + +void setSelected( bool select ){ + select_vertex( select ); +} + +bool isSelected() const { + return selected_vertex(); +} + +void testSelect( Selector& selector, SelectionTest& test ){ + SelectionIntersection best; + m_vertex->testSelect( test, best ); + if ( best.valid() ) { + Selector_add( selector, *this, best ); + } +} +}; + +class BrushInstanceVisitor +{ +public: +virtual void visit( FaceInstance& face ) const = 0; +}; + +class BrushInstance : + public BrushObserver, + public scene::Instance, + public Selectable, + public Renderable, + public SelectionTestable, + public ComponentSelectionTestable, + public ComponentEditable, + public ComponentSnappable, + public PlaneSelectable, + public LightCullable +{ +class TypeCasts +{ +InstanceTypeCastTable m_casts; +public: +TypeCasts(){ + InstanceStaticCast::install( m_casts ); + InstanceContainedCast::install( m_casts ); + InstanceContainedCast::install( m_casts ); + InstanceStaticCast::install( m_casts ); + InstanceStaticCast::install( m_casts ); + InstanceStaticCast::install( m_casts ); + InstanceStaticCast::install( m_casts ); + InstanceStaticCast::install( m_casts ); + InstanceStaticCast::install( m_casts ); + InstanceIdentityCast::install( m_casts ); + InstanceContainedCast::install( m_casts ); +} + +InstanceTypeCastTable& get(){ + return m_casts; +} +}; + + +Brush& m_brush; + +FaceInstances m_faceInstances; + +typedef std::vector EdgeInstances; +EdgeInstances m_edgeInstances; +typedef std::vector VertexInstances; +VertexInstances m_vertexInstances; + +ObservedSelectable m_selectable; + +mutable RenderableWireframe m_render_wireframe; +mutable RenderablePointVector m_render_selected; +mutable AABB m_aabb_component; +mutable Array m_faceCentroidPointsCulled; +RenderablePointArray m_render_faces_wireframe; +mutable bool m_viewChanged; // requires re-evaluation of view-dependent cached data + +BrushClipPlane m_clipPlane; + +static Shader* m_state_selpoint; + +const LightList* m_lightList; + +TransformModifier m_transform; + +BrushInstance( const BrushInstance& other ); // NOT COPYABLE +BrushInstance& operator=( const BrushInstance& other ); // NOT ASSIGNABLE +public: +static Counter* m_counter; + +typedef LazyStatic StaticTypeCasts; + +void lightsChanged(){ + m_lightList->lightsChanged(); +} + +typedef MemberCaller LightsChangedCaller; + +STRING_CONSTANT( Name, "BrushInstance" ); + +BrushInstance( const scene::Path& path, scene::Instance* parent, Brush& brush ) : + Instance( path, parent, this, StaticTypeCasts::instance().get() ), + m_brush( brush ), + m_selectable( SelectedChangedCaller( *this ) ), + m_render_selected( GL_POINTS ), + m_render_faces_wireframe( m_faceCentroidPointsCulled, GL_POINTS ), + m_viewChanged( false ), + m_transform( Brush::TransformChangedCaller( m_brush ), ApplyTransformCaller( *this ) ){ + m_brush.instanceAttach( Instance::path() ); + m_brush.attach( *this ); + m_counter->increment(); + + m_lightList = &GlobalShaderCache().attach( *this ); + m_brush.m_lightsChanged = LightsChangedCaller( *this ); ///\todo Make this work with instancing. + + Instance::setTransformChangedCallback( LightsChangedCaller( *this ) ); +} - Array m_uniqueEdgePoints; - typedef std::vector SelectableEdges; - SelectableEdges m_select_edges; - RenderablePointArray m_render_edges; +~BrushInstance(){ + Instance::setTransformChangedCallback( Callback() ); - Array m_edge_indices; - Array m_edge_faces; + m_brush.m_lightsChanged = Callback(); + GlobalShaderCache().detach( *this ); - AABB m_aabb_local; -// ---- + m_counter->decrement(); + m_brush.detach( *this ); + m_brush.instanceDetach( Instance::path() ); +} - Callback m_evaluateTransform; - Callback m_boundsChanged; +Brush& getBrush(){ + return m_brush; +} +const Brush& getBrush() const { + return m_brush; +} - mutable bool m_planeChanged; // b-rep evaluation required - mutable bool m_transformChanged; // transform evaluation required -// ---- +Bounded& get( NullType){ + return m_brush; +} -public: - STRING_CONSTANT(Name, "Brush"); +Cullable& get( NullType){ + return m_brush; +} - Callback m_lightsChanged; +Transformable& get( NullType){ + return m_transform; +} -// static data - static Shader *m_state_point; -// ---- +void selectedChanged( const Selectable& selectable ){ + GlobalSelectionSystem().getObserver ( SelectionSystem::ePrimitive )( selectable ); + GlobalSelectionSystem().onSelectedChanged( *this, selectable ); - static EBrushType m_type; - static double m_maxWorldCoord; - - Brush(scene::Node &node, const Callback &evaluateTransform, const Callback &boundsChanged) : - m_node(&node), - m_undoable_observer(0), - m_map(0), - m_render_faces(m_faceCentroidPoints, GL_POINTS), - m_render_vertices(m_uniqueVertexPoints, GL_POINTS), - m_render_edges(m_uniqueEdgePoints, GL_POINTS), - m_evaluateTransform(evaluateTransform), - m_boundsChanged(boundsChanged), - m_planeChanged(false), - m_transformChanged(false) - { - planeChanged(); - } - - Brush(const Brush &other, scene::Node &node, const Callback &evaluateTransform, - const Callback &boundsChanged) : - m_node(&node), - m_undoable_observer(0), - m_map(0), - m_render_faces(m_faceCentroidPoints, GL_POINTS), - m_render_vertices(m_uniqueVertexPoints, GL_POINTS), - m_render_edges(m_uniqueEdgePoints, GL_POINTS), - m_evaluateTransform(evaluateTransform), - m_boundsChanged(boundsChanged), - m_planeChanged(false), - m_transformChanged(false) - { - copy(other); - } - - Brush(const Brush &other) : - TransformNode(other), - Bounded(other), - Cullable(other), - Snappable(), - Undoable(other), - FaceObserver(other), - Filterable(other), - Nameable(other), - BrushDoom3(other), - m_node(0), - m_undoable_observer(0), - m_map(0), - m_render_faces(m_faceCentroidPoints, GL_POINTS), - m_render_vertices(m_uniqueVertexPoints, GL_POINTS), - m_render_edges(m_uniqueEdgePoints, GL_POINTS), - m_planeChanged(false), - m_transformChanged(false) - { - copy(other); - } - - ~Brush() - { - ASSERT_MESSAGE(m_observers.empty(), "Brush::~Brush: observers still attached"); - } + Instance::selectedChanged(); +} +typedef MemberCaller SelectedChangedCaller; -// assignment not supported - Brush &operator=(const Brush &other); - - void setDoom3GroupOrigin(const Vector3 &origin) - { - //globalOutputStream() << "func_static origin before: " << m_funcStaticOrigin << " after: " << origin << "\n"; - for (Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i) { - (*i)->getPlane().m_funcStaticOrigin = origin; - (*i)->getPlane().updateTranslated(); - (*i)->planeChanged(); - } - planeChanged(); - } - - void attach(BrushObserver &observer) - { - for (Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i) { - observer.push_back(*(*i)); - } - - for (SelectableEdges::iterator i = m_select_edges.begin(); i != m_select_edges.end(); ++i) { - observer.edge_push_back(*i); - } - - for (SelectableVertices::iterator i = m_select_vertices.begin(); i != m_select_vertices.end(); ++i) { - observer.vertex_push_back(*i); - } - - m_observers.insert(&observer); - } - - void detach(BrushObserver &observer) - { - m_observers.erase(&observer); - } - - void forEachFace(const BrushVisitor &visitor) const - { - for (Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i) { - visitor.visit(*(*i)); - } - } - - void forEachFace_instanceAttach(MapFile *map) const - { - for (Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i) { - (*i)->instanceAttach(map); - } - } - - void forEachFace_instanceDetach(MapFile *map) const - { - for (Faces::const_iterator i = m_faces.begin(); i != m_faces.end(); ++i) { - (*i)->instanceDetach(map); - } - } - - InstanceCounter m_instanceCounter; - - void instanceAttach(const scene::Path &path) - { - if (++m_instanceCounter.m_count == 1) { - m_map = path_find_mapfile(path.begin(), path.end()); - m_undoable_observer = GlobalUndoSystem().observer(this); - GlobalFilterSystem().registerFilterable(*this); - forEachFace_instanceAttach(m_map); - } else { - ASSERT_MESSAGE(path_find_mapfile(path.begin(), path.end()) == m_map, - "node is instanced across more than one file"); - } - } - - void instanceDetach(const scene::Path &path) - { - if (--m_instanceCounter.m_count == 0) { - forEachFace_instanceDetach(m_map); - GlobalFilterSystem().unregisterFilterable(*this); - m_map = 0; - m_undoable_observer = 0; - GlobalUndoSystem().release(this); - } - } +void selectedChangedComponent( const Selectable& selectable ){ + GlobalSelectionSystem().getObserver ( SelectionSystem::eComponent )( selectable ); + GlobalSelectionSystem().onComponentSelection( *this, selectable ); +} +typedef MemberCaller SelectedChangedComponentCaller; -// nameable - const char *name() const - { - return "brush"; - } +const BrushInstanceVisitor& forEachFaceInstance( const BrushInstanceVisitor& visitor ){ + for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + visitor.visit( *i ); + } + return visitor; +} - void attach(const NameCallback &callback) - { - } +static void constructStatic(){ + m_state_selpoint = GlobalShaderCache().capture( "$SELPOINT" ); +} - void detach(const NameCallback &callback) - { - } +static void destroyStatic(){ + GlobalShaderCache().release( "$SELPOINT" ); +} -// filterable - void updateFiltered() - { - if (m_node != 0) { - if (brush_filtered(*this)) { - m_node->enable(scene::Node::eFiltered); - } else { - m_node->disable(scene::Node::eFiltered); - } - } - } +void clear(){ + m_faceInstances.clear(); +} -// observer - void planeChanged() - { - m_planeChanged = true; - aabbChanged(); - m_lightsChanged(); - } - - void shaderChanged() - { - updateFiltered(); - planeChanged(); - } - - void evaluateBRep() const - { - if (m_planeChanged) { - m_planeChanged = false; - const_cast( this )->buildBRep(); - } - } - - void transformChanged() - { - m_transformChanged = true; - planeChanged(); - } - - typedef MemberCaller TransformChangedCaller; - - void evaluateTransform() - { - if (m_transformChanged) { - m_transformChanged = false; - revertTransform(); - m_evaluateTransform(); - } - } - - const Matrix4 &localToParent() const - { - return g_matrix4_identity; - } - - void aabbChanged() - { - m_boundsChanged(); - } - - const AABB &localAABB() const - { - evaluateBRep(); - return m_aabb_local; - } - - VolumeIntersectionValue intersectVolume(const VolumeTest &test, const Matrix4 &localToWorld) const - { - return test.TestAABB(m_aabb_local, localToWorld); - } - - void renderComponents(SelectionSystem::EComponentMode mode, Renderer &renderer, const VolumeTest &volume, - const Matrix4 &localToWorld) const - { - switch (mode) { - case SelectionSystem::eVertex: - renderer.addRenderable(m_render_vertices, localToWorld); - break; - case SelectionSystem::eEdge: - renderer.addRenderable(m_render_edges, localToWorld); - break; - case SelectionSystem::eFace: - renderer.addRenderable(m_render_faces, localToWorld); - break; - default: - break; - } - } - - void transform(const Matrix4 &matrix) - { - bool mirror = matrix4_handedness(matrix) == MATRIX4_LEFTHANDED; - - for (Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i) { - (*i)->transform(matrix, mirror); - } - } - - void snapto(float snap) - { - for (Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i) { - (*i)->snapto(snap); - } - } - - void revertTransform() - { - for (Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i) { - (*i)->revertTransform(); - } - } - - void freezeTransform() - { - for (Faces::iterator i = m_faces.begin(); i != m_faces.end(); ++i) { - (*i)->freezeTransform(); - } - } +void reserve( std::size_t size ){ + m_faceInstances.reserve( size ); +} -/// \brief Returns the absolute index of the \p faceVertex. - std::size_t absoluteIndex(FaceVertexId faceVertex) - { - std::size_t index = 0; - for (std::size_t i = 0; i < faceVertex.getFace(); ++i) { - index += m_faces[i]->getWinding().numpoints; - } - return index + faceVertex.getVertex(); - } - - void appendFaces(const Faces &other) - { - clear(); - for (Faces::const_iterator i = other.begin(); i != other.end(); ++i) { - push_back(*i); - } - } +void push_back( Face& face ){ + m_faceInstances.push_back( FaceInstance( face, SelectedChangedComponentCaller( *this ) ) ); +} -/// \brief The undo memento for a brush stores only the list of face references - the faces are not copied. - class BrushUndoMemento : public UndoMemento { - public: - BrushUndoMemento(const Faces &faces) : m_faces(faces) - { - } - - void release() - { - delete this; - } - - Faces m_faces; - }; - - void undoSave() - { - if (m_map != 0) { - m_map->changed(); - } - if (m_undoable_observer != 0) { - m_undoable_observer->save(this); - } - } - - UndoMemento *exportState() const - { - return new BrushUndoMemento(m_faces); - } - - void importState(const UndoMemento *state) - { - undoSave(); - appendFaces(static_cast( state )->m_faces); - planeChanged(); - - for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { - (*i)->DEBUG_verify(); - } - } - - bool isDetail() - { - return !m_faces.empty() && m_faces.front()->isDetail(); - } +void pop_back(){ + ASSERT_MESSAGE( !m_faceInstances.empty(), "erasing invalid element" ); + m_faceInstances.pop_back(); +} -/// \brief Appends a copy of \p face to the end of the face list. - Face *addFace(const Face &face) - { - if (m_faces.size() == c_brush_maxFaces) { - return 0; - } - undoSave(); - push_back(FaceSmartPointer(new Face(face, this))); - m_faces.back()->setDetail(isDetail()); - planeChanged(); - return m_faces.back(); - } +void erase( std::size_t index ){ + ASSERT_MESSAGE( index < m_faceInstances.size(), "erasing invalid element" ); + m_faceInstances.erase( m_faceInstances.begin() + index ); +} -/// \brief Appends a new face constructed from the parameters to the end of the face list. - Face *addPlane(const Vector3 &p0, const Vector3 &p1, const Vector3 &p2, const char *shader, - const TextureProjection &projection) - { - if (m_faces.size() == c_brush_maxFaces) { - return 0; - } - undoSave(); - push_back(FaceSmartPointer(new Face(p0, p1, p2, shader, projection, this))); - m_faces.back()->setDetail(isDetail()); - planeChanged(); - return m_faces.back(); - } - - static void constructStatic(EBrushType type) - { - m_type = type; - Face::m_type = type; - FacePlane::m_type = type; - - g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_QUAKE; - if (m_type == eBrushTypeQuake3BP || m_type == eBrushTypeDoom3 || m_type == eBrushTypeQuake4) { - g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_BRUSHPRIMITIVES; - // g_brush_texturelock_enabled = true; // bad idea, this overrides user setting - } else if (m_type == eBrushTypeHalfLife) { - g_bp_globals.m_texdefTypeId = TEXDEFTYPEID_HALFLIFE; - // g_brush_texturelock_enabled = true; // bad idea, this overrides user setting - } - - Face::m_quantise = (m_type == eBrushTypeQuake) ? quantiseInteger : quantiseFloating; - - m_state_point = GlobalShaderCache().capture("$POINT"); - } - - static void destroyStatic() - { - GlobalShaderCache().release("$POINT"); - } - - std::size_t DEBUG_size() - { - return m_faces.size(); - } - - typedef Faces::const_iterator const_iterator; - - const_iterator begin() const - { - return m_faces.begin(); - } - - const_iterator end() const - { - return m_faces.end(); - } - - Face *back() - { - return m_faces.back(); - } - - const Face *back() const - { - return m_faces.back(); - } - - void reserve(std::size_t count) - { - m_faces.reserve(count); - for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { - (*i)->reserve(count); - } - } - - void push_back(Faces::value_type face) - { - m_faces.push_back(face); - if (m_instanceCounter.m_count != 0) { - m_faces.back()->instanceAttach(m_map); - } - for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { - (*i)->push_back(*face); - (*i)->DEBUG_verify(); - } - } - - void pop_back() - { - if (m_instanceCounter.m_count != 0) { - m_faces.back()->instanceDetach(m_map); - } - m_faces.pop_back(); - for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { - (*i)->pop_back(); - (*i)->DEBUG_verify(); - } - } - - void erase(std::size_t index) - { - if (m_instanceCounter.m_count != 0) { - m_faces[index]->instanceDetach(m_map); - } - m_faces.erase(m_faces.begin() + index); - for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { - (*i)->erase(index); - (*i)->DEBUG_verify(); - } - } - - void connectivityChanged() - { - for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { - (*i)->connectivityChanged(); - } - } - - - void clear() - { - undoSave(); - if (m_instanceCounter.m_count != 0) { - forEachFace_instanceDetach(m_map); - } - m_faces.clear(); - for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { - (*i)->clear(); - (*i)->DEBUG_verify(); - } - } - - std::size_t size() const - { - return m_faces.size(); - } - - bool empty() const - { - return m_faces.empty(); - } +void connectivityChanged(){ + for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + ( *i ).connectivityChanged(); + } +} -/// \brief Returns true if any face of the brush contributes to the final B-Rep. - bool hasContributingFaces() const - { - for (const_iterator i = begin(); i != end(); ++i) { - if ((*i)->contributes()) { - return true; - } - } - return false; - } +void edge_clear(){ + m_edgeInstances.clear(); +} -/// \brief Removes faces that do not contribute to the brush. This is useful for cleaning up after CSG operations on the brush. -/// Note: removal of empty faces is not performed during direct brush manipulations, because it would make a manipulation irreversible if it created an empty face. - void removeEmptyFaces() - { - evaluateBRep(); - - { - std::size_t i = 0; - while (i < m_faces.size()) { - if (!m_faces[i]->contributes()) { - erase(i); - planeChanged(); - } else { - ++i; - } - } - } - } +void edge_push_back( SelectableEdge& edge ){ + m_edgeInstances.push_back( EdgeInstance( m_faceInstances, edge ) ); +} -/// \brief Constructs \p winding from the intersection of \p plane with the other planes of the brush. - void windingForClipPlane(Winding &winding, const Plane3 &plane) const - { - FixedWinding buffer[2]; - bool swap = false; +void vertex_clear(){ + m_vertexInstances.clear(); +} - // get a poly that covers an effectively infinite area - Winding_createInfinite(buffer[swap], plane, m_maxWorldCoord + 1); +void vertex_push_back( SelectableVertex& vertex ){ + m_vertexInstances.push_back( VertexInstance( m_faceInstances, vertex ) ); +} - // chop the poly by all of the other faces - { - for (std::size_t i = 0; i < m_faces.size(); ++i) { - const Face &clip = *m_faces[i]; +void DEBUG_verify() const { + ASSERT_MESSAGE( m_faceInstances.size() == m_brush.DEBUG_size(), "FATAL: mismatch" ); +} - if (plane3_equal(clip.plane3(), plane) - || !plane3_valid(clip.plane3()) || !plane_unique(i) - || plane3_opposing(plane, clip.plane3())) { - continue; - } +bool isSelected() const { + return m_selectable.isSelected(); +} - buffer[!swap].clear(); +void setSelected( bool select ){ + m_selectable.setSelected( select ); +} -#if BRUSH_CONNECTIVITY_DEBUG - globalOutputStream() << "clip vs face: " << i << "\n"; -#endif +void update_selected() const { + m_render_selected.clear(); + for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + if ( ( *i ).getFace().contributes() ) { + ( *i ).iterate_selected( m_render_selected ); + } + } +} - { - // flip the plane, because we want to keep the back side - Plane3 clipPlane(vector3_negated(clip.plane3().normal()), -clip.plane3().dist()); - Winding_Clip(buffer[swap], plane, clipPlane, i, buffer[!swap]); - } +void evaluateViewDependent( const VolumeTest& volume, const Matrix4& localToWorld ) const { + if ( m_viewChanged ) { + m_viewChanged = false; -#if BRUSH_CONNECTIVITY_DEBUG - for ( FixedWinding::Points::iterator k = buffer[!swap].points.begin(), j = buffer[!swap].points.end() - 1; k != buffer[!swap].points.end(); j = k, ++k ) + bool faces_visible[c_brush_maxFaces]; + { + bool* j = faces_visible; + for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i, ++j ) { - if ( vector3_length_squared( vector3_subtracted( ( *k ).vertex, ( *j ).vertex ) ) < 1 ) { - globalOutputStream() << "v: " << std::distance( buffer[!swap].points.begin(), j ) << " tiny edge adjacent to face " << ( *j ).adjacent << "\n"; - } + *j = ( *i ).intersectVolume( volume, localToWorld ); } -#endif + } + + m_brush.update_wireframe( m_render_wireframe, faces_visible ); + m_brush.update_faces_wireframe( m_faceCentroidPointsCulled, faces_visible ); + } +} - //ASSERT_MESSAGE(buffer[!swap].numpoints != 1, "created single-point winding"); +void renderComponentsSelected( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { + m_brush.evaluateBRep(); - swap = !swap; - } - } + update_selected(); + if ( !m_render_selected.empty() ) { + renderer.Highlight( Renderer::ePrimitive, false ); + renderer.SetState( m_state_selpoint, Renderer::eWireframeOnly ); + renderer.SetState( m_state_selpoint, Renderer::eFullMaterials ); + renderer.addRenderable( m_render_selected, localToWorld ); + } +} - Winding_forFixedWinding(winding, buffer[swap]); +void renderComponents( Renderer& renderer, const VolumeTest& volume ) const { + m_brush.evaluateBRep(); -#if BRUSH_CONNECTIVITY_DEBUG - Winding_printConnectivity( winding ); + const Matrix4& localToWorld = Instance::localToWorld(); - for ( Winding::iterator i = winding.begin(), j = winding.end() - 1; i != winding.end(); j = i, ++i ) + renderer.SetState( m_brush.m_state_point, Renderer::eWireframeOnly ); + renderer.SetState( m_brush.m_state_point, Renderer::eFullMaterials ); + + if ( volume.fill() && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eFace ) { + evaluateViewDependent( volume, localToWorld ); + renderer.addRenderable( m_render_faces_wireframe, localToWorld ); + } + else { - if ( vector3_length_squared( vector3_subtracted( ( *i ).vertex, ( *j ).vertex ) ) < 1 ) { - globalOutputStream() << "v: " << std::distance( winding.begin(), j ) << " tiny edge adjacent to face " << ( *j ).adjacent << "\n"; - } + m_brush.renderComponents( GlobalSelectionSystem().ComponentMode(), renderer, volume, localToWorld ); } -#endif - } - - void update_wireframe(RenderableWireframe &wire, const bool *faces_visible) const - { - wire.m_faceVertex.resize(m_edge_indices.size()); - wire.m_vertices = m_uniqueVertexPoints.data(); - wire.m_size = 0; - for (std::size_t i = 0; i < m_edge_faces.size(); ++i) { - if (faces_visible[m_edge_faces[i].first] - || faces_visible[m_edge_faces[i].second]) { - wire.m_faceVertex[wire.m_size++] = m_edge_indices[i]; - } - } - } - - - void update_faces_wireframe(Array &wire, const bool *faces_visible) const - { - std::size_t count = 0; - for (std::size_t i = 0; i < m_faceCentroidPoints.size(); ++i) { - if (faces_visible[i]) { - ++count; - } - } - - wire.resize(count); - Array::iterator p = wire.begin(); - for (std::size_t i = 0; i < m_faceCentroidPoints.size(); ++i) { - if (faces_visible[i]) { - *p++ = m_faceCentroidPoints[i]; - } - } - } +} -/// \brief Makes this brush a deep-copy of the \p other. - void copy(const Brush &other) - { - for (Faces::const_iterator i = other.m_faces.begin(); i != other.m_faces.end(); ++i) { - addFace(*(*i)); - } - planeChanged(); - } +void renderClipPlane( Renderer& renderer, const VolumeTest& volume ) const { + if ( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip && isSelected() ) { + m_clipPlane.render( renderer, volume, localToWorld() ); + } +} -private: - void edge_push_back(FaceVertexId faceVertex) - { - m_select_edges.push_back(SelectableEdge(m_faces, faceVertex)); - for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { - (*i)->edge_push_back(m_select_edges.back()); - } - } - - void edge_clear() - { - m_select_edges.clear(); - for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { - (*i)->edge_clear(); - } - } - - void vertex_push_back(FaceVertexId faceVertex) - { - m_select_vertices.push_back(SelectableVertex(m_faces, faceVertex)); - for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { - (*i)->vertex_push_back(m_select_vertices.back()); - } - } - - void vertex_clear() - { - m_select_vertices.clear(); - for (Observers::iterator i = m_observers.begin(); i != m_observers.end(); ++i) { - (*i)->vertex_clear(); - } - } +void renderCommon( Renderer& renderer, const VolumeTest& volume ) const { + bool componentMode = GlobalSelectionSystem().Mode() == SelectionSystem::eComponent; -/// \brief Returns true if the face identified by \p index is preceded by another plane that takes priority over it. - bool plane_unique(std::size_t index) const - { - // duplicate plane - for (std::size_t i = 0; i < m_faces.size(); ++i) { - if (index != i && !plane3_inside(m_faces[index]->plane3(), m_faces[i]->plane3(), index < i)) { - return false; - } - } - return true; - } + if ( componentMode && isSelected() ) { + renderComponents( renderer, volume ); + } -/// \brief Removes edges that are smaller than the tolerance used when generating brush windings. - void removeDegenerateEdges() - { - for (std::size_t i = 0; i < m_faces.size(); ++i) { - Winding &winding = m_faces[i]->getWinding(); - for (Winding::iterator j = winding.begin(); j != winding.end();) { - std::size_t index = std::distance(winding.begin(), j); - std::size_t next = Winding_next(winding, index); - if (Edge_isDegenerate(winding[index].vertex, winding[next].vertex)) { -#if BRUSH_DEGENERATE_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << i << ": degenerate edge adjacent to " << winding[index].adjacent << "\n"; -#endif - Winding &other = m_faces[winding[index].adjacent]->getWinding(); - std::size_t adjacent = Winding_FindAdjacent(other, i); - if (adjacent != c_brush_maxFaces) { - other.erase(other.begin() + adjacent); - } - winding.erase(j); - } else { - ++j; - } - } - } - } + if ( parentSelected() ) { + if ( !componentMode ) { + renderer.Highlight( Renderer::eFace ); + } + renderer.Highlight( Renderer::ePrimitive ); + } +} -/// \brief Invalidates faces that have only two vertices in their winding, while preserving edge-connectivity information. - void removeDegenerateFaces() - { - // save adjacency info for degenerate faces - for (std::size_t i = 0; i < m_faces.size(); ++i) { - Winding °en = m_faces[i]->getWinding(); +void renderSolid( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { + //renderCommon(renderer, volume); - if (degen.numpoints == 2) { -#if BRUSH_DEGENERATE_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << i << ": degenerate winding adjacent to " << degen[0].adjacent << ", " << degen[1].adjacent << "\n"; -#endif - // this is an "edge" face, where the plane touches the edge of the brush - { - Winding &winding = m_faces[degen[0].adjacent]->getWinding(); - std::size_t index = Winding_FindAdjacent(winding, i); - if (index != c_brush_maxFaces) { -#if BRUSH_DEGENERATE_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << degen[0].adjacent << ": remapping adjacent " << winding[index].adjacent << " to " << degen[1].adjacent << "\n"; -#endif - winding[index].adjacent = degen[1].adjacent; - } - } - - { - Winding &winding = m_faces[degen[1].adjacent]->getWinding(); - std::size_t index = Winding_FindAdjacent(winding, i); - if (index != c_brush_maxFaces) { -#if BRUSH_DEGENERATE_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << degen[1].adjacent << ": remapping adjacent " << winding[index].adjacent << " to " << degen[0].adjacent << "\n"; -#endif - winding[index].adjacent = degen[0].adjacent; - } - } + m_lightList->evaluateLights(); - degen.resize(0); - } - } - } + for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + renderer.setLights( ( *i ).m_lights ); + ( *i ).render( renderer, volume, localToWorld ); + } -/// \brief Removes edges that have the same adjacent-face as their immediate neighbour. - void removeDuplicateEdges() - { - // verify face connectivity graph - for (std::size_t i = 0; i < m_faces.size(); ++i) { - //if(m_faces[i]->contributes()) - { - Winding &winding = m_faces[i]->getWinding(); - for (std::size_t j = 0; j != winding.numpoints;) { - std::size_t next = Winding_next(winding, j); - if (winding[j].adjacent == winding[next].adjacent) { -#if BRUSH_DEGENERATE_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << i << ": removed duplicate edge adjacent to face " << winding[j].adjacent << "\n"; -#endif - winding.erase(winding.begin() + next); - } else { - ++j; - } - } - } - } - } + renderComponentsSelected( renderer, volume, localToWorld ); +} -/// \brief Removes edges that do not have a matching pair in their adjacent-face. - void verifyConnectivityGraph() - { - // verify face connectivity graph - for (std::size_t i = 0; i < m_faces.size(); ++i) { - //if(m_faces[i]->contributes()) - { - Winding &winding = m_faces[i]->getWinding(); - for (Winding::iterator j = winding.begin(); j != winding.end();) { -#if BRUSH_CONNECTIVITY_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << i << ": adjacent to face " << ( *j ).adjacent << "\n"; -#endif - // remove unidirectional graph edges - if ((*j).adjacent == c_brush_maxFaces - || Winding_FindAdjacent(m_faces[(*j).adjacent]->getWinding(), i) == c_brush_maxFaces) { -#if BRUSH_CONNECTIVITY_DEBUG - globalOutputStream() << "Brush::buildWindings: face " << i << ": removing unidirectional connectivity graph edge adjacent to face " << ( *j ).adjacent << "\n"; -#endif - winding.erase(j); - } else { - ++j; - } - } - } - } - } +void renderWireframe( Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld ) const { + //renderCommon(renderer, volume); -/// \brief Returns true if the brush is a finite volume. A brush without a finite volume extends past the maximum world bounds and is not valid. - bool isBounded() - { - for (const_iterator i = begin(); i != end(); ++i) { - if (!(*i)->is_bounded()) { - return false; - } - } - return true; - } + evaluateViewDependent( volume, localToWorld ); -/// \brief Constructs the polygon windings for each face of the brush. Also updates the brush bounding-box and face texture-coordinates. - bool buildWindings() - { + if ( m_render_wireframe.m_size != 0 ) { + renderer.addRenderable( m_render_wireframe, localToWorld ); + } - { - m_aabb_local = AABB(); + renderComponentsSelected( renderer, volume, localToWorld ); +} - for (std::size_t i = 0; i < m_faces.size(); ++i) { - Face &f = *m_faces[i]; +void renderSolid( Renderer& renderer, const VolumeTest& volume ) const { + m_brush.evaluateBRep(); - if (!plane3_valid(f.plane3()) || !plane_unique(i)) { - f.getWinding().resize(0); - } else { -#if BRUSH_CONNECTIVITY_DEBUG - globalOutputStream() << "face: " << i << "\n"; -#endif - windingForClipPlane(f.getWinding(), f.plane3()); - - // update brush bounds - const Winding &winding = f.getWinding(); - for (Winding::const_iterator i = winding.begin(); i != winding.end(); ++i) { - aabb_extend_by_point_safe(m_aabb_local, (*i).vertex); - } - - // update texture coordinates - f.EmitTextureCoordinates(); - } - } - } - - bool degenerate = !isBounded(); - - if (!degenerate) { - // clean up connectivity information. - // these cleanups must be applied in a specific order. - removeDegenerateEdges(); - removeDegenerateFaces(); - removeDuplicateEdges(); - verifyConnectivityGraph(); - } - - return degenerate; - } + renderClipPlane( renderer, volume ); -/// \brief Constructs the face windings and updates anything that depends on them. - void buildBRep(); -}; + renderSolid( renderer, volume, localToWorld() ); +} +void renderWireframe( Renderer& renderer, const VolumeTest& volume ) const { + m_brush.evaluateBRep(); -class FaceInstance; + renderClipPlane( renderer, volume ); -class FaceInstanceSet { - typedef SelectionList FaceInstances; - FaceInstances m_faceInstances; -public: - void insert(FaceInstance &faceInstance) - { - m_faceInstances.append(faceInstance); - } - - void erase(FaceInstance &faceInstance) - { - m_faceInstances.erase(faceInstance); - } - - template - void foreach(Functor functor) - { - for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - functor(*(*i)); - } - } - - bool empty() const - { - return m_faceInstances.empty(); - } - - FaceInstance &last() const - { - return m_faceInstances.back(); - } -}; + renderWireframe( renderer, volume, localToWorld() ); +} -extern FaceInstanceSet g_SelectedFaceInstances; +void viewChanged() const { + m_viewChanged = true; +} -typedef std::list VertexSelection; +void testSelect( Selector& selector, SelectionTest& test ){ + test.BeginMesh( localToWorld() ); -inline VertexSelection::iterator VertexSelection_find(VertexSelection &self, std::size_t value) -{ - return std::find(self.begin(), self.end(), value); + SelectionIntersection best; + for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + ( *i ).testSelect( test, best ); + } + if ( best.valid() ) { + selector.addIntersection( best ); + } } -inline VertexSelection::const_iterator VertexSelection_find(const VertexSelection &self, std::size_t value) -{ - return std::find(self.begin(), self.end(), value); +bool isSelectedComponents() const { + for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + if ( ( *i ).selectedComponents() ) { + return true; + } + } + return false; } -inline VertexSelection::iterator VertexSelection_insert(VertexSelection &self, std::size_t value) -{ - VertexSelection::iterator i = VertexSelection_find(self, value); - if (i == self.end()) { - self.push_back(value); - return --self.end(); - } - return i; +void setSelectedComponents( bool select, SelectionSystem::EComponentMode mode ){ + for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + ( *i ).setSelected( mode, select ); + } } -inline void VertexSelection_erase(VertexSelection &self, std::size_t value) -{ - VertexSelection::iterator i = VertexSelection_find(self, value); - if (i != self.end()) { - self.erase(i); - } -} +void testSelectComponents( Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode ){ + test.BeginMesh( localToWorld() ); -inline bool triangle_reversed(std::size_t x, std::size_t y, std::size_t z) -{ - return !((x < y && y < z) || (z < x && x < y) || (y < z && z < x)); + switch ( mode ) + { + case SelectionSystem::eVertex: + { + for ( VertexInstances::iterator i = m_vertexInstances.begin(); i != m_vertexInstances.end(); ++i ) + { + ( *i ).testSelect( selector, test ); + } + } + break; + case SelectionSystem::eEdge: + { + for ( EdgeInstances::iterator i = m_edgeInstances.begin(); i != m_edgeInstances.end(); ++i ) + { + ( *i ).testSelect( selector, test ); + } + } + break; + case SelectionSystem::eFace: + { + if ( test.getVolume().fill() ) { + for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + ( *i ).testSelect( selector, test ); + } + } + else + { + for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + ( *i ).testSelect_centroid( selector, test ); + } + } + } + break; + default: + break; + } } -template -inline Vector3 -triangle_cross(const BasicVector3 &x, const BasicVector3 y, const BasicVector3 &z) -{ - return vector3_cross(y - x, z - x); -} +void selectPlanes( Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback ){ + test.BeginMesh( localToWorld() ); -template -inline bool -triangles_same_winding(const BasicVector3 &x1, const BasicVector3 y1, const BasicVector3 &z1, - const BasicVector3 &x2, const BasicVector3 y2, const BasicVector3 &z2) -{ - return vector3_dot(triangle_cross(x1, y1, z1), triangle_cross(x2, y2, z2)) > 0; -} + PlanePointer brushPlanes[c_brush_maxFaces]; + PlanesIterator j = brushPlanes; + for ( Brush::const_iterator i = m_brush.begin(); i != m_brush.end(); ++i ) + { + *j++ = &( *i )->plane3(); + } -typedef const Plane3 *PlanePointer; -typedef PlanePointer *PlanesIterator; + for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + ( *i ).selectPlane( selector, Line( test.getNear(), test.getFar() ), brushPlanes, j, selectedPlaneCallback ); + } +} -class VectorLightList : public LightList { - typedef std::vector Lights; - Lights m_lights; -public: - void addLight(const RendererLight &light) - { - m_lights.push_back(&light); - } - - void clear() - { - m_lights.clear(); - } - - void evaluateLights() const - { - } - - void lightsChanged() const - { - } - - void forEachLight(const RendererLightCallback &callback) const - { - for (Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i) { - callback(*(*i)); - } - } -}; +void selectReversedPlanes( Selector& selector, const SelectedPlanes& selectedPlanes ){ + for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + ( *i ).selectReversedPlane( selector, selectedPlanes ); + } +} -class FaceInstance { - Face *m_face; - ObservedSelectable m_selectable; - ObservedSelectable m_selectableVertices; - ObservedSelectable m_selectableEdges; - SelectionChangeCallback m_selectionChanged; - VertexSelection m_vertexSelection; - VertexSelection m_edgeSelection; +void transformComponents( const Matrix4& matrix ){ + for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + ( *i ).transformComponents( matrix ); + } +} -public: - mutable VectorLightList m_lights; - - FaceInstance(Face &face, const SelectionChangeCallback &observer) : - m_face(&face), - m_selectable(SelectedChangedCaller(*this)), - m_selectableVertices(observer), - m_selectableEdges(observer), - m_selectionChanged(observer) - { - } - - FaceInstance(const FaceInstance &other) : - m_face(other.m_face), - m_selectable(SelectedChangedCaller(*this)), - m_selectableVertices(other.m_selectableVertices), - m_selectableEdges(other.m_selectableEdges), - m_selectionChanged(other.m_selectionChanged) - { - } - - FaceInstance &operator=(const FaceInstance &other) - { - m_face = other.m_face; - return *this; - } - - Face &getFace() - { - return *m_face; - } - - const Face &getFace() const - { - return *m_face; - } - - void selectedChanged(const Selectable &selectable) - { - if (selectable.isSelected()) { - g_SelectedFaceInstances.insert(*this); - } else { - g_SelectedFaceInstances.erase(*this); - } - m_selectionChanged(selectable); - } - - typedef MemberCaller SelectedChangedCaller; - - bool selectedVertices() const - { - return !m_vertexSelection.empty(); - } - - bool selectedEdges() const - { - return !m_edgeSelection.empty(); - } - - bool isSelected() const - { - return m_selectable.isSelected(); - } - - bool selectedComponents() const - { - return selectedVertices() || selectedEdges() || isSelected(); - } - - bool selectedComponents(SelectionSystem::EComponentMode mode) const - { - switch (mode) { - case SelectionSystem::eVertex: - return selectedVertices(); - case SelectionSystem::eEdge: - return selectedEdges(); - case SelectionSystem::eFace: - return isSelected(); - default: - return false; - } - } - - void setSelected(SelectionSystem::EComponentMode mode, bool select) - { - switch (mode) { - case SelectionSystem::eFace: - m_selectable.setSelected(select); - break; - case SelectionSystem::eVertex: - ASSERT_MESSAGE(!select, "select-all not supported"); - - m_vertexSelection.clear(); - m_selectableVertices.setSelected(false); - break; - case SelectionSystem::eEdge: - ASSERT_MESSAGE(!select, "select-all not supported"); - - m_edgeSelection.clear(); - m_selectableEdges.setSelected(false); - break; - default: - break; - } - } - - template - void SelectedVertices_foreach(Functor functor) const - { - for (VertexSelection::const_iterator i = m_vertexSelection.begin(); i != m_vertexSelection.end(); ++i) { - std::size_t index = Winding_FindAdjacent(getFace().getWinding(), *i); - if (index != c_brush_maxFaces) { - functor(getFace().getWinding()[index].vertex); - } - } - } - - template - void SelectedEdges_foreach(Functor functor) const - { - for (VertexSelection::const_iterator i = m_edgeSelection.begin(); i != m_edgeSelection.end(); ++i) { - std::size_t index = Winding_FindAdjacent(getFace().getWinding(), *i); - if (index != c_brush_maxFaces) { - const Winding &winding = getFace().getWinding(); - std::size_t adjacent = Winding_next(winding, index); - functor(vector3_mid(winding[index].vertex, winding[adjacent].vertex)); - } - } - } - - template - void SelectedFaces_foreach(Functor functor) const - { - if (isSelected()) { - functor(centroid()); - } - } - - template - void SelectedComponents_foreach(Functor functor) const - { - SelectedVertices_foreach(functor); - SelectedEdges_foreach(functor); - SelectedFaces_foreach(functor); - } - - void iterate_selected(AABB &aabb) const - { - SelectedComponents_foreach([&](const Vector3 &point) { - aabb_extend_by_point_safe(aabb, point); - }); - } - - void iterate_selected(RenderablePointVector &points) const - { - SelectedComponents_foreach([&](const Vector3 &point) { - const Colour4b colour_selected(0, 0, 255, 255); - points.push_back(pointvertex_for_windingpoint(point, colour_selected)); - }); - } - - bool intersectVolume(const VolumeTest &volume, const Matrix4 &localToWorld) const - { - return m_face->intersectVolume(volume, localToWorld); - } - - void render(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const - { - if (!m_face->isFiltered() && m_face->contributes() && intersectVolume(volume, localToWorld)) { - renderer.PushState(); - if (selectedComponents()) { - renderer.Highlight(Renderer::eFace); - } - m_face->render(renderer, localToWorld); - renderer.PopState(); - } - } - - void testSelect(SelectionTest &test, SelectionIntersection &best) - { - if (!m_face->isFiltered()) { - m_face->testSelect(test, best); - } - } - - void testSelect(Selector &selector, SelectionTest &test) - { - SelectionIntersection best; - testSelect(test, best); - if (best.valid()) { - Selector_add(selector, m_selectable, best); - } - } - - void testSelect_centroid(Selector &selector, SelectionTest &test) - { - if (m_face->contributes() && !m_face->isFiltered()) { - SelectionIntersection best; - m_face->testSelect_centroid(test, best); - if (best.valid()) { - Selector_add(selector, m_selectable, best); - } - } - } - - void selectPlane(Selector &selector, const Line &line, PlanesIterator first, PlanesIterator last, - const PlaneCallback &selectedPlaneCallback) - { - for (Winding::const_iterator i = getFace().getWinding().begin(); i != getFace().getWinding().end(); ++i) { - Vector3 v(vector3_subtracted(line_closest_point(line, (*i).vertex), (*i).vertex)); - double dot = vector3_dot(getFace().plane3().normal(), v); - if (dot <= 0) { - return; - } - } - - Selector_add(selector, m_selectable); - - selectedPlaneCallback(getFace().plane3()); - } - - void selectReversedPlane(Selector &selector, const SelectedPlanes &selectedPlanes) - { - if (selectedPlanes.contains(plane3_flipped(getFace().plane3()))) { - Selector_add(selector, m_selectable); - } - } - - void transformComponents(const Matrix4 &matrix) - { - if (isSelected()) { - m_face->transform(matrix, false); - } - if (selectedVertices()) { - if (m_vertexSelection.size() == 1) { - matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[1]); - m_face->assign_planepts(m_face->m_move_planeptsTransformed); - } else if (m_vertexSelection.size() == 2) { - matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[1]); - matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[2]); - m_face->assign_planepts(m_face->m_move_planeptsTransformed); - } else if (m_vertexSelection.size() >= 3) { - matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[0]); - matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[1]); - matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[2]); - m_face->assign_planepts(m_face->m_move_planeptsTransformed); - } - } - if (selectedEdges()) { - if (m_edgeSelection.size() == 1) { - matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[0]); - matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[1]); - m_face->assign_planepts(m_face->m_move_planeptsTransformed); - } else if (m_edgeSelection.size() >= 2) { - matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[0]); - matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[1]); - matrix4_transform_point(matrix, m_face->m_move_planeptsTransformed[2]); - m_face->assign_planepts(m_face->m_move_planeptsTransformed); - } - } - } - - void snapto(float snap) - { - m_face->snapto(snap); - } - - void snapComponents(float snap) - { - if (isSelected()) { - snapto(snap); - } - if (selectedVertices()) { - vector3_snap(m_face->m_move_planepts[0], snap); - vector3_snap(m_face->m_move_planepts[1], snap); - vector3_snap(m_face->m_move_planepts[2], snap); - m_face->assign_planepts(m_face->m_move_planepts); - planepts_assign(m_face->m_move_planeptsTransformed, m_face->m_move_planepts); - m_face->freezeTransform(); - } - if (selectedEdges()) { - vector3_snap(m_face->m_move_planepts[0], snap); - vector3_snap(m_face->m_move_planepts[1], snap); - vector3_snap(m_face->m_move_planepts[2], snap); - m_face->assign_planepts(m_face->m_move_planepts); - planepts_assign(m_face->m_move_planeptsTransformed, m_face->m_move_planepts); - m_face->freezeTransform(); - } - } - - void update_move_planepts_vertex(std::size_t index) - { - m_face->update_move_planepts_vertex(index, m_face->m_move_planepts); - } - - void update_move_planepts_vertex2(std::size_t index, std::size_t other) - { - const std::size_t numpoints = m_face->getWinding().numpoints; - ASSERT_MESSAGE(index < numpoints, "select_vertex: invalid index"); - - const std::size_t opposite = Winding_Opposite(m_face->getWinding(), index, other); - - if (triangle_reversed(index, other, opposite)) { - std::swap(index, other); - } - - ASSERT_MESSAGE( - triangles_same_winding( - m_face->getWinding()[opposite].vertex, - m_face->getWinding()[index].vertex, - m_face->getWinding()[other].vertex, - m_face->getWinding()[0].vertex, - m_face->getWinding()[1].vertex, - m_face->getWinding()[2].vertex - ), - "update_move_planepts_vertex2: error" - ); - - m_face->m_move_planepts[0] = m_face->getWinding()[opposite].vertex; - m_face->m_move_planepts[1] = m_face->getWinding()[index].vertex; - m_face->m_move_planepts[2] = m_face->getWinding()[other].vertex; - planepts_quantise(m_face->m_move_planepts, GRID_MIN); // winding points are very inaccurate - } - - void update_selection_vertex() - { - if (m_vertexSelection.size() == 0) { - m_selectableVertices.setSelected(false); - } else { - m_selectableVertices.setSelected(true); - - if (m_vertexSelection.size() == 1) { - std::size_t index = Winding_FindAdjacent(getFace().getWinding(), *m_vertexSelection.begin()); - - if (index != c_brush_maxFaces) { - update_move_planepts_vertex(index); - } - } else if (m_vertexSelection.size() == 2) { - std::size_t index = Winding_FindAdjacent(getFace().getWinding(), *m_vertexSelection.begin()); - std::size_t other = Winding_FindAdjacent(getFace().getWinding(), *(++m_vertexSelection.begin())); - - if (index != c_brush_maxFaces - && other != c_brush_maxFaces) { - update_move_planepts_vertex2(index, other); - } - } - } - } - - void select_vertex(std::size_t index, bool select) - { - if (select) { - VertexSelection_insert(m_vertexSelection, getFace().getWinding()[index].adjacent); - } else { - VertexSelection_erase(m_vertexSelection, getFace().getWinding()[index].adjacent); - } - - SceneChangeNotify(); - update_selection_vertex(); - } - - bool selected_vertex(std::size_t index) const - { - return VertexSelection_find(m_vertexSelection, getFace().getWinding()[index].adjacent) != - m_vertexSelection.end(); - } - - void update_move_planepts_edge(std::size_t index) - { - std::size_t numpoints = m_face->getWinding().numpoints; - ASSERT_MESSAGE(index < numpoints, "select_edge: invalid index"); - - std::size_t adjacent = Winding_next(m_face->getWinding(), index); - std::size_t opposite = Winding_Opposite(m_face->getWinding(), index); - m_face->m_move_planepts[0] = m_face->getWinding()[index].vertex; - m_face->m_move_planepts[1] = m_face->getWinding()[adjacent].vertex; - m_face->m_move_planepts[2] = m_face->getWinding()[opposite].vertex; - planepts_quantise(m_face->m_move_planepts, GRID_MIN); // winding points are very inaccurate - } - - void update_selection_edge() - { - if (m_edgeSelection.size() == 0) { - m_selectableEdges.setSelected(false); - } else { - m_selectableEdges.setSelected(true); - - if (m_edgeSelection.size() == 1) { - std::size_t index = Winding_FindAdjacent(getFace().getWinding(), *m_edgeSelection.begin()); - - if (index != c_brush_maxFaces) { - update_move_planepts_edge(index); - } - } - } - } - - void select_edge(std::size_t index, bool select) - { - if (select) { - VertexSelection_insert(m_edgeSelection, getFace().getWinding()[index].adjacent); - } else { - VertexSelection_erase(m_edgeSelection, getFace().getWinding()[index].adjacent); - } - - SceneChangeNotify(); - update_selection_edge(); - } - - bool selected_edge(std::size_t index) const - { - return VertexSelection_find(m_edgeSelection, getFace().getWinding()[index].adjacent) != m_edgeSelection.end(); - } - - const Vector3 ¢roid() const - { - return m_face->centroid(); - } - - void connectivityChanged() - { - // This occurs when a face is added or removed. - // The current vertex and edge selections no longer valid and must be cleared. - m_vertexSelection.clear(); - m_selectableVertices.setSelected(false); - m_edgeSelection.clear(); - m_selectableEdges.setSelected(false); - } -}; +const AABB& getSelectedComponentsBounds() const { + m_aabb_component = AABB(); -class BrushClipPlane : public OpenGLRenderable { - Plane3 m_plane; - Winding m_winding; - static Shader *m_state; -public: - static void constructStatic() - { - m_state = GlobalShaderCache().capture("$CLIPPER_OVERLAY"); - } - - static void destroyStatic() - { - GlobalShaderCache().release("$CLIPPER_OVERLAY"); - } - - void setPlane(const Brush &brush, const Plane3 &plane) - { - m_plane = plane; - if (plane3_valid(m_plane)) { - brush.windingForClipPlane(m_winding, m_plane); - } else { - m_winding.resize(0); - } - } - - void render(RenderStateFlags state) const - { - if ((state & RENDER_FILL) != 0) { - Winding_Draw(m_winding, m_plane.normal(), state); - } else { - Winding_DrawWireframe(m_winding); - - // also draw a line indicating the direction of the cut - Vector3 lineverts[2]; - Winding_Centroid(m_winding, m_plane, lineverts[0]); - lineverts[1] = vector3_added(lineverts[0], vector3_scaled(m_plane.normal(), Brush::m_maxWorldCoord * 4)); - - glVertexPointer(3, GL_FLOAT, sizeof(Vector3), &lineverts[0]); - glDrawArrays(GL_LINES, 0, GLsizei(2)); - } - } - - void render(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const - { - renderer.SetState(m_state, Renderer::eWireframeOnly); - renderer.SetState(m_state, Renderer::eFullMaterials); - renderer.addRenderable(*this, localToWorld); - } -}; + for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + ( *i ).iterate_selected( m_aabb_component ); + } -inline void Face_addLight(const FaceInstance &face, const Matrix4 &localToWorld, const RendererLight &light) -{ - const Plane3 &facePlane = face.getFace().plane3(); - const Vector3 &origin = light.aabb().origin; - Plane3 tmp(plane3_transformed(Plane3(facePlane.normal(), -facePlane.dist()), localToWorld)); - if (!plane3_test_point(tmp, origin) - || !plane3_test_point(tmp, vector3_added(origin, light.offset()))) { - face.m_lights.addLight(light); - } + return m_aabb_component; } +void snapComponents( float snap ){ + for ( FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + ( *i ).snapComponents( snap ); + } +} -typedef std::vector FaceInstances; +void evaluateTransform(){ + Matrix4 matrix( m_transform.calculateTransform() ); + //globalOutputStream() << "matrix: " << matrix << "\n"; -class EdgeInstance : public Selectable { - FaceInstances &m_faceInstances; - SelectableEdge *m_edge; - - void select_edge(bool select) - { - FaceVertexId faceVertex = m_edge->m_faceVertex; - m_faceInstances[faceVertex.getFace()].select_edge(faceVertex.getVertex(), select); - faceVertex = next_edge(m_edge->m_faces, faceVertex); - m_faceInstances[faceVertex.getFace()].select_edge(faceVertex.getVertex(), select); - } - - bool selected_edge() const - { - FaceVertexId faceVertex = m_edge->m_faceVertex; - if (!m_faceInstances[faceVertex.getFace()].selected_edge(faceVertex.getVertex())) { - return false; - } - faceVertex = next_edge(m_edge->m_faces, faceVertex); - if (!m_faceInstances[faceVertex.getFace()].selected_edge(faceVertex.getVertex())) { - return false; - } - - return true; - } + if ( m_transform.getType() == TRANSFORM_PRIMITIVE ) { + m_brush.transform( matrix ); + } + else + { + transformComponents( matrix ); + } +} -public: - EdgeInstance(FaceInstances &faceInstances, SelectableEdge &edge) - : m_faceInstances(faceInstances), m_edge(&edge) - { - } - - EdgeInstance &operator=(const EdgeInstance &other) - { - m_edge = other.m_edge; - return *this; - } - - void setSelected(bool select) - { - select_edge(select); - } - - bool isSelected() const - { - return selected_edge(); - } - - - void testSelect(Selector &selector, SelectionTest &test) - { - SelectionIntersection best; - m_edge->testSelect(test, best); - if (best.valid()) { - Selector_add(selector, *this, best); - } - } -}; +void applyTransform(){ + m_brush.revertTransform(); + evaluateTransform(); + m_brush.freezeTransform(); +} -class VertexInstance : public Selectable { - FaceInstances &m_faceInstances; - SelectableVertex *m_vertex; - - void select_vertex(bool select) - { - FaceVertexId faceVertex = m_vertex->m_faceVertex; - do { - m_faceInstances[faceVertex.getFace()].select_vertex(faceVertex.getVertex(), select); - faceVertex = next_vertex(m_vertex->m_faces, faceVertex); - } while (faceVertex.getFace() != m_vertex->m_faceVertex.getFace()); - } - - bool selected_vertex() const - { - FaceVertexId faceVertex = m_vertex->m_faceVertex; - do { - if (!m_faceInstances[faceVertex.getFace()].selected_vertex(faceVertex.getVertex())) { - return false; - } - faceVertex = next_vertex(m_vertex->m_faces, faceVertex); - } while (faceVertex.getFace() != m_vertex->m_faceVertex.getFace()); - return true; - } +typedef MemberCaller ApplyTransformCaller; -public: - VertexInstance(FaceInstances &faceInstances, SelectableVertex &vertex) - : m_faceInstances(faceInstances), m_vertex(&vertex) - { - } - - VertexInstance &operator=(const VertexInstance &other) - { - m_vertex = other.m_vertex; - return *this; - } - - void setSelected(bool select) - { - select_vertex(select); - } - - bool isSelected() const - { - return selected_vertex(); - } - - void testSelect(Selector &selector, SelectionTest &test) - { - SelectionIntersection best; - m_vertex->testSelect(test, best); - if (best.valid()) { - Selector_add(selector, *this, best); - } - } -}; +void setClipPlane( const Plane3& plane ){ + m_clipPlane.setPlane( m_brush, plane ); +} -class BrushInstanceVisitor { -public: - virtual void visit(FaceInstance &face) const = 0; -}; +bool testLight( const RendererLight& light ) const { + return light.testAABB( worldAABB() ); +} -class BrushInstance : - public BrushObserver, - public scene::Instance, - public Selectable, - public Renderable, - public SelectionTestable, - public ComponentSelectionTestable, - public ComponentEditable, - public ComponentSnappable, - public PlaneSelectable, - public LightCullable { - class TypeCasts { - InstanceTypeCastTable m_casts; - public: - TypeCasts() - { - InstanceStaticCast::install(m_casts); - InstanceContainedCast::install(m_casts); - InstanceContainedCast::install(m_casts); - InstanceStaticCast::install(m_casts); - InstanceStaticCast::install(m_casts); - InstanceStaticCast::install(m_casts); - InstanceStaticCast::install(m_casts); - InstanceStaticCast::install(m_casts); - InstanceStaticCast::install(m_casts); - InstanceIdentityCast::install(m_casts); - InstanceContainedCast::install(m_casts); - } - - InstanceTypeCastTable &get() - { - return m_casts; - } - }; - - - Brush &m_brush; - - FaceInstances m_faceInstances; - - typedef std::vector EdgeInstances; - EdgeInstances m_edgeInstances; - typedef std::vector VertexInstances; - VertexInstances m_vertexInstances; - - ObservedSelectable m_selectable; - - mutable RenderableWireframe m_render_wireframe; - mutable RenderablePointVector m_render_selected; - mutable AABB m_aabb_component; - mutable Array m_faceCentroidPointsCulled; - RenderablePointArray m_render_faces_wireframe; - mutable bool m_viewChanged; // requires re-evaluation of view-dependent cached data - - BrushClipPlane m_clipPlane; - - static Shader *m_state_selpoint; - - const LightList *m_lightList; - - TransformModifier m_transform; - - BrushInstance(const BrushInstance &other); // NOT COPYABLE - BrushInstance &operator=(const BrushInstance &other); // NOT ASSIGNABLE -public: - static Counter *m_counter; - - typedef LazyStatic StaticTypeCasts; - - void lightsChanged() - { - m_lightList->lightsChanged(); - } - - typedef MemberCaller LightsChangedCaller; - - STRING_CONSTANT(Name, "BrushInstance"); - - BrushInstance(const scene::Path &path, scene::Instance *parent, Brush &brush) : - Instance(path, parent, this, StaticTypeCasts::instance().get()), - m_brush(brush), - m_selectable(SelectedChangedCaller(*this)), - m_render_selected(GL_POINTS), - m_render_faces_wireframe(m_faceCentroidPointsCulled, GL_POINTS), - m_viewChanged(false), - m_transform(Brush::TransformChangedCaller(m_brush), ApplyTransformCaller(*this)) - { - m_brush.instanceAttach(Instance::path()); - m_brush.attach(*this); - m_counter->increment(); - - m_lightList = &GlobalShaderCache().attach(*this); - m_brush.m_lightsChanged = LightsChangedCaller(*this); ///\todo Make this work with instancing. - - Instance::setTransformChangedCallback(LightsChangedCaller(*this)); - } - - ~BrushInstance() - { - Instance::setTransformChangedCallback(Callback()); - - m_brush.m_lightsChanged = Callback(); - GlobalShaderCache().detach(*this); - - m_counter->decrement(); - m_brush.detach(*this); - m_brush.instanceDetach(Instance::path()); - } - - Brush &getBrush() - { - return m_brush; - } - - const Brush &getBrush() const - { - return m_brush; - } - - Bounded &get(NullType) - { - return m_brush; - } - - Cullable &get(NullType) - { - return m_brush; - } - - Transformable &get(NullType) - { - return m_transform; - } - - void selectedChanged(const Selectable &selectable) - { - GlobalSelectionSystem().getObserver(SelectionSystem::ePrimitive)(selectable); - GlobalSelectionSystem().onSelectedChanged(*this, selectable); - - Instance::selectedChanged(); - } - - typedef MemberCaller SelectedChangedCaller; - - void selectedChangedComponent(const Selectable &selectable) - { - GlobalSelectionSystem().getObserver(SelectionSystem::eComponent)(selectable); - GlobalSelectionSystem().onComponentSelection(*this, selectable); - } - - typedef MemberCaller SelectedChangedComponentCaller; - - const BrushInstanceVisitor &forEachFaceInstance(const BrushInstanceVisitor &visitor) - { - for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - visitor.visit(*i); - } - return visitor; - } - - static void constructStatic() - { - m_state_selpoint = GlobalShaderCache().capture("$SELPOINT"); - } - - static void destroyStatic() - { - GlobalShaderCache().release("$SELPOINT"); - } - - void clear() - { - m_faceInstances.clear(); - } - - void reserve(std::size_t size) - { - m_faceInstances.reserve(size); - } - - void push_back(Face &face) - { - m_faceInstances.push_back(FaceInstance(face, SelectedChangedComponentCaller(*this))); - } - - void pop_back() - { - ASSERT_MESSAGE(!m_faceInstances.empty(), "erasing invalid element"); - m_faceInstances.pop_back(); - } - - void erase(std::size_t index) - { - ASSERT_MESSAGE(index < m_faceInstances.size(), "erasing invalid element"); - m_faceInstances.erase(m_faceInstances.begin() + index); - } - - void connectivityChanged() - { - for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - (*i).connectivityChanged(); - } - } - - void edge_clear() - { - m_edgeInstances.clear(); - } - - void edge_push_back(SelectableEdge &edge) - { - m_edgeInstances.push_back(EdgeInstance(m_faceInstances, edge)); - } - - void vertex_clear() - { - m_vertexInstances.clear(); - } - - void vertex_push_back(SelectableVertex &vertex) - { - m_vertexInstances.push_back(VertexInstance(m_faceInstances, vertex)); - } - - void DEBUG_verify() const - { - ASSERT_MESSAGE(m_faceInstances.size() == m_brush.DEBUG_size(), "FATAL: mismatch"); - } - - bool isSelected() const - { - return m_selectable.isSelected(); - } - - void setSelected(bool select) - { - m_selectable.setSelected(select); - } - - void update_selected() const - { - m_render_selected.clear(); - for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - if ((*i).getFace().contributes()) { - (*i).iterate_selected(m_render_selected); - } - } - } - - void evaluateViewDependent(const VolumeTest &volume, const Matrix4 &localToWorld) const - { - if (m_viewChanged) { - m_viewChanged = false; - - bool faces_visible[c_brush_maxFaces]; - { - bool *j = faces_visible; - for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i, ++j) { - *j = (*i).intersectVolume(volume, localToWorld); - } - } - - m_brush.update_wireframe(m_render_wireframe, faces_visible); - m_brush.update_faces_wireframe(m_faceCentroidPointsCulled, faces_visible); - } - } - - void renderComponentsSelected(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const - { - m_brush.evaluateBRep(); - - update_selected(); - if (!m_render_selected.empty()) { - renderer.Highlight(Renderer::ePrimitive, false); - renderer.SetState(m_state_selpoint, Renderer::eWireframeOnly); - renderer.SetState(m_state_selpoint, Renderer::eFullMaterials); - renderer.addRenderable(m_render_selected, localToWorld); - } - } - - void renderComponents(Renderer &renderer, const VolumeTest &volume) const - { - m_brush.evaluateBRep(); - - const Matrix4 &localToWorld = Instance::localToWorld(); - - renderer.SetState(m_brush.m_state_point, Renderer::eWireframeOnly); - renderer.SetState(m_brush.m_state_point, Renderer::eFullMaterials); - - if (volume.fill() && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eFace) { - evaluateViewDependent(volume, localToWorld); - renderer.addRenderable(m_render_faces_wireframe, localToWorld); - } else { - m_brush.renderComponents(GlobalSelectionSystem().ComponentMode(), renderer, volume, localToWorld); - } - } - - void renderClipPlane(Renderer &renderer, const VolumeTest &volume) const - { - if (GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip && isSelected()) { - m_clipPlane.render(renderer, volume, localToWorld()); - } - } - - void renderCommon(Renderer &renderer, const VolumeTest &volume) const - { - bool componentMode = GlobalSelectionSystem().Mode() == SelectionSystem::eComponent; - - if (componentMode && isSelected()) { - renderComponents(renderer, volume); - } - - if (parentSelected()) { - if (!componentMode) { - renderer.Highlight(Renderer::eFace); - } - renderer.Highlight(Renderer::ePrimitive); - } - } - - void renderSolid(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const - { - //renderCommon(renderer, volume); - - m_lightList->evaluateLights(); - - for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - renderer.setLights((*i).m_lights); - (*i).render(renderer, volume, localToWorld); - } - - renderComponentsSelected(renderer, volume, localToWorld); - } - - void renderWireframe(Renderer &renderer, const VolumeTest &volume, const Matrix4 &localToWorld) const - { - //renderCommon(renderer, volume); - - evaluateViewDependent(volume, localToWorld); - - if (m_render_wireframe.m_size != 0) { - renderer.addRenderable(m_render_wireframe, localToWorld); - } - - renderComponentsSelected(renderer, volume, localToWorld); - } - - void renderSolid(Renderer &renderer, const VolumeTest &volume) const - { - m_brush.evaluateBRep(); - - renderClipPlane(renderer, volume); - - renderSolid(renderer, volume, localToWorld()); - } - - void renderWireframe(Renderer &renderer, const VolumeTest &volume) const - { - m_brush.evaluateBRep(); - - renderClipPlane(renderer, volume); - - renderWireframe(renderer, volume, localToWorld()); - } - - void viewChanged() const - { - m_viewChanged = true; - } - - void testSelect(Selector &selector, SelectionTest &test) - { - test.BeginMesh(localToWorld()); - - SelectionIntersection best; - for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - (*i).testSelect(test, best); - } - if (best.valid()) { - selector.addIntersection(best); - } - } - - bool isSelectedComponents() const - { - for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - if ((*i).selectedComponents()) { - return true; - } - } - return false; - } - - void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode) - { - for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - (*i).setSelected(mode, select); - } - } - - void testSelectComponents(Selector &selector, SelectionTest &test, SelectionSystem::EComponentMode mode) - { - test.BeginMesh(localToWorld()); - - switch (mode) { - case SelectionSystem::eVertex: { - for (VertexInstances::iterator i = m_vertexInstances.begin(); i != m_vertexInstances.end(); ++i) { - (*i).testSelect(selector, test); - } - } - break; - case SelectionSystem::eEdge: { - for (EdgeInstances::iterator i = m_edgeInstances.begin(); i != m_edgeInstances.end(); ++i) { - (*i).testSelect(selector, test); - } - } - break; - case SelectionSystem::eFace: { - if (test.getVolume().fill()) { - for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - (*i).testSelect(selector, test); - } - } else { - for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - (*i).testSelect_centroid(selector, test); - } - } - } - break; - default: - break; - } - } - - void selectPlanes(Selector &selector, SelectionTest &test, const PlaneCallback &selectedPlaneCallback) - { - test.BeginMesh(localToWorld()); - - PlanePointer brushPlanes[c_brush_maxFaces]; - PlanesIterator j = brushPlanes; - - for (Brush::const_iterator i = m_brush.begin(); i != m_brush.end(); ++i) { - *j++ = &(*i)->plane3(); - } - - for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - (*i).selectPlane(selector, Line(test.getNear(), test.getFar()), brushPlanes, j, selectedPlaneCallback); - } - } - - void selectReversedPlanes(Selector &selector, const SelectedPlanes &selectedPlanes) - { - for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - (*i).selectReversedPlane(selector, selectedPlanes); - } - } - - - void transformComponents(const Matrix4 &matrix) - { - for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - (*i).transformComponents(matrix); - } - } - - const AABB &getSelectedComponentsBounds() const - { - m_aabb_component = AABB(); - - for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - (*i).iterate_selected(m_aabb_component); - } - - return m_aabb_component; - } - - void snapComponents(float snap) - { - for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - (*i).snapComponents(snap); - } - } - - void evaluateTransform() - { - Matrix4 matrix(m_transform.calculateTransform()); - //globalOutputStream() << "matrix: " << matrix << "\n"; - - if (m_transform.getType() == TRANSFORM_PRIMITIVE) { - m_brush.transform(matrix); - } else { - transformComponents(matrix); - } - } - - void applyTransform() - { - m_brush.revertTransform(); - evaluateTransform(); - m_brush.freezeTransform(); - } - - typedef MemberCaller ApplyTransformCaller; - - void setClipPlane(const Plane3 &plane) - { - m_clipPlane.setPlane(m_brush, plane); - } - - bool testLight(const RendererLight &light) const - { - return light.testAABB(worldAABB()); - } - - void insertLight(const RendererLight &light) - { - const Matrix4 &localToWorld = Instance::localToWorld(); - for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - Face_addLight(*i, localToWorld, light); - } - } - - void clearLights() - { - for (FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i) { - (*i).m_lights.clear(); - } - } +void insertLight( const RendererLight& light ){ + const Matrix4& localToWorld = Instance::localToWorld(); + for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + Face_addLight( *i, localToWorld, light ); + } +} + +void clearLights(){ + for ( FaceInstances::const_iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i ) + { + ( *i ).m_lights.clear(); + } +} }; -inline BrushInstance *Instance_getBrush(scene::Instance &instance) -{ - return InstanceTypeCast::cast(instance); +inline BrushInstance* Instance_getBrush( scene::Instance& instance ){ + return InstanceTypeCast::cast( instance ); } template -class BrushSelectedVisitor : public SelectionSystem::Visitor { - const Functor &m_functor; +class BrushSelectedVisitor : public SelectionSystem::Visitor +{ +const Functor& m_functor; public: - BrushSelectedVisitor(const Functor &functor) : m_functor(functor) - { - } - - void visit(scene::Instance &instance) const - { - BrushInstance *brush = Instance_getBrush(instance); - if (brush != 0) { - m_functor(*brush); - } - } +BrushSelectedVisitor( const Functor& functor ) : m_functor( functor ){ +} + +void visit( scene::Instance& instance ) const { + BrushInstance* brush = Instance_getBrush( instance ); + if ( brush != 0 ) { + m_functor( *brush ); + } +} }; template -inline const Functor &Scene_forEachSelectedBrush(const Functor &functor) -{ - GlobalSelectionSystem().foreachSelected(BrushSelectedVisitor(functor)); - return functor; +inline const Functor& Scene_forEachSelectedBrush( const Functor& functor ){ + GlobalSelectionSystem().foreachSelected( BrushSelectedVisitor( functor ) ); + return functor; } template -class BrushVisibleSelectedVisitor : public SelectionSystem::Visitor { - const Functor &m_functor; +class BrushVisibleSelectedVisitor : public SelectionSystem::Visitor +{ +const Functor& m_functor; public: - BrushVisibleSelectedVisitor(const Functor &functor) : m_functor(functor) - { - } - - void visit(scene::Instance &instance) const - { - BrushInstance *brush = Instance_getBrush(instance); - if (brush != 0 - && instance.path().top().get().visible()) { - m_functor(*brush); - } - } +BrushVisibleSelectedVisitor( const Functor& functor ) : m_functor( functor ){ +} + +void visit( scene::Instance& instance ) const { + BrushInstance* brush = Instance_getBrush( instance ); + if ( brush != 0 + && instance.path().top().get().visible() ) { + m_functor( *brush ); + } +} }; template -inline const Functor &Scene_forEachVisibleSelectedBrush(const Functor &functor) -{ - GlobalSelectionSystem().foreachSelected(BrushVisibleSelectedVisitor(functor)); - return functor; +inline const Functor& Scene_forEachVisibleSelectedBrush( const Functor& functor ){ + GlobalSelectionSystem().foreachSelected( BrushVisibleSelectedVisitor( functor ) ); + return functor; } -class BrushForEachFace { - const BrushInstanceVisitor &m_visitor; +class BrushForEachFace +{ +const BrushInstanceVisitor& m_visitor; public: - BrushForEachFace(const BrushInstanceVisitor &visitor) : m_visitor(visitor) - { - } - - void operator()(BrushInstance &brush) const - { - brush.forEachFaceInstance(m_visitor); - } +BrushForEachFace( const BrushInstanceVisitor& visitor ) : m_visitor( visitor ){ +} + +void operator()( BrushInstance& brush ) const { + brush.forEachFaceInstance( m_visitor ); +} }; template -class FaceInstanceVisitFace : public BrushInstanceVisitor { - const Functor &functor; +class FaceInstanceVisitFace : public BrushInstanceVisitor +{ +const Functor& functor; public: - FaceInstanceVisitFace(const Functor &functor) - : functor(functor) - { - } - - void visit(FaceInstance &face) const - { - functor(face.getFace()); - } +FaceInstanceVisitFace( const Functor& functor ) + : functor( functor ){ +} + +void visit( FaceInstance& face ) const { + functor( face.getFace() ); +} }; template -inline const Functor &Brush_forEachFace(BrushInstance &brush, const Functor &functor) -{ - brush.forEachFaceInstance(FaceInstanceVisitFace(functor)); - return functor; +inline const Functor& Brush_forEachFace( BrushInstance& brush, const Functor& functor ){ + brush.forEachFaceInstance( FaceInstanceVisitFace( functor ) ); + return functor; } template -class FaceVisitAll : public BrushVisitor { - const Functor &functor; +class FaceVisitAll : public BrushVisitor +{ +const Functor& functor; public: - FaceVisitAll(const Functor &functor) - : functor(functor) - { - } - - void visit(Face &face) const - { - functor(face); - } +FaceVisitAll( const Functor& functor ) + : functor( functor ){ +} + +void visit( Face& face ) const { + functor( face ); +} }; template -inline const Functor &Brush_forEachFace(const Brush &brush, const Functor &functor) -{ - brush.forEachFace(FaceVisitAll(functor)); - return functor; +inline const Functor& Brush_forEachFace( const Brush& brush, const Functor& functor ){ + brush.forEachFace( FaceVisitAll( functor ) ); + return functor; } template -inline const Functor &Brush_forEachFace(Brush &brush, const Functor &functor) -{ - brush.forEachFace(FaceVisitAll(functor)); - return functor; +inline const Functor& Brush_forEachFace( Brush& brush, const Functor& functor ){ + brush.forEachFace( FaceVisitAll( functor ) ); + return functor; } template -class FaceInstanceVisitAll : public BrushInstanceVisitor { - const Functor &functor; +class FaceInstanceVisitAll : public BrushInstanceVisitor +{ +const Functor& functor; public: - FaceInstanceVisitAll(const Functor &functor) - : functor(functor) - { - } - - void visit(FaceInstance &face) const - { - functor(face); - } +FaceInstanceVisitAll( const Functor& functor ) + : functor( functor ){ +} + +void visit( FaceInstance& face ) const { + functor( face ); +} }; template -inline const Functor &Brush_ForEachFaceInstance(BrushInstance &brush, const Functor &functor) -{ - brush.forEachFaceInstance(FaceInstanceVisitAll(functor)); - return functor; +inline const Functor& Brush_ForEachFaceInstance( BrushInstance& brush, const Functor& functor ){ + brush.forEachFaceInstance( FaceInstanceVisitAll( functor ) ); + return functor; } template -inline const Functor &Scene_forEachBrush(scene::Graph &graph, const Functor &functor) -{ - graph.traverse(InstanceWalker >(functor)); - return functor; +inline const Functor& Scene_forEachBrush( scene::Graph& graph, const Functor& functor ){ + graph.traverse( InstanceWalker< InstanceApply >( functor ) ); + return functor; } template -class InstanceIfVisible : public Functor { +class InstanceIfVisible : public Functor +{ public: - InstanceIfVisible(const Functor &functor) : Functor(functor) - { - } - - void operator()(scene::Instance &instance) - { - if (instance.path().top().get().visible()) { - Functor::operator()(instance); - } - } +InstanceIfVisible( const Functor& functor ) : Functor( functor ){ +} + +void operator()( scene::Instance& instance ){ + if ( instance.path().top().get().visible() ) { + Functor::operator()( instance ); + } +} }; template -class BrushVisibleWalker : public scene::Graph::Walker { - const Functor &m_functor; +class BrushVisibleWalker : public scene::Graph::Walker +{ +const Functor& m_functor; public: - BrushVisibleWalker(const Functor &functor) : m_functor(functor) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - if (path.top().get().visible()) { - BrushInstance *brush = Instance_getBrush(instance); - if (brush != 0) { - m_functor(*brush); - } - } - return true; - } +BrushVisibleWalker( const Functor& functor ) : m_functor( functor ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get().visible() ) { + BrushInstance* brush = Instance_getBrush( instance ); + if ( brush != 0 ) { + m_functor( *brush ); + } + } + return true; +} }; template -inline const Functor &Scene_forEachVisibleBrush(scene::Graph &graph, const Functor &functor) -{ - graph.traverse(BrushVisibleWalker(functor)); - return functor; +inline const Functor& Scene_forEachVisibleBrush( scene::Graph& graph, const Functor& functor ){ + graph.traverse( BrushVisibleWalker( functor ) ); + return functor; } template -inline const Functor &Scene_ForEachBrush_ForEachFace(scene::Graph &graph, const Functor &functor) -{ - Scene_forEachBrush(graph, BrushForEachFace(FaceInstanceVisitFace(functor))); - return functor; +inline const Functor& Scene_ForEachBrush_ForEachFace( scene::Graph& graph, const Functor& functor ){ + Scene_forEachBrush( graph, BrushForEachFace( FaceInstanceVisitFace( functor ) ) ); + return functor; } // d1223m template -inline const Functor &Scene_ForEachBrush_ForEachFaceInstance(scene::Graph &graph, const Functor &functor) -{ - Scene_forEachBrush(graph, BrushForEachFace(FaceInstanceVisitAll(functor))); - return functor; +inline const Functor& Scene_ForEachBrush_ForEachFaceInstance( scene::Graph& graph, const Functor& functor ){ + Scene_forEachBrush( graph, BrushForEachFace( FaceInstanceVisitAll( functor ) ) ); + return functor; } template -inline const Functor &Scene_ForEachSelectedBrush_ForEachFace(scene::Graph &graph, const Functor &functor) -{ - Scene_forEachSelectedBrush(BrushForEachFace(FaceInstanceVisitFace(functor))); - return functor; +inline const Functor& Scene_ForEachSelectedBrush_ForEachFace( scene::Graph& graph, const Functor& functor ){ + Scene_forEachSelectedBrush( BrushForEachFace( FaceInstanceVisitFace( functor ) ) ); + return functor; } template -inline const Functor &Scene_ForEachSelectedBrush_ForEachFaceInstance(scene::Graph &graph, const Functor &functor) -{ - Scene_forEachSelectedBrush(BrushForEachFace(FaceInstanceVisitAll(functor))); - return functor; +inline const Functor& Scene_ForEachSelectedBrush_ForEachFaceInstance( scene::Graph& graph, const Functor& functor ){ + Scene_forEachSelectedBrush( BrushForEachFace( FaceInstanceVisitAll( functor ) ) ); + return functor; } template -class FaceVisitorWrapper { - const Functor &functor; +class FaceVisitorWrapper +{ +const Functor& functor; public: - FaceVisitorWrapper(const Functor &functor) : functor(functor) - { - } - - void operator()(FaceInstance &faceInstance) const - { - functor(faceInstance.getFace()); - } +FaceVisitorWrapper( const Functor& functor ) : functor( functor ){ +} + +void operator()( FaceInstance& faceInstance ) const { + functor( faceInstance.getFace() ); +} }; template -inline const Functor &Scene_ForEachSelectedBrushFace(scene::Graph &graph, const Functor &functor) -{ - g_SelectedFaceInstances.foreach(FaceVisitorWrapper(functor)); - return functor; +inline const Functor& Scene_ForEachSelectedBrushFace( scene::Graph& graph, const Functor& functor ){ + g_SelectedFaceInstances.foreach( FaceVisitorWrapper( functor ) ); + return functor; } diff --git a/radiant/brushmanip.cpp b/radiant/brushmanip.cpp index 19e91e03..fc3054e1 100644 --- a/radiant/brushmanip.cpp +++ b/radiant/brushmanip.cpp @@ -38,951 +38,902 @@ #include #include -void Brush_ConstructCuboid(Brush &brush, const AABB &bounds, const char *shader, const TextureProjection &projection) -{ - const unsigned char box[3][2] = {{0, 1}, - {2, 0}, - {1, 2}}; - Vector3 mins(vector3_subtracted(bounds.origin, bounds.extents)); - Vector3 maxs(vector3_added(bounds.origin, bounds.extents)); - - brush.clear(); - brush.reserve(6); - - { - for (int i = 0; i < 3; ++i) { - Vector3 planepts1(maxs); - Vector3 planepts2(maxs); - planepts2[box[i][0]] = mins[box[i][0]]; - planepts1[box[i][1]] = mins[box[i][1]]; - - brush.addPlane(maxs, planepts1, planepts2, shader, projection); - } - } - { - for (int i = 0; i < 3; ++i) { - Vector3 planepts1(mins); - Vector3 planepts2(mins); - planepts1[box[i][0]] = maxs[box[i][0]]; - planepts2[box[i][1]] = maxs[box[i][1]]; - - brush.addPlane(mins, planepts1, planepts2, shader, projection); - } - } -} - -inline float max_extent(const Vector3 &extents) -{ - return std::max(std::max(extents[0], extents[1]), extents[2]); -} - -inline float max_extent_2d(const Vector3 &extents, int axis) -{ - switch (axis) { - case 0: - return std::max(extents[1], extents[2]); - case 1: - return std::max(extents[0], extents[2]); - default: - return std::max(extents[0], extents[1]); - } +void Brush_ConstructCuboid( Brush& brush, const AABB& bounds, const char* shader, const TextureProjection& projection ){ + const unsigned char box[3][2] = { { 0, 1 }, { 2, 0 }, { 1, 2 } }; + Vector3 mins( vector3_subtracted( bounds.origin, bounds.extents ) ); + Vector3 maxs( vector3_added( bounds.origin, bounds.extents ) ); + + brush.clear(); + brush.reserve( 6 ); + + { + for ( int i = 0; i < 3; ++i ) + { + Vector3 planepts1( maxs ); + Vector3 planepts2( maxs ); + planepts2[box[i][0]] = mins[box[i][0]]; + planepts1[box[i][1]] = mins[box[i][1]]; + + brush.addPlane( maxs, planepts1, planepts2, shader, projection ); + } + } + { + for ( int i = 0; i < 3; ++i ) + { + Vector3 planepts1( mins ); + Vector3 planepts2( mins ); + planepts1[box[i][0]] = maxs[box[i][0]]; + planepts2[box[i][1]] = maxs[box[i][1]]; + + brush.addPlane( mins, planepts1, planepts2, shader, projection ); + } + } +} + +inline float max_extent( const Vector3& extents ){ + return std::max( std::max( extents[0], extents[1] ), extents[2] ); +} + +inline float max_extent_2d( const Vector3& extents, int axis ){ + switch ( axis ) + { + case 0: + return std::max( extents[1], extents[2] ); + case 1: + return std::max( extents[0], extents[2] ); + default: + return std::max( extents[0], extents[1] ); + } } const std::size_t c_brushPrism_minSides = 3; const std::size_t c_brushPrism_maxSides = c_brush_maxFaces - 2; -const char *const c_brushPrism_name = "brushPrism"; - -void Brush_ConstructPrism(Brush &brush, const AABB &bounds, std::size_t sides, int axis, const char *shader, - const TextureProjection &projection) -{ - if (sides < c_brushPrism_minSides) { - globalErrorStream() << c_brushPrism_name << ": sides " << Unsigned(sides) << ": too few sides, minimum is " - << Unsigned(c_brushPrism_minSides) << "\n"; - return; - } - if (sides > c_brushPrism_maxSides) { - globalErrorStream() << c_brushPrism_name << ": sides " << Unsigned(sides) << ": too many sides, maximum is " - << Unsigned(c_brushPrism_maxSides) << "\n"; - return; - } - - brush.clear(); - brush.reserve(sides + 2); - - Vector3 mins(vector3_subtracted(bounds.origin, bounds.extents)); - Vector3 maxs(vector3_added(bounds.origin, bounds.extents)); - - float radius = max_extent_2d(bounds.extents, axis); - const Vector3 &mid = bounds.origin; - Vector3 planepts[3]; - - planepts[2][(axis + 1) % 3] = mins[(axis + 1) % 3]; - planepts[2][(axis + 2) % 3] = mins[(axis + 2) % 3]; - planepts[2][axis] = maxs[axis]; - planepts[1][(axis + 1) % 3] = maxs[(axis + 1) % 3]; - planepts[1][(axis + 2) % 3] = mins[(axis + 2) % 3]; - planepts[1][axis] = maxs[axis]; - planepts[0][(axis + 1) % 3] = maxs[(axis + 1) % 3]; - planepts[0][(axis + 2) % 3] = maxs[(axis + 2) % 3]; - planepts[0][axis] = maxs[axis]; - - brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); - - planepts[0][(axis + 1) % 3] = mins[(axis + 1) % 3]; - planepts[0][(axis + 2) % 3] = mins[(axis + 2) % 3]; - planepts[0][axis] = mins[axis]; - planepts[1][(axis + 1) % 3] = maxs[(axis + 1) % 3]; - planepts[1][(axis + 2) % 3] = mins[(axis + 2) % 3]; - planepts[1][axis] = mins[axis]; - planepts[2][(axis + 1) % 3] = maxs[(axis + 1) % 3]; - planepts[2][(axis + 2) % 3] = maxs[(axis + 2) % 3]; - planepts[2][axis] = mins[axis]; - - brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); - - for (std::size_t i = 0; i < sides; ++i) { - double sv = sin(i * 3.14159265 * 2 / sides); - double cv = cos(i * 3.14159265 * 2 / sides); - - planepts[0][(axis + 1) % 3] = static_cast( floor(mid[(axis + 1) % 3] + radius * cv + 0.5)); - planepts[0][(axis + 2) % 3] = static_cast( floor(mid[(axis + 2) % 3] + radius * sv + 0.5)); - planepts[0][axis] = mins[axis]; - - planepts[1][(axis + 1) % 3] = planepts[0][(axis + 1) % 3]; - planepts[1][(axis + 2) % 3] = planepts[0][(axis + 2) % 3]; - planepts[1][axis] = maxs[axis]; - - planepts[2][(axis + 1) % 3] = static_cast( floor(planepts[0][(axis + 1) % 3] - radius * sv + 0.5)); - planepts[2][(axis + 2) % 3] = static_cast( floor(planepts[0][(axis + 2) % 3] + radius * cv + 0.5)); - planepts[2][axis] = maxs[axis]; - - brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); - } +const char* const c_brushPrism_name = "brushPrism"; + +void Brush_ConstructPrism( Brush& brush, const AABB& bounds, std::size_t sides, int axis, const char* shader, const TextureProjection& projection ){ + if ( sides < c_brushPrism_minSides ) { + globalErrorStream() << c_brushPrism_name << ": sides " << Unsigned( sides ) << ": too few sides, minimum is " << Unsigned( c_brushPrism_minSides ) << "\n"; + return; + } + if ( sides > c_brushPrism_maxSides ) { + globalErrorStream() << c_brushPrism_name << ": sides " << Unsigned( sides ) << ": too many sides, maximum is " << Unsigned( c_brushPrism_maxSides ) << "\n"; + return; + } + + brush.clear(); + brush.reserve( sides + 2 ); + + Vector3 mins( vector3_subtracted( bounds.origin, bounds.extents ) ); + Vector3 maxs( vector3_added( bounds.origin, bounds.extents ) ); + + float radius = max_extent_2d( bounds.extents, axis ); + const Vector3& mid = bounds.origin; + Vector3 planepts[3]; + + planepts[2][( axis + 1 ) % 3] = mins[( axis + 1 ) % 3]; + planepts[2][( axis + 2 ) % 3] = mins[( axis + 2 ) % 3]; + planepts[2][axis] = maxs[axis]; + planepts[1][( axis + 1 ) % 3] = maxs[( axis + 1 ) % 3]; + planepts[1][( axis + 2 ) % 3] = mins[( axis + 2 ) % 3]; + planepts[1][axis] = maxs[axis]; + planepts[0][( axis + 1 ) % 3] = maxs[( axis + 1 ) % 3]; + planepts[0][( axis + 2 ) % 3] = maxs[( axis + 2 ) % 3]; + planepts[0][axis] = maxs[axis]; + + brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); + + planepts[0][( axis + 1 ) % 3] = mins[( axis + 1 ) % 3]; + planepts[0][( axis + 2 ) % 3] = mins[( axis + 2 ) % 3]; + planepts[0][axis] = mins[axis]; + planepts[1][( axis + 1 ) % 3] = maxs[( axis + 1 ) % 3]; + planepts[1][( axis + 2 ) % 3] = mins[( axis + 2 ) % 3]; + planepts[1][axis] = mins[axis]; + planepts[2][( axis + 1 ) % 3] = maxs[( axis + 1 ) % 3]; + planepts[2][( axis + 2 ) % 3] = maxs[( axis + 2 ) % 3]; + planepts[2][axis] = mins[axis]; + + brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); + + for ( std::size_t i = 0 ; i < sides ; ++i ) + { + double sv = sin( i * 3.14159265 * 2 / sides ); + double cv = cos( i * 3.14159265 * 2 / sides ); + + planepts[0][( axis + 1 ) % 3] = static_cast( floor( mid[( axis + 1 ) % 3] + radius * cv + 0.5 ) ); + planepts[0][( axis + 2 ) % 3] = static_cast( floor( mid[( axis + 2 ) % 3] + radius * sv + 0.5 ) ); + planepts[0][axis] = mins[axis]; + + planepts[1][( axis + 1 ) % 3] = planepts[0][( axis + 1 ) % 3]; + planepts[1][( axis + 2 ) % 3] = planepts[0][( axis + 2 ) % 3]; + planepts[1][axis] = maxs[axis]; + + planepts[2][( axis + 1 ) % 3] = static_cast( floor( planepts[0][( axis + 1 ) % 3] - radius * sv + 0.5 ) ); + planepts[2][( axis + 2 ) % 3] = static_cast( floor( planepts[0][( axis + 2 ) % 3] + radius * cv + 0.5 ) ); + planepts[2][axis] = maxs[axis]; + + brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); + } } const std::size_t c_brushCone_minSides = 3; const std::size_t c_brushCone_maxSides = 32; -const char *const c_brushCone_name = "brushCone"; +const char* const c_brushCone_name = "brushCone"; -void Brush_ConstructCone(Brush &brush, const AABB &bounds, std::size_t sides, const char *shader, - const TextureProjection &projection) -{ - if (sides < c_brushCone_minSides) { - globalErrorStream() << c_brushCone_name << ": sides " << Unsigned(sides) << ": too few sides, minimum is " - << Unsigned(c_brushCone_minSides) << "\n"; - return; - } - if (sides > c_brushCone_maxSides) { - globalErrorStream() << c_brushCone_name << ": sides " << Unsigned(sides) << ": too many sides, maximum is " - << Unsigned(c_brushCone_maxSides) << "\n"; - return; - } - - brush.clear(); - brush.reserve(sides + 1); - - Vector3 mins(vector3_subtracted(bounds.origin, bounds.extents)); - Vector3 maxs(vector3_added(bounds.origin, bounds.extents)); - - float radius = max_extent(bounds.extents); - const Vector3 &mid = bounds.origin; - Vector3 planepts[3]; - - planepts[0][0] = mins[0]; - planepts[0][1] = mins[1]; - planepts[0][2] = mins[2]; - planepts[1][0] = maxs[0]; - planepts[1][1] = mins[1]; - planepts[1][2] = mins[2]; - planepts[2][0] = maxs[0]; - planepts[2][1] = maxs[1]; - planepts[2][2] = mins[2]; - - brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); - - for (std::size_t i = 0; i < sides; ++i) { - double sv = sin(i * 3.14159265 * 2 / sides); - double cv = cos(i * 3.14159265 * 2 / sides); - - planepts[0][0] = static_cast( floor(mid[0] + radius * cv + 0.5)); - planepts[0][1] = static_cast( floor(mid[1] + radius * sv + 0.5)); - planepts[0][2] = mins[2]; - - planepts[1][0] = mid[0]; - planepts[1][1] = mid[1]; - planepts[1][2] = maxs[2]; - - planepts[2][0] = static_cast( floor(planepts[0][0] - radius * sv + 0.5)); - planepts[2][1] = static_cast( floor(planepts[0][1] + radius * cv + 0.5)); - planepts[2][2] = maxs[2]; - - brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); - } -} +void Brush_ConstructCone( Brush& brush, const AABB& bounds, std::size_t sides, const char* shader, const TextureProjection& projection ){ + if ( sides < c_brushCone_minSides ) { + globalErrorStream() << c_brushCone_name << ": sides " << Unsigned( sides ) << ": too few sides, minimum is " << Unsigned( c_brushCone_minSides ) << "\n"; + return; + } + if ( sides > c_brushCone_maxSides ) { + globalErrorStream() << c_brushCone_name << ": sides " << Unsigned( sides ) << ": too many sides, maximum is " << Unsigned( c_brushCone_maxSides ) << "\n"; + return; + } -const std::size_t c_brushSphere_minSides = 3; -const std::size_t c_brushSphere_maxSides = 31; -const char *const c_brushSphere_name = "brushSphere"; + brush.clear(); + brush.reserve( sides + 1 ); -void Brush_ConstructSphere(Brush &brush, const AABB &bounds, std::size_t sides, const char *shader, - const TextureProjection &projection) -{ - if (sides < c_brushSphere_minSides) { - globalErrorStream() << c_brushSphere_name << ": sides " << Unsigned(sides) << ": too few sides, minimum is " - << Unsigned(c_brushSphere_minSides) << "\n"; - return; - } - if (sides > c_brushSphere_maxSides) { - globalErrorStream() << c_brushSphere_name << ": sides " << Unsigned(sides) << ": too many sides, maximum is " - << Unsigned(c_brushSphere_maxSides) << "\n"; - return; - } - - brush.clear(); - brush.reserve(sides * sides); - - float radius = max_extent(bounds.extents); - const Vector3 &mid = bounds.origin; - Vector3 planepts[3]; - - double dt = 2 * c_pi / sides; - double dp = c_pi / sides; - for (std::size_t i = 0; i < sides; i++) { - for (std::size_t j = 0; j < sides - 1; j++) { - double t = i * dt; - double p = float(j * dp - c_pi / 2); - - planepts[0] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t, p), radius)); - planepts[1] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t, p + dp), radius)); - planepts[2] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t + dt, p + dp), radius)); - - brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); - } - } - - { - double p = (sides - 1) * dp - c_pi / 2; - for (std::size_t i = 0; i < sides; i++) { - double t = i * dt; - - planepts[0] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t, p), radius)); - planepts[1] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t + dt, p + dp), radius)); - planepts[2] = vector3_added(mid, vector3_scaled(vector3_for_spherical(t + dt, p), radius)); - - brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); - } - } -} + Vector3 mins( vector3_subtracted( bounds.origin, bounds.extents ) ); + Vector3 maxs( vector3_added( bounds.origin, bounds.extents ) ); -const std::size_t c_brushRock_minSides = 10; -const std::size_t c_brushRock_maxSides = 1000; -const char *const c_brushRock_name = "brushRock"; + float radius = max_extent( bounds.extents ); + const Vector3& mid = bounds.origin; + Vector3 planepts[3]; -void Brush_ConstructRock(Brush &brush, const AABB &bounds, std::size_t sides, const char *shader, - const TextureProjection &projection) -{ - if (sides < c_brushRock_minSides) { - globalErrorStream() << c_brushRock_name << ": sides " << Unsigned(sides) << ": too few sides, minimum is " - << Unsigned(c_brushRock_minSides) << "\n"; - return; - } - if (sides > c_brushRock_maxSides) { - globalErrorStream() << c_brushRock_name << ": sides " << Unsigned(sides) << ": too many sides, maximum is " - << Unsigned(c_brushRock_maxSides) << "\n"; - return; - } - - brush.clear(); - brush.reserve(sides * sides); - - float radius = max_extent(bounds.extents); - const Vector3 &mid = bounds.origin; - Vector3 planepts[3]; - - for (std::size_t j = 0; j < sides; j++) { - planepts[0][0] = rand() - (RAND_MAX / 2); - planepts[0][1] = rand() - (RAND_MAX / 2); - planepts[0][2] = rand() - (RAND_MAX / 2); - vector3_normalise(planepts[0]); - - // find two vectors that are perpendicular to planepts[0] - ComputeAxisBase(planepts[0], planepts[1], planepts[2]); - - planepts[0] = vector3_added(mid, vector3_scaled(planepts[0], radius)); - planepts[1] = vector3_added(planepts[0], vector3_scaled(planepts[1], radius)); - planepts[2] = vector3_added(planepts[0], vector3_scaled(planepts[2], radius)); + planepts[0][0] = mins[0]; planepts[0][1] = mins[1]; planepts[0][2] = mins[2]; + planepts[1][0] = maxs[0]; planepts[1][1] = mins[1]; planepts[1][2] = mins[2]; + planepts[2][0] = maxs[0]; planepts[2][1] = maxs[1]; planepts[2][2] = mins[2]; -#if 0 - // make sure the orientation is right - if ( vector3_dot( vector3_subtracted( planepts[0], mid ), vector3_cross( vector3_subtracted( planepts[1], mid ), vector3_subtracted( planepts[2], mid ) ) ) > 0 ) { - Vector3 h; - h = planepts[1]; - planepts[1] = planepts[2]; - planepts[2] = h; - globalOutputStream() << "flip\n"; - } - else{ - globalOutputStream() << "no flip\n"; - } -#endif + brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); - brush.addPlane(planepts[0], planepts[1], planepts[2], shader, projection); - } -} + for ( std::size_t i = 0 ; i < sides ; ++i ) + { + double sv = sin( i * 3.14159265 * 2 / sides ); + double cv = cos( i * 3.14159265 * 2 / sides ); -int GetViewAxis() -{ - switch (GlobalXYWnd_getCurrentViewType()) { - case XY: - return 2; - case XZ: - return 1; - case YZ: - return 0; - } - return 2; -} - -void Brush_ConstructPrefab(Brush &brush, EBrushPrefab type, const AABB &bounds, std::size_t sides, const char *shader, - const TextureProjection &projection) -{ - switch (type) { - case eBrushCuboid: { - UndoableCommand undo("brushCuboid"); - - Brush_ConstructCuboid(brush, bounds, shader, projection); - } - break; - case eBrushPrism: { - int axis = GetViewAxis(); - StringOutputStream command; - command << c_brushPrism_name << " -sides " << Unsigned(sides) << " -axis " << axis; - UndoableCommand undo(command.c_str()); - - Brush_ConstructPrism(brush, bounds, sides, axis, shader, projection); - } - break; - case eBrushCone: { - StringOutputStream command; - command << c_brushCone_name << " -sides " << Unsigned(sides); - UndoableCommand undo(command.c_str()); - - Brush_ConstructCone(brush, bounds, sides, shader, projection); - } - break; - case eBrushSphere: { - StringOutputStream command; - command << c_brushSphere_name << " -sides " << Unsigned(sides); - UndoableCommand undo(command.c_str()); - - Brush_ConstructSphere(brush, bounds, sides, shader, projection); - } - break; - case eBrushRock: { - StringOutputStream command; - command << c_brushRock_name << " -sides " << Unsigned(sides); - UndoableCommand undo(command.c_str()); - - Brush_ConstructRock(brush, bounds, sides, shader, projection); - } - break; - } -} - - -void ConstructRegionBrushes(scene::Node *brushes[6], const Vector3 ®ion_mins, const Vector3 ®ion_maxs) -{ - { - // set mins - Vector3 mins(region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32); - - // vary maxs - for (std::size_t i = 0; i < 3; i++) { - Vector3 maxs(region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32); - maxs[i] = region_mins[i]; - Brush_ConstructCuboid(*Node_getBrush(*brushes[i]), aabb_for_minmax(mins, maxs), texdef_name_default(), - TextureProjection()); - } - } - - { - // set maxs - Vector3 maxs(region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32); - - // vary mins - for (std::size_t i = 0; i < 3; i++) { - Vector3 mins(region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32); - mins[i] = region_maxs[i]; - Brush_ConstructCuboid(*Node_getBrush(*brushes[i + 3]), aabb_for_minmax(mins, maxs), texdef_name_default(), - TextureProjection()); - } - } -} - - -void Scene_BrushSetTexdef_Selected(scene::Graph &graph, const TextureProjection &projection) -{ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.SetTexdef(projection); - }); - SceneChangeNotify(); -} + planepts[0][0] = static_cast( floor( mid[0] + radius * cv + 0.5 ) ); + planepts[0][1] = static_cast( floor( mid[1] + radius * sv + 0.5 ) ); + planepts[0][2] = mins[2]; -void Scene_BrushSetTexdef_Component_Selected(scene::Graph &graph, const TextureProjection &projection) -{ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.SetTexdef(projection); - }); - SceneChangeNotify(); -} + planepts[1][0] = mid[0]; + planepts[1][1] = mid[1]; + planepts[1][2] = maxs[2]; + planepts[2][0] = static_cast( floor( planepts[0][0] - radius * sv + 0.5 ) ); + planepts[2][1] = static_cast( floor( planepts[0][1] + radius * cv + 0.5 ) ); + planepts[2][2] = maxs[2]; -void Scene_BrushSetFlags_Selected(scene::Graph &graph, const ContentsFlagsValue &flags) -{ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.SetFlags(flags); - }); - SceneChangeNotify(); + brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); + } } -void Scene_BrushSetFlags_Component_Selected(scene::Graph &graph, const ContentsFlagsValue &flags) -{ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.SetFlags(flags); - }); - SceneChangeNotify(); +const std::size_t c_brushSphere_minSides = 3; +const std::size_t c_brushSphere_maxSides = 31; +const char* const c_brushSphere_name = "brushSphere"; + +void Brush_ConstructSphere( Brush& brush, const AABB& bounds, std::size_t sides, const char* shader, const TextureProjection& projection ){ + if ( sides < c_brushSphere_minSides ) { + globalErrorStream() << c_brushSphere_name << ": sides " << Unsigned( sides ) << ": too few sides, minimum is " << Unsigned( c_brushSphere_minSides ) << "\n"; + return; + } + if ( sides > c_brushSphere_maxSides ) { + globalErrorStream() << c_brushSphere_name << ": sides " << Unsigned( sides ) << ": too many sides, maximum is " << Unsigned( c_brushSphere_maxSides ) << "\n"; + return; + } + + brush.clear(); + brush.reserve( sides * sides ); + + float radius = max_extent( bounds.extents ); + const Vector3& mid = bounds.origin; + Vector3 planepts[3]; + + double dt = 2 * c_pi / sides; + double dp = c_pi / sides; + for ( std::size_t i = 0; i < sides; i++ ) + { + for ( std::size_t j = 0; j < sides - 1; j++ ) + { + double t = i * dt; + double p = float(j * dp - c_pi / 2); + + planepts[0] = vector3_added( mid, vector3_scaled( vector3_for_spherical( t, p ), radius ) ); + planepts[1] = vector3_added( mid, vector3_scaled( vector3_for_spherical( t, p + dp ), radius ) ); + planepts[2] = vector3_added( mid, vector3_scaled( vector3_for_spherical( t + dt, p + dp ), radius ) ); + + brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); + } + } + + { + double p = ( sides - 1 ) * dp - c_pi / 2; + for ( std::size_t i = 0; i < sides; i++ ) + { + double t = i * dt; + + planepts[0] = vector3_added( mid, vector3_scaled( vector3_for_spherical( t, p ), radius ) ); + planepts[1] = vector3_added( mid, vector3_scaled( vector3_for_spherical( t + dt, p + dp ), radius ) ); + planepts[2] = vector3_added( mid, vector3_scaled( vector3_for_spherical( t + dt, p ), radius ) ); + + brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); + } + } } -void Scene_BrushShiftTexdef_Selected(scene::Graph &graph, float s, float t) -{ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.ShiftTexdef(s, t); - }); - SceneChangeNotify(); -} +const std::size_t c_brushRock_minSides = 10; +const std::size_t c_brushRock_maxSides = 1000; +const char* const c_brushRock_name = "brushRock"; + +void Brush_ConstructRock( Brush& brush, const AABB& bounds, std::size_t sides, const char* shader, const TextureProjection& projection ){ + if ( sides < c_brushRock_minSides ) { + globalErrorStream() << c_brushRock_name << ": sides " << Unsigned( sides ) << ": too few sides, minimum is " << Unsigned( c_brushRock_minSides ) << "\n"; + return; + } + if ( sides > c_brushRock_maxSides ) { + globalErrorStream() << c_brushRock_name << ": sides " << Unsigned( sides ) << ": too many sides, maximum is " << Unsigned( c_brushRock_maxSides ) << "\n"; + return; + } + + brush.clear(); + brush.reserve( sides * sides ); + + float radius = max_extent( bounds.extents ); + const Vector3& mid = bounds.origin; + Vector3 planepts[3]; + + for ( std::size_t j = 0; j < sides; j++ ) + { + planepts[0][0] = rand() - ( RAND_MAX / 2 ); + planepts[0][1] = rand() - ( RAND_MAX / 2 ); + planepts[0][2] = rand() - ( RAND_MAX / 2 ); + vector3_normalise( planepts[0] ); + + // find two vectors that are perpendicular to planepts[0] + ComputeAxisBase( planepts[0], planepts[1], planepts[2] ); + + planepts[0] = vector3_added( mid, vector3_scaled( planepts[0], radius ) ); + planepts[1] = vector3_added( planepts[0], vector3_scaled( planepts[1], radius ) ); + planepts[2] = vector3_added( planepts[0], vector3_scaled( planepts[2], radius ) ); -void Scene_BrushShiftTexdef_Component_Selected(scene::Graph &graph, float s, float t) -{ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.ShiftTexdef(s, t); - }); - SceneChangeNotify(); +#if 0 + // make sure the orientation is right + if ( vector3_dot( vector3_subtracted( planepts[0], mid ), vector3_cross( vector3_subtracted( planepts[1], mid ), vector3_subtracted( planepts[2], mid ) ) ) > 0 ) { + Vector3 h; + h = planepts[1]; + planepts[1] = planepts[2]; + planepts[2] = h; + globalOutputStream() << "flip\n"; + } + else{ + globalOutputStream() << "no flip\n"; + } +#endif + + brush.addPlane( planepts[0], planepts[1], planepts[2], shader, projection ); + } +} + +int GetViewAxis(){ + switch ( GlobalXYWnd_getCurrentViewType() ) + { + case XY: + return 2; + case XZ: + return 1; + case YZ: + return 0; + } + return 2; +} + +void Brush_ConstructPrefab( Brush& brush, EBrushPrefab type, const AABB& bounds, std::size_t sides, const char* shader, const TextureProjection& projection ){ + switch ( type ) + { + case eBrushCuboid: + { + UndoableCommand undo( "brushCuboid" ); + + Brush_ConstructCuboid( brush, bounds, shader, projection ); + } + break; + case eBrushPrism: + { + int axis = GetViewAxis(); + StringOutputStream command; + command << c_brushPrism_name << " -sides " << Unsigned( sides ) << " -axis " << axis; + UndoableCommand undo( command.c_str() ); + + Brush_ConstructPrism( brush, bounds, sides, axis, shader, projection ); + } + break; + case eBrushCone: + { + StringOutputStream command; + command << c_brushCone_name << " -sides " << Unsigned( sides ); + UndoableCommand undo( command.c_str() ); + + Brush_ConstructCone( brush, bounds, sides, shader, projection ); + } + break; + case eBrushSphere: + { + StringOutputStream command; + command << c_brushSphere_name << " -sides " << Unsigned( sides ); + UndoableCommand undo( command.c_str() ); + + Brush_ConstructSphere( brush, bounds, sides, shader, projection ); + } + break; + case eBrushRock: + { + StringOutputStream command; + command << c_brushRock_name << " -sides " << Unsigned( sides ); + UndoableCommand undo( command.c_str() ); + + Brush_ConstructRock( brush, bounds, sides, shader, projection ); + } + break; + } +} + + +void ConstructRegionBrushes( scene::Node* brushes[6], const Vector3& region_mins, const Vector3& region_maxs ){ + { + // set mins + Vector3 mins( region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32 ); + + // vary maxs + for ( std::size_t i = 0; i < 3; i++ ) + { + Vector3 maxs( region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32 ); + maxs[i] = region_mins[i]; + Brush_ConstructCuboid( *Node_getBrush( *brushes[i] ), aabb_for_minmax( mins, maxs ), texdef_name_default(), TextureProjection() ); + } + } + + { + // set maxs + Vector3 maxs( region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32 ); + + // vary mins + for ( std::size_t i = 0; i < 3; i++ ) + { + Vector3 mins( region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32 ); + mins[i] = region_maxs[i]; + Brush_ConstructCuboid( *Node_getBrush( *brushes[i + 3] ), aabb_for_minmax( mins, maxs ), texdef_name_default(), TextureProjection() ); + } + } +} + + +void Scene_BrushSetTexdef_Selected( scene::Graph& graph, const TextureProjection& projection ){ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.SetTexdef(projection); + }); + SceneChangeNotify(); +} + +void Scene_BrushSetTexdef_Component_Selected( scene::Graph& graph, const TextureProjection& projection ){ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.SetTexdef(projection); + }); + SceneChangeNotify(); +} + + +void Scene_BrushSetFlags_Selected( scene::Graph& graph, const ContentsFlagsValue& flags ){ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.SetFlags(flags); + }); + SceneChangeNotify(); +} + +void Scene_BrushSetFlags_Component_Selected( scene::Graph& graph, const ContentsFlagsValue& flags ){ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.SetFlags(flags); + }); + SceneChangeNotify(); +} + +void Scene_BrushShiftTexdef_Selected( scene::Graph& graph, float s, float t ){ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.ShiftTexdef(s, t); + }); + SceneChangeNotify(); +} + +void Scene_BrushShiftTexdef_Component_Selected( scene::Graph& graph, float s, float t ){ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.ShiftTexdef(s, t); + }); + SceneChangeNotify(); } -void Scene_BrushScaleTexdef_Selected(scene::Graph &graph, float s, float t) -{ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.ScaleTexdef(s, t); - }); - SceneChangeNotify(); +void Scene_BrushScaleTexdef_Selected( scene::Graph& graph, float s, float t ){ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.ScaleTexdef(s, t); + }); + SceneChangeNotify(); } -void Scene_BrushScaleTexdef_Component_Selected(scene::Graph &graph, float s, float t) -{ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.ScaleTexdef(s, t); - }); - SceneChangeNotify(); +void Scene_BrushScaleTexdef_Component_Selected( scene::Graph& graph, float s, float t ){ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.ScaleTexdef(s, t); + }); + SceneChangeNotify(); } -void Scene_BrushRotateTexdef_Selected(scene::Graph &graph, float angle) -{ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.RotateTexdef(angle); - }); - SceneChangeNotify(); +void Scene_BrushRotateTexdef_Selected( scene::Graph& graph, float angle ){ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.RotateTexdef(angle); + }); + SceneChangeNotify(); } -void Scene_BrushRotateTexdef_Component_Selected(scene::Graph &graph, float angle) -{ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.RotateTexdef(angle); - }); - SceneChangeNotify(); +void Scene_BrushRotateTexdef_Component_Selected( scene::Graph& graph, float angle ){ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.RotateTexdef(angle); + }); + SceneChangeNotify(); } -void Scene_BrushSetShader_Selected(scene::Graph &graph, const char *name) -{ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.SetShader(name); - }); - SceneChangeNotify(); +void Scene_BrushSetShader_Selected( scene::Graph& graph, const char* name ){ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.SetShader(name); + }); + SceneChangeNotify(); } -void Scene_BrushSetShader_Component_Selected(scene::Graph &graph, const char *name) -{ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.SetShader(name); - }); - SceneChangeNotify(); +void Scene_BrushSetShader_Component_Selected( scene::Graph& graph, const char* name ){ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.SetShader(name); + }); + SceneChangeNotify(); } -void Scene_BrushSetDetail_Selected(scene::Graph &graph, bool detail) -{ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.setDetail(detail); - }); - SceneChangeNotify(); +void Scene_BrushSetDetail_Selected( scene::Graph& graph, bool detail ){ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.setDetail(detail); + }); + SceneChangeNotify(); } -bool Face_FindReplaceShader(Face &face, const char *find, const char *replace) -{ - if (shader_equal(face.GetShader(), find)) { - face.SetShader(replace); - return true; - } - return false; +bool Face_FindReplaceShader( Face& face, const char* find, const char* replace ){ + if ( shader_equal( face.GetShader(), find ) ) { + face.SetShader( replace ); + return true; + } + return false; } -bool DoingSearch(const char *repl) -{ - return (repl == NULL || (strcmp("textures/", repl) == 0)); +bool DoingSearch( const char *repl ){ + return ( repl == NULL || ( strcmp( "textures/", repl ) == 0 ) ); } -void Scene_BrushFindReplaceShader(scene::Graph &graph, const char *find, const char *replace) -{ - if (DoingSearch(replace)) { - Scene_ForEachBrush_ForEachFaceInstance(graph, [&](FaceInstance &faceinst) { - if (shader_equal(faceinst.getFace().GetShader(), find)) { - faceinst.setSelected(SelectionSystem::eFace, true); - } - }); - } else { - Scene_ForEachBrush_ForEachFace(graph, [&](Face &face) { Face_FindReplaceShader(face, find, replace); }); - } -} - -void Scene_BrushFindReplaceShader_Selected(scene::Graph &graph, const char *find, const char *replace) -{ - if (DoingSearch(replace)) { - Scene_ForEachSelectedBrush_ForEachFaceInstance(graph, [&](FaceInstance &faceinst) { - if (shader_equal(faceinst.getFace().GetShader(), find)) { - faceinst.setSelected(SelectionSystem::eFace, true); - } - }); - } else { - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - Face_FindReplaceShader(face, find, replace); - }); - } +void Scene_BrushFindReplaceShader( scene::Graph& graph, const char* find, const char* replace ){ + if ( DoingSearch( replace ) ) { + Scene_ForEachBrush_ForEachFaceInstance(graph, [&](FaceInstance &faceinst) { + if (shader_equal(faceinst.getFace().GetShader(), find)) { + faceinst.setSelected(SelectionSystem::eFace, true); + } + }); + } + else + { + Scene_ForEachBrush_ForEachFace(graph, [&](Face &face) { Face_FindReplaceShader(face, find, replace); }); + } +} + +void Scene_BrushFindReplaceShader_Selected( scene::Graph& graph, const char* find, const char* replace ){ + if ( DoingSearch( replace ) ) { + Scene_ForEachSelectedBrush_ForEachFaceInstance(graph, [&](FaceInstance &faceinst) { + if (shader_equal(faceinst.getFace().GetShader(), find)) { + faceinst.setSelected(SelectionSystem::eFace, true); + } + }); + } + else + { + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + Face_FindReplaceShader(face, find, replace); + }); + } } // TODO: find for components // d1223m: dont even know what they are... -void Scene_BrushFindReplaceShader_Component_Selected(scene::Graph &graph, const char *find, const char *replace) -{ - if (DoingSearch(replace)) { +void Scene_BrushFindReplaceShader_Component_Selected( scene::Graph& graph, const char* find, const char* replace ){ + if ( DoingSearch( replace ) ) { - } else { - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - Face_FindReplaceShader(face, find, replace); - }); - } + } + else + { + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + Face_FindReplaceShader(face, find, replace); + }); + } } -void Scene_BrushFitTexture_Selected(scene::Graph &graph, float s_repeat, float t_repeat) -{ - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - face.FitTexture(s_repeat, t_repeat); - }); - SceneChangeNotify(); +void Scene_BrushFitTexture_Selected( scene::Graph& graph, float s_repeat, float t_repeat ){ + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + face.FitTexture(s_repeat, t_repeat); + }); + SceneChangeNotify(); } -void Scene_BrushFitTexture_Component_Selected(scene::Graph &graph, float s_repeat, float t_repeat) -{ - Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { - face.FitTexture(s_repeat, t_repeat); - }); - SceneChangeNotify(); +void Scene_BrushFitTexture_Component_Selected( scene::Graph& graph, float s_repeat, float t_repeat ){ + Scene_ForEachSelectedBrushFace(graph, [&](Face &face) { + face.FitTexture(s_repeat, t_repeat); + }); + SceneChangeNotify(); } TextureProjection g_defaultTextureProjection; -const TextureProjection &TextureTransform_getDefault() -{ - TexDef_Construct_Default(g_defaultTextureProjection); - return g_defaultTextureProjection; +const TextureProjection& TextureTransform_getDefault(){ + TexDef_Construct_Default( g_defaultTextureProjection ); + return g_defaultTextureProjection; } -void Scene_BrushConstructPrefab(scene::Graph &graph, EBrushPrefab type, std::size_t sides, const char *shader) -{ - if (GlobalSelectionSystem().countSelected() != 0) { - const scene::Path &path = GlobalSelectionSystem().ultimateSelected().path(); +void Scene_BrushConstructPrefab( scene::Graph& graph, EBrushPrefab type, std::size_t sides, const char* shader ){ + if ( GlobalSelectionSystem().countSelected() != 0 ) { + const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path(); - Brush *brush = Node_getBrush(path.top()); - if (brush != 0) { - AABB bounds = brush->localAABB(); // copy bounds because the brush will be modified - Brush_ConstructPrefab(*brush, type, bounds, sides, shader, TextureTransform_getDefault()); - SceneChangeNotify(); - } - } + Brush* brush = Node_getBrush( path.top() ); + if ( brush != 0 ) { + AABB bounds = brush->localAABB(); // copy bounds because the brush will be modified + Brush_ConstructPrefab( *brush, type, bounds, sides, shader, TextureTransform_getDefault() ); + SceneChangeNotify(); + } + } } -void Scene_BrushResize_Selected(scene::Graph &graph, const AABB &bounds, const char *shader) -{ - if (GlobalSelectionSystem().countSelected() != 0) { - const scene::Path &path = GlobalSelectionSystem().ultimateSelected().path(); +void Scene_BrushResize_Selected( scene::Graph& graph, const AABB& bounds, const char* shader ){ + if ( GlobalSelectionSystem().countSelected() != 0 ) { + const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path(); - Brush *brush = Node_getBrush(path.top()); - if (brush != 0) { - Brush_ConstructCuboid(*brush, bounds, shader, TextureTransform_getDefault()); - SceneChangeNotify(); - } - } + Brush* brush = Node_getBrush( path.top() ); + if ( brush != 0 ) { + Brush_ConstructCuboid( *brush, bounds, shader, TextureTransform_getDefault() ); + SceneChangeNotify(); + } + } } -bool Brush_hasShader(const Brush &brush, const char *name) -{ - for (Brush::const_iterator i = brush.begin(); i != brush.end(); ++i) { - if (shader_equal((*i)->GetShader(), name)) { - return true; - } - } - return false; +bool Brush_hasShader( const Brush& brush, const char* name ){ + for ( Brush::const_iterator i = brush.begin(); i != brush.end(); ++i ) + { + if ( shader_equal( ( *i )->GetShader(), name ) ) { + return true; + } + } + return false; } -class BrushSelectByShaderWalker : public scene::Graph::Walker { - const char *m_name; +class BrushSelectByShaderWalker : public scene::Graph::Walker +{ +const char* m_name; public: - BrushSelectByShaderWalker(const char *name) - : m_name(name) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - if (path.top().get().visible()) { - Brush *brush = Node_getBrush(path.top()); - if (brush != 0 && Brush_hasShader(*brush, m_name)) { - Instance_getSelectable(instance)->setSelected(true); - } - } - return true; - } +BrushSelectByShaderWalker( const char* name ) + : m_name( name ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get().visible() ) { + Brush* brush = Node_getBrush( path.top() ); + if ( brush != 0 && Brush_hasShader( *brush, m_name ) ) { + Instance_getSelectable( instance )->setSelected( true ); + } + } + return true; +} }; -void Scene_BrushSelectByShader(scene::Graph &graph, const char *name) -{ - graph.traverse(BrushSelectByShaderWalker(name)); +void Scene_BrushSelectByShader( scene::Graph& graph, const char* name ){ + graph.traverse( BrushSelectByShaderWalker( name ) ); } -void Scene_BrushSelectByShader_Component(scene::Graph &graph, const char *name) -{ - Scene_ForEachSelectedBrush_ForEachFaceInstance(graph, [&](FaceInstance &face) { - printf("checking %s = %s\n", face.getFace().GetShader(), name); - if (shader_equal(face.getFace().GetShader(), name)) { - face.setSelected(SelectionSystem::eFace, true); - } - }); +void Scene_BrushSelectByShader_Component( scene::Graph& graph, const char* name ){ + Scene_ForEachSelectedBrush_ForEachFaceInstance(graph, [&](FaceInstance &face) { + printf("checking %s = %s\n", face.getFace().GetShader(), name); + if (shader_equal(face.getFace().GetShader(), name)) { + face.setSelected(SelectionSystem::eFace, true); + } + }); } -void Scene_BrushGetTexdef_Selected(scene::Graph &graph, TextureProjection &projection) -{ - bool done = false; - Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { - if (!done) { - done = true; - face.GetTexdef(projection); - } - }); +void Scene_BrushGetTexdef_Selected( scene::Graph& graph, TextureProjection& projection ){ + bool done = false; + Scene_ForEachSelectedBrush_ForEachFace(graph, [&](Face &face) { + if (!done) { + done = true; + face.GetTexdef(projection); + } + }); } -void Scene_BrushGetTexdef_Component_Selected(scene::Graph &graph, TextureProjection &projection) -{ +void Scene_BrushGetTexdef_Component_Selected( scene::Graph& graph, TextureProjection& projection ){ #if 1 - if (!g_SelectedFaceInstances.empty()) { - FaceInstance &faceInstance = g_SelectedFaceInstances.last(); - faceInstance.getFace().GetTexdef(projection); - } + if ( !g_SelectedFaceInstances.empty() ) { + FaceInstance& faceInstance = g_SelectedFaceInstances.last(); + faceInstance.getFace().GetTexdef( projection ); + } #else - FaceGetTexdef visitor( projection ); - Scene_ForEachSelectedBrushFace( graph, visitor ); + FaceGetTexdef visitor( projection ); + Scene_ForEachSelectedBrushFace( graph, visitor ); #endif } -void Scene_BrushGetShaderSize_Component_Selected(scene::Graph &graph, size_t &width, size_t &height) -{ - if (!g_SelectedFaceInstances.empty()) { - FaceInstance &faceInstance = g_SelectedFaceInstances.last(); - width = faceInstance.getFace().getShader().width(); - height = faceInstance.getFace().getShader().height(); - } +void Scene_BrushGetShaderSize_Component_Selected( scene::Graph& graph, size_t& width, size_t& height ){ + if ( !g_SelectedFaceInstances.empty() ) { + FaceInstance& faceInstance = g_SelectedFaceInstances.last(); + width = faceInstance.getFace().getShader().width(); + height = faceInstance.getFace().getShader().height(); + } } -void Scene_BrushGetFlags_Selected(scene::Graph &graph, ContentsFlagsValue &flags) -{ +void Scene_BrushGetFlags_Selected( scene::Graph& graph, ContentsFlagsValue& flags ){ #if 1 - if (GlobalSelectionSystem().countSelected() != 0) { - BrushInstance *brush = Instance_getBrush(GlobalSelectionSystem().ultimateSelected()); - if (brush != 0) { - bool done = false; - Brush_forEachFace(*brush, [&](Face &face) { - if (!done) { - done = true; - face.GetFlags(flags); - } - }); - } - } + if ( GlobalSelectionSystem().countSelected() != 0 ) { + BrushInstance* brush = Instance_getBrush( GlobalSelectionSystem().ultimateSelected() ); + if ( brush != 0 ) { + bool done = false; + Brush_forEachFace(*brush, [&](Face &face) { + if (!done) { + done = true; + face.GetFlags(flags); + } + }); + } + } #else - Scene_ForEachSelectedBrush_ForEachFace( graph, FaceGetFlags( flags ) ); + Scene_ForEachSelectedBrush_ForEachFace( graph, FaceGetFlags( flags ) ); #endif } -void Scene_BrushGetFlags_Component_Selected(scene::Graph &graph, ContentsFlagsValue &flags) -{ +void Scene_BrushGetFlags_Component_Selected( scene::Graph& graph, ContentsFlagsValue& flags ){ #if 1 - if (!g_SelectedFaceInstances.empty()) { - FaceInstance &faceInstance = g_SelectedFaceInstances.last(); - faceInstance.getFace().GetFlags(flags); - } + if ( !g_SelectedFaceInstances.empty() ) { + FaceInstance& faceInstance = g_SelectedFaceInstances.last(); + faceInstance.getFace().GetFlags( flags ); + } #else - Scene_ForEachSelectedBrushFace( graph, FaceGetFlags( flags ) ); + Scene_ForEachSelectedBrushFace( graph, FaceGetFlags( flags ) ); #endif } -void Scene_BrushGetShader_Selected(scene::Graph &graph, CopiedString &shader) -{ +void Scene_BrushGetShader_Selected( scene::Graph& graph, CopiedString& shader ){ #if 1 - if (GlobalSelectionSystem().countSelected() != 0) { - BrushInstance *brush = Instance_getBrush(GlobalSelectionSystem().ultimateSelected()); - if (brush != 0) { - bool done = false; - Brush_forEachFace(*brush, [&](Face &face) { - if (!done) { - done = true; - shader = face.GetShader(); - } - }); - } - } + if ( GlobalSelectionSystem().countSelected() != 0 ) { + BrushInstance* brush = Instance_getBrush( GlobalSelectionSystem().ultimateSelected() ); + if ( brush != 0 ) { + bool done = false; + Brush_forEachFace(*brush, [&](Face &face) { + if (!done) { + done = true; + shader = face.GetShader(); + } + }); + } + } #else - Scene_ForEachSelectedBrush_ForEachFace( graph, FaceGetShader( shader ) ); + Scene_ForEachSelectedBrush_ForEachFace( graph, FaceGetShader( shader ) ); #endif } -void Scene_BrushGetShader_Component_Selected(scene::Graph &graph, CopiedString &shader) -{ +void Scene_BrushGetShader_Component_Selected( scene::Graph& graph, CopiedString& shader ){ #if 1 - if (!g_SelectedFaceInstances.empty()) { - FaceInstance &faceInstance = g_SelectedFaceInstances.last(); - shader = faceInstance.getFace().GetShader(); - } + if ( !g_SelectedFaceInstances.empty() ) { + FaceInstance& faceInstance = g_SelectedFaceInstances.last(); + shader = faceInstance.getFace().GetShader(); + } #else - FaceGetShader visitor( shader ); - Scene_ForEachSelectedBrushFace( graph, visitor ); + FaceGetShader visitor( shader ); + Scene_ForEachSelectedBrushFace( graph, visitor ); #endif } -class filter_face_shader : public FaceFilter { - const char *m_shader; +class filter_face_shader : public FaceFilter +{ +const char* m_shader; public: - filter_face_shader(const char *shader) : m_shader(shader) - { - } - - bool filter(const Face &face) const - { - return shader_equal(face.GetShader(), m_shader); - } +filter_face_shader( const char* shader ) : m_shader( shader ){ +} + +bool filter( const Face& face ) const { + return shader_equal( face.GetShader(), m_shader ); +} }; -class filter_face_shader_prefix : public FaceFilter { - const char *m_prefix; +class filter_face_shader_prefix : public FaceFilter +{ +const char* m_prefix; public: - filter_face_shader_prefix(const char *prefix) : m_prefix(prefix) - { - } - - bool filter(const Face &face) const - { - return shader_equal_n(face.GetShader(), m_prefix, strlen(m_prefix)); - } +filter_face_shader_prefix( const char* prefix ) : m_prefix( prefix ){ +} + +bool filter( const Face& face ) const { + return shader_equal_n( face.GetShader(), m_prefix, strlen( m_prefix ) ); +} }; -class filter_face_flags : public FaceFilter { - int m_flags; +class filter_face_flags : public FaceFilter +{ +int m_flags; public: - filter_face_flags(int flags) : m_flags(flags) - { - } - - bool filter(const Face &face) const - { - return (face.getShader().shaderFlags() & m_flags) != 0; - } +filter_face_flags( int flags ) : m_flags( flags ){ +} + +bool filter( const Face& face ) const { + return ( face.getShader().shaderFlags() & m_flags ) != 0; +} }; -class filter_face_contents : public FaceFilter { - int m_contents; +class filter_face_contents : public FaceFilter +{ +int m_contents; public: - filter_face_contents(int contents) : m_contents(contents) - { - } - - bool filter(const Face &face) const - { - return (face.getShader().m_flags.m_contentFlags & m_contents) != 0; - } +filter_face_contents( int contents ) : m_contents( contents ){ +} + +bool filter( const Face& face ) const { + return ( face.getShader().m_flags.m_contentFlags & m_contents ) != 0; +} }; -class filter_brush_any_face : public BrushFilter { - FaceFilter *m_filter; + +class filter_brush_any_face : public BrushFilter +{ +FaceFilter* m_filter; public: - filter_brush_any_face(FaceFilter *filter) : m_filter(filter) - { - } - - bool filter(const Brush &brush) const - { - bool filtered = false; - Brush_forEachFace(brush, [&](Face &face) { - if (m_filter->filter(face)) { - filtered = true; - } - }); - return filtered; - } +filter_brush_any_face( FaceFilter* filter ) : m_filter( filter ){ +} + +bool filter( const Brush& brush ) const { + bool filtered = false; + Brush_forEachFace(brush, [&](Face &face) { + if (m_filter->filter(face)) { + filtered = true; + } + }); + return filtered; +} }; -class filter_brush_all_faces : public BrushFilter { - FaceFilter *m_filter; +class filter_brush_all_faces : public BrushFilter +{ +FaceFilter* m_filter; public: - filter_brush_all_faces(FaceFilter *filter) : m_filter(filter) - { - } - - bool filter(const Brush &brush) const - { - bool filtered = true; - Brush_forEachFace(brush, [&](Face &face) { - if (!m_filter->filter(face)) { - filtered = false; - } - }); - return filtered; - } +filter_brush_all_faces( FaceFilter* filter ) : m_filter( filter ){ +} +bool filter( const Brush& brush ) const { + bool filtered = true; + Brush_forEachFace(brush, [&](Face &face) { + if (!m_filter->filter(face)) { + filtered = false; + } + }); + return filtered; +} }; -filter_face_flags g_filter_face_clip(QER_CLIP); -filter_brush_all_faces g_filter_brush_clip(&g_filter_face_clip); +filter_face_flags g_filter_face_clip( QER_CLIP ); +filter_brush_all_faces g_filter_brush_clip( &g_filter_face_clip ); -filter_face_shader g_filter_face_clip_q2("textures/clip"); -filter_brush_all_faces g_filter_brush_clip_q2(&g_filter_face_clip_q2); +filter_face_shader g_filter_face_clip_q2( "textures/clip" ); +filter_brush_all_faces g_filter_brush_clip_q2( &g_filter_face_clip_q2 ); -filter_face_shader g_filter_face_weapclip("textures/common/weapclip"); -filter_brush_all_faces g_filter_brush_weapclip(&g_filter_face_weapclip); +filter_face_shader g_filter_face_weapclip( "textures/common/weapclip" ); +filter_brush_all_faces g_filter_brush_weapclip( &g_filter_face_weapclip ); -filter_face_shader g_filter_face_commonclip("textures/common/clip"); -filter_brush_all_faces g_filter_brush_commonclip(&g_filter_face_commonclip); +filter_face_shader g_filter_face_commonclip( "textures/common/clip" ); +filter_brush_all_faces g_filter_brush_commonclip( &g_filter_face_commonclip ); -filter_face_shader g_filter_face_fullclip("textures/common/fullclip"); -filter_brush_all_faces g_filter_brush_fullclip(&g_filter_face_fullclip); +filter_face_shader g_filter_face_fullclip( "textures/common/fullclip" ); +filter_brush_all_faces g_filter_brush_fullclip( &g_filter_face_fullclip ); -filter_face_shader g_filter_face_botclip("textures/common/botclip"); -filter_brush_all_faces g_filter_brush_botclip(&g_filter_face_botclip); +filter_face_shader g_filter_face_botclip( "textures/common/botclip" ); +filter_brush_all_faces g_filter_brush_botclip( &g_filter_face_botclip ); -filter_face_shader_prefix g_filter_face_caulk("textures/common/caulk"); -filter_brush_all_faces g_filter_brush_caulk(&g_filter_face_caulk); +filter_face_shader_prefix g_filter_face_caulk( "textures/common/caulk" ); +filter_brush_all_faces g_filter_brush_caulk( &g_filter_face_caulk ); -filter_face_shader_prefix g_filter_face_caulk_ja("textures/system/caulk"); -filter_brush_all_faces g_filter_brush_caulk_ja(&g_filter_face_caulk_ja); +filter_face_shader_prefix g_filter_face_caulk_ja( "textures/system/caulk" ); +filter_brush_all_faces g_filter_brush_caulk_ja( &g_filter_face_caulk_ja ); -filter_face_shader_prefix g_filter_face_liquids("textures/liquids/"); -filter_brush_any_face g_filter_brush_liquids(&g_filter_face_liquids); +filter_face_shader_prefix g_filter_face_liquids( "textures/liquids/" ); +filter_brush_any_face g_filter_brush_liquids( &g_filter_face_liquids ); -filter_face_shader g_filter_face_hint("textures/common/hint"); -filter_brush_any_face g_filter_brush_hint(&g_filter_face_hint); +filter_face_shader g_filter_face_hint( "textures/common/hint" ); +filter_brush_any_face g_filter_brush_hint( &g_filter_face_hint ); -filter_face_shader g_filter_face_hint_q2("textures/hint"); -filter_brush_any_face g_filter_brush_hint_q2(&g_filter_face_hint_q2); +filter_face_shader g_filter_face_hint_q2( "textures/hint" ); +filter_brush_any_face g_filter_brush_hint_q2( &g_filter_face_hint_q2 ); -filter_face_shader g_filter_face_hint_ja("textures/system/hint"); -filter_brush_any_face g_filter_brush_hint_ja(&g_filter_face_hint_ja); +filter_face_shader g_filter_face_hint_ja( "textures/system/hint" ); +filter_brush_any_face g_filter_brush_hint_ja( &g_filter_face_hint_ja ); -filter_face_shader g_filter_face_areaportal("textures/common/areaportal"); -filter_brush_all_faces g_filter_brush_areaportal(&g_filter_face_areaportal); +filter_face_shader g_filter_face_areaportal( "textures/common/areaportal" ); +filter_brush_all_faces g_filter_brush_areaportal( &g_filter_face_areaportal ); -filter_face_shader g_filter_face_visportal("textures/editor/visportal"); -filter_brush_any_face g_filter_brush_visportal(&g_filter_face_visportal); +filter_face_shader g_filter_face_visportal( "textures/editor/visportal" ); +filter_brush_any_face g_filter_brush_visportal( &g_filter_face_visportal ); -filter_face_shader g_filter_face_clusterportal("textures/common/clusterportal"); -filter_brush_all_faces g_filter_brush_clusterportal(&g_filter_face_clusterportal); +filter_face_shader g_filter_face_clusterportal( "textures/common/clusterportal" ); +filter_brush_all_faces g_filter_brush_clusterportal( &g_filter_face_clusterportal ); -filter_face_shader g_filter_face_lightgrid("textures/common/lightgrid"); -filter_brush_all_faces g_filter_brush_lightgrid(&g_filter_face_lightgrid); +filter_face_shader g_filter_face_lightgrid( "textures/common/lightgrid" ); +filter_brush_all_faces g_filter_brush_lightgrid( &g_filter_face_lightgrid ); -filter_face_flags g_filter_face_translucent(QER_TRANS); -filter_brush_all_faces g_filter_brush_translucent(&g_filter_face_translucent); +filter_face_flags g_filter_face_translucent( QER_TRANS ); +filter_brush_all_faces g_filter_brush_translucent( &g_filter_face_translucent ); -filter_face_contents g_filter_face_detail(BRUSH_DETAIL_MASK); -filter_brush_all_faces g_filter_brush_detail(&g_filter_face_detail); +filter_face_contents g_filter_face_detail( BRUSH_DETAIL_MASK ); +filter_brush_all_faces g_filter_brush_detail( &g_filter_face_detail ); -filter_face_shader_prefix g_filter_face_decals("textures/decals/"); -filter_brush_any_face g_filter_brush_decals(&g_filter_face_decals); +filter_face_shader_prefix g_filter_face_decals( "textures/decals/" ); +filter_brush_any_face g_filter_brush_decals( &g_filter_face_decals ); -void BrushFilters_construct() -{ - add_brush_filter(g_filter_brush_clip, EXCLUDE_CLIP); - add_brush_filter(g_filter_brush_clip_q2, EXCLUDE_CLIP); - add_brush_filter(g_filter_brush_weapclip, EXCLUDE_CLIP); - add_brush_filter(g_filter_brush_fullclip, EXCLUDE_CLIP); - add_brush_filter(g_filter_brush_commonclip, EXCLUDE_CLIP); - add_brush_filter(g_filter_brush_botclip, EXCLUDE_BOTCLIP); - add_brush_filter(g_filter_brush_caulk, EXCLUDE_CAULK); - add_brush_filter(g_filter_brush_caulk_ja, EXCLUDE_CAULK); - add_face_filter(g_filter_face_caulk, EXCLUDE_CAULK); - add_face_filter(g_filter_face_caulk_ja, EXCLUDE_CAULK); - add_brush_filter(g_filter_brush_liquids, EXCLUDE_LIQUIDS); - add_brush_filter(g_filter_brush_hint, EXCLUDE_HINTSSKIPS); - add_brush_filter(g_filter_brush_hint_q2, EXCLUDE_HINTSSKIPS); - add_brush_filter(g_filter_brush_hint_ja, EXCLUDE_HINTSSKIPS); - add_brush_filter(g_filter_brush_clusterportal, EXCLUDE_CLUSTERPORTALS); - add_brush_filter(g_filter_brush_visportal, EXCLUDE_VISPORTALS); - add_brush_filter(g_filter_brush_areaportal, EXCLUDE_AREAPORTALS); - add_brush_filter(g_filter_brush_translucent, EXCLUDE_TRANSLUCENT); - add_brush_filter(g_filter_brush_detail, EXCLUDE_DETAILS); - add_brush_filter(g_filter_brush_detail, EXCLUDE_STRUCTURAL, true); - add_brush_filter(g_filter_brush_lightgrid, EXCLUDE_LIGHTGRID); - add_brush_filter(g_filter_brush_decals, EXCLUDE_DECALS); +void BrushFilters_construct(){ + add_brush_filter( g_filter_brush_clip, EXCLUDE_CLIP ); + add_brush_filter( g_filter_brush_clip_q2, EXCLUDE_CLIP ); + add_brush_filter( g_filter_brush_weapclip, EXCLUDE_CLIP ); + add_brush_filter( g_filter_brush_fullclip, EXCLUDE_CLIP ); + add_brush_filter( g_filter_brush_commonclip, EXCLUDE_CLIP ); + add_brush_filter( g_filter_brush_botclip, EXCLUDE_BOTCLIP ); + add_brush_filter( g_filter_brush_caulk, EXCLUDE_CAULK ); + add_brush_filter( g_filter_brush_caulk_ja, EXCLUDE_CAULK ); + add_face_filter( g_filter_face_caulk, EXCLUDE_CAULK ); + add_face_filter( g_filter_face_caulk_ja, EXCLUDE_CAULK ); + add_brush_filter( g_filter_brush_liquids, EXCLUDE_LIQUIDS ); + add_brush_filter( g_filter_brush_hint, EXCLUDE_HINTSSKIPS ); + add_brush_filter( g_filter_brush_hint_q2, EXCLUDE_HINTSSKIPS ); + add_brush_filter( g_filter_brush_hint_ja, EXCLUDE_HINTSSKIPS ); + add_brush_filter( g_filter_brush_clusterportal, EXCLUDE_CLUSTERPORTALS ); + add_brush_filter( g_filter_brush_visportal, EXCLUDE_VISPORTALS ); + add_brush_filter( g_filter_brush_areaportal, EXCLUDE_AREAPORTALS ); + add_brush_filter( g_filter_brush_translucent, EXCLUDE_TRANSLUCENT ); + add_brush_filter( g_filter_brush_detail, EXCLUDE_DETAILS ); + add_brush_filter( g_filter_brush_detail, EXCLUDE_STRUCTURAL, true ); + add_brush_filter( g_filter_brush_lightgrid, EXCLUDE_LIGHTGRID ); + add_brush_filter( g_filter_brush_decals, EXCLUDE_DECALS ); } #if 0 void normalquantisation_draw(){ - glPointSize( 1 ); - glBegin( GL_POINTS ); - for ( std::size_t i = 0; i <= c_quantise_normal; ++i ) - { - for ( std::size_t j = 0; j <= c_quantise_normal; ++j ) - { - Normal3f vertex( normal3f_normalised( Normal3f( - static_cast( c_quantise_normal - j - i ), - static_cast( i ), - static_cast( j ) - ) ) ); - VectorScale( normal3f_to_array( vertex ), 64.f, normal3f_to_array( vertex ) ); - glVertex3fv( normal3f_to_array( vertex ) ); - vertex.x = -vertex.x; - glVertex3fv( normal3f_to_array( vertex ) ); - } - } - glEnd(); + glPointSize( 1 ); + glBegin( GL_POINTS ); + for ( std::size_t i = 0; i <= c_quantise_normal; ++i ) + { + for ( std::size_t j = 0; j <= c_quantise_normal; ++j ) + { + Normal3f vertex( normal3f_normalised( Normal3f( + static_cast( c_quantise_normal - j - i ), + static_cast( i ), + static_cast( j ) + ) ) ); + VectorScale( normal3f_to_array( vertex ), 64.f, normal3f_to_array( vertex ) ); + glVertex3fv( normal3f_to_array( vertex ) ); + vertex.x = -vertex.x; + glVertex3fv( normal3f_to_array( vertex ) ); + } + } + glEnd(); } class RenderableNormalQuantisation : public OpenGLRenderable { public: void render( RenderStateFlags state ) const { - normalquantisation_draw(); + normalquantisation_draw(); } }; @@ -991,104 +942,104 @@ const float g_test_quantise_normal = 1.f / static_cast( 1 << 3 ); class TestNormalQuantisation { void check_normal( const Normal3f& normal, const Normal3f& other ){ - spherical_t spherical = spherical_from_normal3f( normal ); - double longditude = RAD2DEG( spherical.longditude ); - double latitude = RAD2DEG( spherical.latitude ); - double x = cos( spherical.longditude ) * sin( spherical.latitude ); - double y = sin( spherical.longditude ) * sin( spherical.latitude ); - double z = cos( spherical.latitude ); + spherical_t spherical = spherical_from_normal3f( normal ); + double longditude = RAD2DEG( spherical.longditude ); + double latitude = RAD2DEG( spherical.latitude ); + double x = cos( spherical.longditude ) * sin( spherical.latitude ); + double y = sin( spherical.longditude ) * sin( spherical.latitude ); + double z = cos( spherical.latitude ); - ASSERT_MESSAGE( normal3f_dot( normal, other ) > 0.99, "bleh" ); + ASSERT_MESSAGE( normal3f_dot( normal, other ) > 0.99, "bleh" ); } void test_normal( const Normal3f& normal ){ - Normal3f test = normal3f_from_spherical( spherical_from_normal3f( normal ) ); - check_normal( normal, test ); + Normal3f test = normal3f_from_spherical( spherical_from_normal3f( normal ) ); + check_normal( normal, test ); - EOctant octant = normal3f_classify_octant( normal ); - Normal3f folded = normal3f_fold_octant( normal, octant ); - ESextant sextant = normal3f_classify_sextant( folded ); - folded = normal3f_fold_sextant( folded, sextant ); + EOctant octant = normal3f_classify_octant( normal ); + Normal3f folded = normal3f_fold_octant( normal, octant ); + ESextant sextant = normal3f_classify_sextant( folded ); + folded = normal3f_fold_sextant( folded, sextant ); - double scale = static_cast( c_quantise_normal ) / ( folded.x + folded.y + folded.z ); + double scale = static_cast( c_quantise_normal ) / ( folded.x + folded.y + folded.z ); - double zbits = folded.z * scale; - double ybits = folded.y * scale; + double zbits = folded.z * scale; + double ybits = folded.y * scale; - std::size_t zbits_q = static_cast( zbits ); - std::size_t ybits_q = static_cast( ybits ); + std::size_t zbits_q = static_cast( zbits ); + std::size_t ybits_q = static_cast( ybits ); - ASSERT_MESSAGE( zbits_q <= ( c_quantise_normal / 8 ) * 3, "bleh" ); - ASSERT_MESSAGE( ybits_q <= ( c_quantise_normal / 2 ), "bleh" ); - ASSERT_MESSAGE( zbits_q + ( ( c_quantise_normal / 2 ) - ybits_q ) <= ( c_quantise_normal / 2 ), "bleh" ); + ASSERT_MESSAGE( zbits_q <= ( c_quantise_normal / 8 ) * 3, "bleh" ); + ASSERT_MESSAGE( ybits_q <= ( c_quantise_normal / 2 ), "bleh" ); + ASSERT_MESSAGE( zbits_q + ( ( c_quantise_normal / 2 ) - ybits_q ) <= ( c_quantise_normal / 2 ), "bleh" ); - std::size_t y_t = ( zbits_q < ( c_quantise_normal / 4 ) ) ? ybits_q : ( c_quantise_normal / 2 ) - ybits_q; - std::size_t z_t = ( zbits_q < ( c_quantise_normal / 4 ) ) ? zbits_q : ( c_quantise_normal / 2 ) - zbits_q; - std::size_t index = ( c_quantise_normal / 4 ) * y_t + z_t; - ASSERT_MESSAGE( index <= ( c_quantise_normal / 4 ) * ( c_quantise_normal / 2 ), "bleh" ); + std::size_t y_t = ( zbits_q < ( c_quantise_normal / 4 ) ) ? ybits_q : ( c_quantise_normal / 2 ) - ybits_q; + std::size_t z_t = ( zbits_q < ( c_quantise_normal / 4 ) ) ? zbits_q : ( c_quantise_normal / 2 ) - zbits_q; + std::size_t index = ( c_quantise_normal / 4 ) * y_t + z_t; + ASSERT_MESSAGE( index <= ( c_quantise_normal / 4 ) * ( c_quantise_normal / 2 ), "bleh" ); - Normal3f tmp( c_quantise_normal - zbits_q - ybits_q, ybits_q, zbits_q ); - tmp = normal3f_normalised( tmp ); + Normal3f tmp( c_quantise_normal - zbits_q - ybits_q, ybits_q, zbits_q ); + tmp = normal3f_normalised( tmp ); - Normal3f unfolded = normal3f_unfold_octant( normal3f_unfold_sextant( tmp, sextant ), octant ); + Normal3f unfolded = normal3f_unfold_octant( normal3f_unfold_sextant( tmp, sextant ), octant ); - check_normal( normal, unfolded ); + check_normal( normal, unfolded ); - double dot = normal3f_dot( normal, unfolded ); - float length = VectorLength( normal3f_to_array( unfolded ) ); - float inv_length = 1 / length; + double dot = normal3f_dot( normal, unfolded ); + float length = VectorLength( normal3f_to_array( unfolded ) ); + float inv_length = 1 / length; - Normal3f quantised = normal3f_quantised( normal ); - check_normal( normal, quantised ); + Normal3f quantised = normal3f_quantised( normal ); + check_normal( normal, quantised ); } void test2( const Normal3f& normal, const Normal3f& other ){ - if ( normal3f_quantised( normal ) != normal3f_quantised( other ) ) { - int bleh = 0; - } + if ( normal3f_quantised( normal ) != normal3f_quantised( other ) ) { + int bleh = 0; + } } static Normal3f normalise( float x, float y, float z ){ - return normal3f_normalised( Normal3f( x, y, z ) ); + return normal3f_normalised( Normal3f( x, y, z ) ); } float vec_rand(){ - return static_cast( rand() - ( RAND_MAX / 2 ) ); + return static_cast( rand() - ( RAND_MAX / 2 ) ); } Normal3f normal3f_rand(){ - return normalise( vec_rand(), vec_rand(), vec_rand() ); + return normalise( vec_rand(), vec_rand(), vec_rand() ); } public: TestNormalQuantisation(){ - for ( int i = 4096; i > 0; --i ) - test_normal( normal3f_rand() ); - - test_normal( normalise( 1, 0, 0 ) ); - test_normal( normalise( 0, 1, 0 ) ); - test_normal( normalise( 0, 0, 1 ) ); - test_normal( normalise( 1, 1, 0 ) ); - test_normal( normalise( 1, 0, 1 ) ); - test_normal( normalise( 0, 1, 1 ) ); - - test_normal( normalise( 10000, 10000, 10000 ) ); - test_normal( normalise( 10000, 10000, 10001 ) ); - test_normal( normalise( 10000, 10000, 10002 ) ); - test_normal( normalise( 10000, 10000, 10010 ) ); - test_normal( normalise( 10000, 10000, 10020 ) ); - test_normal( normalise( 10000, 10000, 10030 ) ); - test_normal( normalise( 10000, 10000, 10100 ) ); - test_normal( normalise( 10000, 10000, 10101 ) ); - test_normal( normalise( 10000, 10000, 10102 ) ); - test_normal( normalise( 10000, 10000, 10200 ) ); - test_normal( normalise( 10000, 10000, 10201 ) ); - test_normal( normalise( 10000, 10000, 10202 ) ); - test_normal( normalise( 10000, 10000, 10203 ) ); - test_normal( normalise( 10000, 10000, 10300 ) ); - - - test2( normalise( 10000, 10000, 10000 ), normalise( 10000, 10000, 10001 ) ); - test2( normalise( 10000, 10000, 10001 ), normalise( 10000, 10001, 10000 ) ); + for ( int i = 4096; i > 0; --i ) + test_normal( normal3f_rand() ); + + test_normal( normalise( 1, 0, 0 ) ); + test_normal( normalise( 0, 1, 0 ) ); + test_normal( normalise( 0, 0, 1 ) ); + test_normal( normalise( 1, 1, 0 ) ); + test_normal( normalise( 1, 0, 1 ) ); + test_normal( normalise( 0, 1, 1 ) ); + + test_normal( normalise( 10000, 10000, 10000 ) ); + test_normal( normalise( 10000, 10000, 10001 ) ); + test_normal( normalise( 10000, 10000, 10002 ) ); + test_normal( normalise( 10000, 10000, 10010 ) ); + test_normal( normalise( 10000, 10000, 10020 ) ); + test_normal( normalise( 10000, 10000, 10030 ) ); + test_normal( normalise( 10000, 10000, 10100 ) ); + test_normal( normalise( 10000, 10000, 10101 ) ); + test_normal( normalise( 10000, 10000, 10102 ) ); + test_normal( normalise( 10000, 10000, 10200 ) ); + test_normal( normalise( 10000, 10000, 10201 ) ); + test_normal( normalise( 10000, 10000, 10202 ) ); + test_normal( normalise( 10000, 10000, 10203 ) ); + test_normal( normalise( 10000, 10000, 10300 ) ); + + + test2( normalise( 10000, 10000, 10000 ), normalise( 10000, 10000, 10001 ) ); + test2( normalise( 10000, 10000, 10001 ), normalise( 10000, 10001, 10000 ) ); } }; @@ -1102,23 +1053,23 @@ class TestSelectableObserver : public observer_template { public: void notify( const Selectable& arguments ){ - bool bleh = arguments.isSelected(); + bool bleh = arguments.isSelected(); } }; inline void test_bleh(){ - TestSelectableObserver test; - ObservableSelectableInstance< SingleObservable< SelectionChangeCallback > > bleh; - bleh.attach( test ); - bleh.setSelected( true ); - bleh.detach( test ); + TestSelectableObserver test; + ObservableSelectableInstance< SingleObservable< SelectionChangeCallback > > bleh; + bleh.attach( test ); + bleh.setSelected( true ); + bleh.detach( test ); } class TestBleh { public: TestBleh(){ - test_bleh(); + test_bleh(); } }; @@ -1131,35 +1082,35 @@ class TestRefcountedString { public: TestRefcountedString(){ - { - // copy construct - SmartString string1( "string1" ); - SmartString string2( string1 ); - SmartString string3( string2 ); - } - { - // refcounted assignment - SmartString string1( "string1" ); - SmartString string2( "string2" ); - string1 = string2; - } - { - // copy assignment - SmartString string1( "string1" ); - SmartString string2( "string2" ); - string1 = string2.c_str(); - } - { - // self-assignment - SmartString string1( "string1" ); - string1 = string1; - } - { - // self-assignment via another reference - SmartString string1( "string1" ); - SmartString string2( string1 ); - string1 = string2; - } + { + // copy construct + SmartString string1( "string1" ); + SmartString string2( string1 ); + SmartString string3( string2 ); + } + { + // refcounted assignment + SmartString string1( "string1" ); + SmartString string2( "string2" ); + string1 = string2; + } + { + // copy assignment + SmartString string1( "string1" ); + SmartString string2( "string2" ); + string1 = string2.c_str(); + } + { + // self-assignment + SmartString string1( "string1" ); + string1 = string1; + } + { + // self-assignment via another reference + SmartString string1( "string1" ); + SmartString string2( string1 ); + string1 = string2; + } } }; @@ -1167,77 +1118,72 @@ const TestRefcountedString g_testRefcountedString; #endif -void Select_MakeDetail() -{ - UndoableCommand undo("brushSetDetail"); - Scene_BrushSetDetail_Selected(GlobalSceneGraph(), true); +void Select_MakeDetail(){ + UndoableCommand undo( "brushSetDetail" ); + Scene_BrushSetDetail_Selected( GlobalSceneGraph(), true ); } -void Select_MakeStructural() -{ - UndoableCommand undo("brushClearDetail"); - Scene_BrushSetDetail_Selected(GlobalSceneGraph(), false); +void Select_MakeStructural(){ + UndoableCommand undo( "brushClearDetail" ); + Scene_BrushSetDetail_Selected( GlobalSceneGraph(), false ); } -class BrushMakeSided { - std::size_t m_count; +class BrushMakeSided +{ +std::size_t m_count; public: - BrushMakeSided(std::size_t count) - : m_count(count) - { - } - - void set() - { - Scene_BrushConstructPrefab(GlobalSceneGraph(), eBrushPrism, m_count, - TextureBrowser_GetSelectedShader(GlobalTextureBrowser())); - } - - typedef MemberCaller SetCaller; -}; +BrushMakeSided( std::size_t count ) + : m_count( count ){ +} +void set(){ + Scene_BrushConstructPrefab( GlobalSceneGraph(), eBrushPrism, m_count, TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) ); +} + +typedef MemberCaller SetCaller; +}; -BrushMakeSided g_brushmakesided3(3); -BrushMakeSided g_brushmakesided4(4); -BrushMakeSided g_brushmakesided5(5); -BrushMakeSided g_brushmakesided6(6); -BrushMakeSided g_brushmakesided7(7); -BrushMakeSided g_brushmakesided8(8); -BrushMakeSided g_brushmakesided9(9); -inline int axis_for_viewtype(int viewtype) +BrushMakeSided g_brushmakesided3( 3 ); +BrushMakeSided g_brushmakesided4( 4 ); +BrushMakeSided g_brushmakesided5( 5 ); +BrushMakeSided g_brushmakesided6( 6 ); +BrushMakeSided g_brushmakesided7( 7 ); +BrushMakeSided g_brushmakesided8( 8 ); +BrushMakeSided g_brushmakesided9( 9 ); + +inline int axis_for_viewtype( int viewtype ){ + switch ( viewtype ) + { + case XY: + return 2; + case XZ: + return 1; + case YZ: + return 0; + } + return 2; +} + +class BrushPrefab { - switch (viewtype) { - case XY: - return 2; - case XZ: - return 1; - case YZ: - return 0; - } - return 2; -} - -class BrushPrefab { - EBrushPrefab m_type; +EBrushPrefab m_type; public: - BrushPrefab(EBrushPrefab type) - : m_type(type) - { - } +BrushPrefab( EBrushPrefab type ) + : m_type( type ){ +} - void set() - { - DoSides(m_type, axis_for_viewtype(GetViewAxis())); - } +void set(){ + DoSides( m_type, axis_for_viewtype( GetViewAxis() ) ); +} - typedef MemberCaller SetCaller; +typedef MemberCaller SetCaller; }; -BrushPrefab g_brushprism(eBrushPrism); -BrushPrefab g_brushcone(eBrushCone); -BrushPrefab g_brushsphere(eBrushSphere); -BrushPrefab g_brushrock(eBrushRock); +BrushPrefab g_brushprism( eBrushPrism ); +BrushPrefab g_brushcone( eBrushCone ); +BrushPrefab g_brushsphere( eBrushSphere ); +BrushPrefab g_brushrock( eBrushRock ); void FlipClip(); @@ -1246,127 +1192,107 @@ void SplitClip(); void Clip(); -void OnClipMode(bool enable); +void OnClipMode( bool enable ); bool ClipMode(); -void ClipSelected() -{ - if (ClipMode()) { - UndoableCommand undo("clipperClip"); - Clip(); - } +void ClipSelected(){ + if ( ClipMode() ) { + UndoableCommand undo( "clipperClip" ); + Clip(); + } } -void SplitSelected() -{ - if (ClipMode()) { - UndoableCommand undo("clipperSplit"); - SplitClip(); - } +void SplitSelected(){ + if ( ClipMode() ) { + UndoableCommand undo( "clipperSplit" ); + SplitClip(); + } } -void FlipClipper() -{ - FlipClip(); +void FlipClipper(){ + FlipClip(); } Callback g_texture_lock_status_changed; -ConstReferenceCaller &), PropertyImpl::Export> g_texdef_movelock_caller( - g_brush_texturelock_enabled); -ToggleItem g_texdef_movelock_item(g_texdef_movelock_caller); - -void Texdef_ToggleMoveLock() -{ - g_brush_texturelock_enabled = !g_brush_texturelock_enabled; - g_texdef_movelock_item.update(); - g_texture_lock_status_changed(); -} - - -void Brush_registerCommands() -{ - GlobalToggles_insert("TogTexLock", makeCallbackF(Texdef_ToggleMoveLock), - ToggleItem::AddCallbackCaller(g_texdef_movelock_item), - Accelerator('T', (GdkModifierType) GDK_SHIFT_MASK)); - - GlobalCommands_insert("BrushPrism", BrushPrefab::SetCaller(g_brushprism)); - GlobalCommands_insert("BrushCone", BrushPrefab::SetCaller(g_brushcone)); - GlobalCommands_insert("BrushSphere", BrushPrefab::SetCaller(g_brushsphere)); - GlobalCommands_insert("BrushRock", BrushPrefab::SetCaller(g_brushrock)); - - GlobalCommands_insert("Brush3Sided", BrushMakeSided::SetCaller(g_brushmakesided3), - Accelerator('3', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("Brush4Sided", BrushMakeSided::SetCaller(g_brushmakesided4), - Accelerator('4', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("Brush5Sided", BrushMakeSided::SetCaller(g_brushmakesided5), - Accelerator('5', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("Brush6Sided", BrushMakeSided::SetCaller(g_brushmakesided6), - Accelerator('6', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("Brush7Sided", BrushMakeSided::SetCaller(g_brushmakesided7), - Accelerator('7', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("Brush8Sided", BrushMakeSided::SetCaller(g_brushmakesided8), - Accelerator('8', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("Brush9Sided", BrushMakeSided::SetCaller(g_brushmakesided9), - Accelerator('9', (GdkModifierType) GDK_CONTROL_MASK)); - - GlobalCommands_insert("ClipSelected", makeCallbackF(ClipSelected), Accelerator(GDK_KEY_Return)); - GlobalCommands_insert("SplitSelected", makeCallbackF(SplitSelected), - Accelerator(GDK_KEY_Return, (GdkModifierType) GDK_SHIFT_MASK)); - GlobalCommands_insert("FlipClip", makeCallbackF(FlipClipper), - Accelerator(GDK_KEY_Return, (GdkModifierType) GDK_CONTROL_MASK)); - - GlobalCommands_insert("MakeDetail", makeCallbackF(Select_MakeDetail), - Accelerator('M', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("MakeStructural", makeCallbackF(Select_MakeStructural), - Accelerator('S', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); -} - -void Brush_constructMenu(ui::Menu menu) -{ - create_menu_item_with_mnemonic(menu, "Prism...", "BrushPrism"); - create_menu_item_with_mnemonic(menu, "Cone...", "BrushCone"); - create_menu_item_with_mnemonic(menu, "Sphere...", "BrushSphere"); - create_menu_item_with_mnemonic(menu, "Rock...", "BrushRock"); - menu_separator(menu); - { - auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "CSG"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu_in_menu); - } - create_menu_item_with_mnemonic(menu_in_menu, "Make _Hollow", "CSGMakeHollow"); - create_menu_item_with_mnemonic(menu_in_menu, "Make _Room", "CSGMakeRoom"); - create_menu_item_with_mnemonic(menu_in_menu, "CSG _Subtract", "CSGSubtract"); - create_menu_item_with_mnemonic(menu_in_menu, "CSG _Merge", "CSGMerge"); - } - menu_separator(menu); - { - auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Clipper"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu_in_menu); - } - - create_menu_item_with_mnemonic(menu_in_menu, "Clip selection", "ClipSelected"); - create_menu_item_with_mnemonic(menu_in_menu, "Split selection", "SplitSelected"); - create_menu_item_with_mnemonic(menu_in_menu, "Flip Clip orientation", "FlipClip"); - } - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "Make detail", "MakeDetail"); - create_menu_item_with_mnemonic(menu, "Make structural", "MakeStructural"); - create_menu_item_with_mnemonic(menu, "Snap selection to _grid", "SnapToGrid"); - - create_check_menu_item_with_mnemonic(menu, "Texture Lock", "TogTexLock"); - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "Copy Face Texture", "FaceCopyTexture"); - create_menu_item_with_mnemonic(menu, "Paste Face Texture", "FacePasteTexture"); - - command_connect_accelerator("Brush3Sided"); - command_connect_accelerator("Brush4Sided"); - command_connect_accelerator("Brush5Sided"); - command_connect_accelerator("Brush6Sided"); - command_connect_accelerator("Brush7Sided"); - command_connect_accelerator("Brush8Sided"); - command_connect_accelerator("Brush9Sided"); +ConstReferenceCaller &), PropertyImpl::Export> g_texdef_movelock_caller( g_brush_texturelock_enabled ); +ToggleItem g_texdef_movelock_item( g_texdef_movelock_caller ); + +void Texdef_ToggleMoveLock(){ + g_brush_texturelock_enabled = !g_brush_texturelock_enabled; + g_texdef_movelock_item.update(); + g_texture_lock_status_changed(); +} + + +void Brush_registerCommands(){ + GlobalToggles_insert( "TogTexLock", makeCallbackF(Texdef_ToggleMoveLock), ToggleItem::AddCallbackCaller( g_texdef_movelock_item ), Accelerator( 'T', (GdkModifierType)GDK_SHIFT_MASK ) ); + + GlobalCommands_insert( "BrushPrism", BrushPrefab::SetCaller( g_brushprism ) ); + GlobalCommands_insert( "BrushCone", BrushPrefab::SetCaller( g_brushcone ) ); + GlobalCommands_insert( "BrushSphere", BrushPrefab::SetCaller( g_brushsphere ) ); + GlobalCommands_insert( "BrushRock", BrushPrefab::SetCaller( g_brushrock ) ); + + GlobalCommands_insert( "Brush3Sided", BrushMakeSided::SetCaller( g_brushmakesided3 ), Accelerator( '3', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "Brush4Sided", BrushMakeSided::SetCaller( g_brushmakesided4 ), Accelerator( '4', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "Brush5Sided", BrushMakeSided::SetCaller( g_brushmakesided5 ), Accelerator( '5', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "Brush6Sided", BrushMakeSided::SetCaller( g_brushmakesided6 ), Accelerator( '6', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "Brush7Sided", BrushMakeSided::SetCaller( g_brushmakesided7 ), Accelerator( '7', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "Brush8Sided", BrushMakeSided::SetCaller( g_brushmakesided8 ), Accelerator( '8', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "Brush9Sided", BrushMakeSided::SetCaller( g_brushmakesided9 ), Accelerator( '9', (GdkModifierType)GDK_CONTROL_MASK ) ); + + GlobalCommands_insert( "ClipSelected", makeCallbackF(ClipSelected), Accelerator( GDK_KEY_Return ) ); + GlobalCommands_insert( "SplitSelected", makeCallbackF(SplitSelected), Accelerator( GDK_KEY_Return, (GdkModifierType)GDK_SHIFT_MASK ) ); + GlobalCommands_insert( "FlipClip", makeCallbackF(FlipClipper), Accelerator( GDK_KEY_Return, (GdkModifierType)GDK_CONTROL_MASK ) ); + + GlobalCommands_insert( "MakeDetail", makeCallbackF(Select_MakeDetail), Accelerator( 'M', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "MakeStructural", makeCallbackF(Select_MakeStructural), Accelerator( 'S', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); +} + +void Brush_constructMenu( ui::Menu menu ){ + create_menu_item_with_mnemonic( menu, "Prism...", "BrushPrism" ); + create_menu_item_with_mnemonic( menu, "Cone...", "BrushCone" ); + create_menu_item_with_mnemonic( menu, "Sphere...", "BrushSphere" ); + create_menu_item_with_mnemonic( menu, "Rock...", "BrushRock" ); + menu_separator( menu ); + { + auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "CSG" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu_in_menu ); + } + create_menu_item_with_mnemonic( menu_in_menu, "Make _Hollow", "CSGMakeHollow" ); + create_menu_item_with_mnemonic( menu_in_menu, "Make _Room", "CSGMakeRoom" ); + create_menu_item_with_mnemonic( menu_in_menu, "CSG _Subtract", "CSGSubtract" ); + create_menu_item_with_mnemonic( menu_in_menu, "CSG _Merge", "CSGMerge" ); + } + menu_separator( menu ); + { + auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Clipper" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu_in_menu ); + } + + create_menu_item_with_mnemonic( menu_in_menu, "Clip selection", "ClipSelected" ); + create_menu_item_with_mnemonic( menu_in_menu, "Split selection", "SplitSelected" ); + create_menu_item_with_mnemonic( menu_in_menu, "Flip Clip orientation", "FlipClip" ); + } + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "Make detail", "MakeDetail" ); + create_menu_item_with_mnemonic( menu, "Make structural", "MakeStructural" ); + create_menu_item_with_mnemonic( menu, "Snap selection to _grid", "SnapToGrid" ); + + create_check_menu_item_with_mnemonic( menu, "Texture Lock", "TogTexLock" ); + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "Copy Face Texture", "FaceCopyTexture" ); + create_menu_item_with_mnemonic( menu, "Paste Face Texture", "FacePasteTexture" ); + + command_connect_accelerator( "Brush3Sided" ); + command_connect_accelerator( "Brush4Sided" ); + command_connect_accelerator( "Brush5Sided" ); + command_connect_accelerator( "Brush6Sided" ); + command_connect_accelerator( "Brush7Sided" ); + command_connect_accelerator( "Brush8Sided" ); + command_connect_accelerator( "Brush9Sided" ); } diff --git a/radiant/csg.cpp b/radiant/csg.cpp index fab905aa..44fefdc8 100644 --- a/radiant/csg.cpp +++ b/radiant/csg.cpp @@ -30,132 +30,125 @@ #include "brushnode.h" #include "grid.h" -void Face_makeBrush(Face &face, const Brush &brush, brush_vector_t &out, float offset) -{ - if (face.contributes()) { - out.push_back(new Brush(brush)); - Face *newFace = out.back()->addFace(face); - if (newFace != 0) { - newFace->flipWinding(); - newFace->getPlane().offset(offset); - newFace->planeChanged(); - } - } -} - -void Face_makeRoom(Face &face, const Brush &brush, brush_vector_t &out, float offset) -{ - if (face.contributes()) { - face.getPlane().offset(offset); - out.push_back(new Brush(brush)); - face.getPlane().offset(-offset); - Face *newFace = out.back()->addFace(face); - if (newFace != 0) { - newFace->flipWinding(); - newFace->planeChanged(); - } - } -} - -void Brush_makeHollow(const Brush &brush, brush_vector_t &out, float offset) -{ - Brush_forEachFace(brush, [&](Face &face) { - Face_makeBrush(face, brush, out, offset); - }); +void Face_makeBrush( Face& face, const Brush& brush, brush_vector_t& out, float offset ){ + if ( face.contributes() ) { + out.push_back( new Brush( brush ) ); + Face* newFace = out.back()->addFace( face ); + if ( newFace != 0 ) { + newFace->flipWinding(); + newFace->getPlane().offset( offset ); + newFace->planeChanged(); + } + } } -void Brush_makeRoom(const Brush &brush, brush_vector_t &out, float offset) -{ - Brush_forEachFace(brush, [&](Face &face) { - Face_makeRoom(face, brush, out, offset); - }); +void Face_makeRoom( Face &face, const Brush &brush, brush_vector_t &out, float offset ){ + if ( face.contributes() ) { + face.getPlane().offset( offset ); + out.push_back( new Brush( brush ) ); + face.getPlane().offset( -offset ); + Face* newFace = out.back()->addFace( face ); + if ( newFace != 0 ) { + newFace->flipWinding(); + newFace->planeChanged(); + } + } } -class BrushHollowSelectedWalker : public scene::Graph::Walker { - float m_offset; - bool m_makeRoom; +void Brush_makeHollow( const Brush &brush, brush_vector_t &out, float offset ){ + Brush_forEachFace( brush, [&]( Face &face ) { + Face_makeBrush( face, brush, out, offset ); + } ); +} + +void Brush_makeRoom( const Brush &brush, brush_vector_t &out, float offset ){ + Brush_forEachFace( brush, [&]( Face &face ) { + Face_makeRoom( face, brush, out, offset ); + } ); +} + +class BrushHollowSelectedWalker : public scene::Graph::Walker +{ +float m_offset; +bool m_makeRoom; public: - BrushHollowSelectedWalker(float offset, bool makeRoom) - : m_offset(offset), m_makeRoom(makeRoom) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - if (path.top().get().visible()) { - Brush *brush = Node_getBrush(path.top()); - if (brush != 0 - && Instance_getSelectable(instance)->isSelected() - && path.size() > 1) { - brush_vector_t out; - - if (m_makeRoom) { - Brush_makeRoom(*brush, out, m_offset); - } - else { - Brush_makeHollow(*brush, out, m_offset); - } - - for (brush_vector_t::const_iterator i = out.begin(); i != out.end(); ++i) { - (*i)->removeEmptyFaces(); - NodeSmartReference node((new BrushNode())->node()); - Node_getBrush(node)->copy(*(*i)); - delete (*i); - Node_getTraversable(path.parent())->insert(node); - } - } - } - return true; - } +BrushHollowSelectedWalker( float offset, bool makeRoom ) + : m_offset( offset ), m_makeRoom( makeRoom ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get().visible() ) { + Brush* brush = Node_getBrush( path.top() ); + if ( brush != 0 + && Instance_getSelectable( instance )->isSelected() + && path.size() > 1 ) { + brush_vector_t out; + + if ( m_makeRoom ) { + Brush_makeRoom(* brush, out, m_offset ); + } + else + { + Brush_makeHollow(* brush, out, m_offset ); + } + + for ( brush_vector_t::const_iterator i = out.begin(); i != out.end(); ++i ) + { + ( *i )->removeEmptyFaces(); + NodeSmartReference node( ( new BrushNode() )->node() ); + Node_getBrush( node )->copy( *( *i ) ); + delete ( *i ); + Node_getTraversable( path.parent() )->insert( node ); + } + } + } + return true; +} }; -typedef std::list brushlist_t; +typedef std::list brushlist_t; -class BrushGatherSelected : public scene::Graph::Walker { - brush_vector_t &m_brushlist; +class BrushGatherSelected : public scene::Graph::Walker +{ +brush_vector_t& m_brushlist; public: - BrushGatherSelected(brush_vector_t &brushlist) - : m_brushlist(brushlist) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - if (path.top().get().visible()) { - Brush *brush = Node_getBrush(path.top()); - if (brush != 0 - && Instance_getSelectable(instance)->isSelected()) { - m_brushlist.push_back(brush); - } - } - return true; - } +BrushGatherSelected( brush_vector_t& brushlist ) + : m_brushlist( brushlist ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get().visible() ) { + Brush* brush = Node_getBrush( path.top() ); + if ( brush != 0 + && Instance_getSelectable( instance )->isSelected() ) { + m_brushlist.push_back( brush ); + } + } + return true; +} }; -class BrushDeleteSelected : public scene::Graph::Walker { +class BrushDeleteSelected : public scene::Graph::Walker +{ public: - bool pre(const scene::Path &path, scene::Instance &instance) const - { - return true; - } - - void post(const scene::Path &path, scene::Instance &instance) const - { - if (path.top().get().visible()) { - Brush *brush = Node_getBrush(path.top()); - if (brush != 0 - && Instance_getSelectable(instance)->isSelected() - && path.size() > 1) { - Path_deleteTop(path); - } - } - } +bool pre( const scene::Path& path, scene::Instance& instance ) const { + return true; +} +void post( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get().visible() ) { + Brush* brush = Node_getBrush( path.top() ); + if ( brush != 0 + && Instance_getSelectable( instance )->isSelected() + && path.size() > 1 ) { + Path_deleteTop( path ); + } + } +} }; -void Scene_BrushMakeHollow_Selected(scene::Graph &graph, bool makeRoom) -{ - GlobalSceneGraph().traverse(BrushHollowSelectedWalker(GetGridSize(), makeRoom)); - GlobalSceneGraph().traverse(BrushDeleteSelected()); +void Scene_BrushMakeHollow_Selected( scene::Graph& graph, bool makeRoom ){ + GlobalSceneGraph().traverse( BrushHollowSelectedWalker( GetGridSize(), makeRoom ) ); + GlobalSceneGraph().traverse( BrushDeleteSelected() ); } /* @@ -164,368 +157,361 @@ void Scene_BrushMakeHollow_Selected(scene::Graph &graph, bool makeRoom) ============= */ -void CSG_MakeHollow(void) -{ - UndoableCommand undo("brushHollow"); +void CSG_MakeHollow( void ){ + UndoableCommand undo( "brushHollow" ); - Scene_BrushMakeHollow_Selected(GlobalSceneGraph(), false); + Scene_BrushMakeHollow_Selected( GlobalSceneGraph(), false ); - SceneChangeNotify(); + SceneChangeNotify(); } -void CSG_MakeRoom(void) -{ - UndoableCommand undo("brushRoom"); +void CSG_MakeRoom( void ){ + UndoableCommand undo( "brushRoom" ); - Scene_BrushMakeHollow_Selected(GlobalSceneGraph(), true); + Scene_BrushMakeHollow_Selected( GlobalSceneGraph(), true ); - SceneChangeNotify(); + SceneChangeNotify(); } template -class RemoveReference { +class RemoveReference +{ public: - typedef Type type; +typedef Type type; }; template -class RemoveReference { +class RemoveReference +{ public: - typedef Type type; +typedef Type type; }; template -class Dereference { - const Functor &functor; +class Dereference +{ +const Functor& functor; public: - Dereference(const Functor &functor) : functor(functor) - { - } - - get_result_type operator()(typename RemoveReference>::type *firstArgument) const - { - return functor(*firstArgument); - } +Dereference( const Functor& functor ) : functor( functor ){ +} +get_result_type operator()( typename RemoveReference>::type *firstArgument ) const { + return functor( *firstArgument ); +} }; template -inline Dereference makeDereference(const Functor &functor) -{ - return Dereference(functor); +inline Dereference makeDereference( const Functor& functor ){ + return Dereference( functor ); } -typedef Face *FacePointer; +typedef Face* FacePointer; const FacePointer c_nullFacePointer = 0; template -Face *Brush_findIf(const Brush &brush, const Predicate &predicate) -{ - Brush::const_iterator i = std::find_if(brush.begin(), brush.end(), makeDereference(predicate)); - return i == brush.end() ? c_nullFacePointer - : *i; // uses c_nullFacePointer instead of 0 because otherwise gcc 4.1 attempts conversion to int +Face* Brush_findIf( const Brush& brush, const Predicate& predicate ){ + Brush::const_iterator i = std::find_if( brush.begin(), brush.end(), makeDereference( predicate ) ); + return i == brush.end() ? c_nullFacePointer : *i; // uses c_nullFacePointer instead of 0 because otherwise gcc 4.1 attempts conversion to int } template -class BindArguments1 { - typedef get_argument FirstBound; - FirstBound firstBound; +class BindArguments1 +{ +typedef get_argument FirstBound; +FirstBound firstBound; public: - BindArguments1(FirstBound firstBound) - : firstBound(firstBound) - { - } - - get_result_type operator()(get_argument firstArgument) const - { - return Caller::call(firstArgument, firstBound); - } +BindArguments1( FirstBound firstBound ) + : firstBound( firstBound ){ +} + +get_result_type operator()( get_argument firstArgument ) const { + return Caller::call( firstArgument, firstBound ); +} }; template -class BindArguments2 { - typedef get_argument FirstBound; - typedef get_argument SecondBound; - FirstBound firstBound; - SecondBound secondBound; +class BindArguments2 +{ +typedef get_argument FirstBound; +typedef get_argument SecondBound; +FirstBound firstBound; +SecondBound secondBound; public: - BindArguments2(FirstBound firstBound, SecondBound secondBound) - : firstBound(firstBound), secondBound(secondBound) - { - } - - get_result_type operator()(get_argument firstArgument) const - { - return Caller::call(firstArgument, firstBound, secondBound); - } +BindArguments2( FirstBound firstBound, SecondBound secondBound ) + : firstBound( firstBound ), secondBound( secondBound ){ +} + +get_result_type operator()( get_argument firstArgument ) const { + return Caller::call( firstArgument, firstBound, secondBound ); +} }; template -BindArguments2 bindArguments(const Caller &caller, FirstBound firstBound, SecondBound secondBound) -{ - return BindArguments2(firstBound, secondBound); +BindArguments2 bindArguments( const Caller& caller, FirstBound firstBound, SecondBound secondBound ){ + return BindArguments2( firstBound, secondBound ); } -inline bool Face_testPlane(const Face &face, const Plane3 &plane, bool flipped) -{ - return face.contributes() && !Winding_TestPlane(face.getWinding(), plane, flipped); +inline bool Face_testPlane( const Face& face, const Plane3& plane, bool flipped ){ + return face.contributes() && !Winding_TestPlane( face.getWinding(), plane, flipped ); } -typedef Function FaceTestPlane; +typedef Function FaceTestPlane; /// \brief Returns true if /// \li !flipped && brush is BACK or ON /// \li flipped && brush is FRONT or ON -bool Brush_testPlane(const Brush &brush, const Plane3 &plane, bool flipped) -{ - brush.evaluateBRep(); +bool Brush_testPlane( const Brush& brush, const Plane3& plane, bool flipped ){ + brush.evaluateBRep(); #if 1 - for (Brush::const_iterator i(brush.begin()); i != brush.end(); ++i) { - if (Face_testPlane(*(*i), plane, flipped)) { - return false; - } - } - return true; + for ( Brush::const_iterator i( brush.begin() ); i != brush.end(); ++i ) + { + if ( Face_testPlane( *( *i ), plane, flipped ) ) { + return false; + } + } + return true; #else - return Brush_findIf( brush, bindArguments( FaceTestPlane(), makeReference( plane ), flipped ) ) == 0; + return Brush_findIf( brush, bindArguments( FaceTestPlane(), makeReference( plane ), flipped ) ) == 0; #endif } -brushsplit_t Brush_classifyPlane(const Brush &brush, const Plane3 &plane) -{ - brush.evaluateBRep(); - brushsplit_t split; - for (Brush::const_iterator i(brush.begin()); i != brush.end(); ++i) { - if ((*i)->contributes()) { - split += Winding_ClassifyPlane((*i)->getWinding(), plane); - } - } - return split; +brushsplit_t Brush_classifyPlane( const Brush& brush, const Plane3& plane ){ + brush.evaluateBRep(); + brushsplit_t split; + for ( Brush::const_iterator i( brush.begin() ); i != brush.end(); ++i ) + { + if ( ( *i )->contributes() ) { + split += Winding_ClassifyPlane( ( *i )->getWinding(), plane ); + } + } + return split; } -bool Brush_subtract(const Brush &brush, const Brush &other, brush_vector_t &ret_fragments) +bool Brush_subtract( const Brush& brush, const Brush& other, brush_vector_t& ret_fragments ){ + if ( aabb_intersects_aabb( brush.localAABB(), other.localAABB() ) ) { + brush_vector_t fragments; + fragments.reserve( other.size() ); + Brush back( brush ); + + for ( Brush::const_iterator i( other.begin() ); i != other.end(); ++i ) + { + if ( ( *i )->contributes() ) { + brushsplit_t split = Brush_classifyPlane( back, ( *i )->plane3() ); + if ( split.counts[ePlaneFront] != 0 + && split.counts[ePlaneBack] != 0 ) { + fragments.push_back( new Brush( back ) ); + Face* newFace = fragments.back()->addFace( *( *i ) ); + if ( newFace != 0 ) { + newFace->flipWinding(); + } + back.addFace( *( *i ) ); + } + else if ( split.counts[ePlaneBack] == 0 ) { + for ( brush_vector_t::iterator i = fragments.begin(); i != fragments.end(); ++i ) + { + delete( *i ); + } + return false; + } + } + } + ret_fragments.insert( ret_fragments.end(), fragments.begin(), fragments.end() ); + return true; + } + return false; +} + +class SubtractBrushesFromUnselected : public scene::Graph::Walker { - if (aabb_intersects_aabb(brush.localAABB(), other.localAABB())) { - brush_vector_t fragments; - fragments.reserve(other.size()); - Brush back(brush); - - for (Brush::const_iterator i(other.begin()); i != other.end(); ++i) { - if ((*i)->contributes()) { - brushsplit_t split = Brush_classifyPlane(back, (*i)->plane3()); - if (split.counts[ePlaneFront] != 0 - && split.counts[ePlaneBack] != 0) { - fragments.push_back(new Brush(back)); - Face *newFace = fragments.back()->addFace(*(*i)); - if (newFace != 0) { - newFace->flipWinding(); - } - back.addFace(*(*i)); - } else if (split.counts[ePlaneBack] == 0) { - for (brush_vector_t::iterator i = fragments.begin(); i != fragments.end(); ++i) { - delete (*i); - } - return false; - } - } - } - ret_fragments.insert(ret_fragments.end(), fragments.begin(), fragments.end()); - return true; - } - return false; -} - -class SubtractBrushesFromUnselected : public scene::Graph::Walker { - const brush_vector_t &m_brushlist; - std::size_t &m_before; - std::size_t &m_after; +const brush_vector_t& m_brushlist; +std::size_t& m_before; +std::size_t& m_after; public: - SubtractBrushesFromUnselected(const brush_vector_t &brushlist, std::size_t &before, std::size_t &after) - : m_brushlist(brushlist), m_before(before), m_after(after) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - return true; - } - - void post(const scene::Path &path, scene::Instance &instance) const - { - if (path.top().get().visible()) { - Brush *brush = Node_getBrush(path.top()); - if (brush != 0 - && !Instance_getSelectable(instance)->isSelected()) { - brush_vector_t buffer[2]; - bool swap = false; - Brush *original = new Brush(*brush); - buffer[static_cast( swap )].push_back(original); - - { - for (brush_vector_t::const_iterator i(m_brushlist.begin()); i != m_brushlist.end(); ++i) { - for (brush_vector_t::iterator j(buffer[static_cast( swap )].begin()); - j != buffer[static_cast( swap )].end(); ++j) { - if (Brush_subtract(*(*j), *(*i), buffer[static_cast( !swap )])) { - delete (*j); - } else { - buffer[static_cast( !swap )].push_back((*j)); - } - } - buffer[static_cast( swap )].clear(); - swap = !swap; - } - } - - brush_vector_t &out = buffer[static_cast( swap )]; - - if (out.size() == 1 && out.back() == original) { - delete original; - } else { - ++m_before; - for (brush_vector_t::const_iterator i = out.begin(); i != out.end(); ++i) { - ++m_after; - (*i)->removeEmptyFaces(); - if (!(*i)->empty()) { - NodeSmartReference node((new BrushNode())->node()); - Node_getBrush(node)->copy(*(*i)); - delete (*i); - Node_getTraversable(path.parent())->insert(node); - } else { - delete (*i); - } - } - Path_deleteTop(path); - } - } - } - } +SubtractBrushesFromUnselected( const brush_vector_t& brushlist, std::size_t& before, std::size_t& after ) + : m_brushlist( brushlist ), m_before( before ), m_after( after ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + return true; +} + +void post( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get().visible() ) { + Brush* brush = Node_getBrush( path.top() ); + if ( brush != 0 + && !Instance_getSelectable( instance )->isSelected() ) { + brush_vector_t buffer[2]; + bool swap = false; + Brush* original = new Brush( *brush ); + buffer[static_cast( swap )].push_back( original ); + + { + for ( brush_vector_t::const_iterator i( m_brushlist.begin() ); i != m_brushlist.end(); ++i ) + { + for ( brush_vector_t::iterator j( buffer[static_cast( swap )].begin() ); j != buffer[static_cast( swap )].end(); ++j ) + { + if ( Brush_subtract( *( *j ), *( *i ), buffer[static_cast( !swap )] ) ) { + delete ( *j ); + } + else + { + buffer[static_cast( !swap )].push_back( ( *j ) ); + } + } + buffer[static_cast( swap )].clear(); + swap = !swap; + } + } + + brush_vector_t& out = buffer[static_cast( swap )]; + + if ( out.size() == 1 && out.back() == original ) { + delete original; + } + else + { + ++m_before; + for ( brush_vector_t::const_iterator i = out.begin(); i != out.end(); ++i ) + { + ++m_after; + ( *i )->removeEmptyFaces(); + if ( !( *i )->empty() ) { + NodeSmartReference node( ( new BrushNode() )->node() ); + Node_getBrush( node )->copy( *( *i ) ); + delete ( *i ); + Node_getTraversable( path.parent() )->insert( node ); + } + else{ + delete ( *i ); + } + } + Path_deleteTop( path ); + } + } + } +} }; -void CSG_Subtract() +void CSG_Subtract(){ + brush_vector_t selected_brushes; + GlobalSceneGraph().traverse( BrushGatherSelected( selected_brushes ) ); + + if ( selected_brushes.empty() ) { + globalOutputStream() << "CSG Subtract: No brushes selected.\n"; + } + else + { + globalOutputStream() << "CSG Subtract: Subtracting " << Unsigned( selected_brushes.size() ) << " brushes.\n"; + + UndoableCommand undo( "brushSubtract" ); + + // subtract selected from unselected + std::size_t before = 0; + std::size_t after = 0; + GlobalSceneGraph().traverse( SubtractBrushesFromUnselected( selected_brushes, before, after ) ); + globalOutputStream() << "CSG Subtract: Result: " + << Unsigned( after ) << " fragment" << ( after == 1 ? "" : "s" ) + << " from " << Unsigned( before ) << " brush" << ( before == 1 ? "" : "es" ) << ".\n"; + + SceneChangeNotify(); + } +} + +class BrushSplitByPlaneSelected : public scene::Graph::Walker { - brush_vector_t selected_brushes; - GlobalSceneGraph().traverse(BrushGatherSelected(selected_brushes)); - - if (selected_brushes.empty()) { - globalOutputStream() << "CSG Subtract: No brushes selected.\n"; - } else { - globalOutputStream() << "CSG Subtract: Subtracting " << Unsigned(selected_brushes.size()) << " brushes.\n"; - - UndoableCommand undo("brushSubtract"); - - // subtract selected from unselected - std::size_t before = 0; - std::size_t after = 0; - GlobalSceneGraph().traverse(SubtractBrushesFromUnselected(selected_brushes, before, after)); - globalOutputStream() << "CSG Subtract: Result: " - << Unsigned(after) << " fragment" << (after == 1 ? "" : "s") - << " from " << Unsigned(before) << " brush" << (before == 1 ? "" : "es") << ".\n"; - - SceneChangeNotify(); - } -} - -class BrushSplitByPlaneSelected : public scene::Graph::Walker { - const Vector3 &m_p0; - const Vector3 &m_p1; - const Vector3 &m_p2; - const char *m_shader; - const TextureProjection &m_projection; - EBrushSplit m_split; +const Vector3& m_p0; +const Vector3& m_p1; +const Vector3& m_p2; +const char* m_shader; +const TextureProjection& m_projection; +EBrushSplit m_split; public: - BrushSplitByPlaneSelected(const Vector3 &p0, const Vector3 &p1, const Vector3 &p2, const char *shader, - const TextureProjection &projection, EBrushSplit split) - : m_p0(p0), m_p1(p1), m_p2(p2), m_shader(shader), m_projection(projection), m_split(split) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - return true; - } - - void post(const scene::Path &path, scene::Instance &instance) const - { - if (path.top().get().visible()) { - Brush *brush = Node_getBrush(path.top()); - if (brush != 0 - && Instance_getSelectable(instance)->isSelected()) { - Plane3 plane(plane3_for_points(m_p0, m_p1, m_p2)); - if (plane3_valid(plane)) { - brushsplit_t split = Brush_classifyPlane(*brush, m_split == eFront ? plane3_flipped(plane) : plane); - if (split.counts[ePlaneBack] && split.counts[ePlaneFront]) { - // the plane intersects this brush - if (m_split == eFrontAndBack) { - NodeSmartReference node((new BrushNode())->node()); - Brush *fragment = Node_getBrush(node); - fragment->copy(*brush); - Face *newFace = fragment->addPlane(m_p0, m_p1, m_p2, m_shader, m_projection); - if (newFace != 0 && m_split != eFront) { - newFace->flipWinding(); - } - fragment->removeEmptyFaces(); - ASSERT_MESSAGE(!fragment->empty(), "brush left with no faces after split"); - - Node_getTraversable(path.parent())->insert(node); - { - scene::Path fragmentPath = path; - fragmentPath.top() = makeReference(node.get()); - selectPath(fragmentPath, true); - } - } - - Face *newFace = brush->addPlane(m_p0, m_p1, m_p2, m_shader, m_projection); - if (newFace != 0 && m_split == eFront) { - newFace->flipWinding(); - } - brush->removeEmptyFaces(); - ASSERT_MESSAGE(!brush->empty(), "brush left with no faces after split"); - } else - // the plane does not intersect this brush - if (m_split != eFrontAndBack && split.counts[ePlaneBack] != 0) { - // the brush is "behind" the plane - Path_deleteTop(path); - } - } - } - } - } +BrushSplitByPlaneSelected( const Vector3& p0, const Vector3& p1, const Vector3& p2, const char* shader, const TextureProjection& projection, EBrushSplit split ) + : m_p0( p0 ), m_p1( p1 ), m_p2( p2 ), m_shader( shader ), m_projection( projection ), m_split( split ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + return true; +} + +void post( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get().visible() ) { + Brush* brush = Node_getBrush( path.top() ); + if ( brush != 0 + && Instance_getSelectable( instance )->isSelected() ) { + Plane3 plane( plane3_for_points( m_p0, m_p1, m_p2 ) ); + if ( plane3_valid( plane ) ) { + brushsplit_t split = Brush_classifyPlane( *brush, m_split == eFront ? plane3_flipped( plane ) : plane ); + if ( split.counts[ePlaneBack] && split.counts[ePlaneFront] ) { + // the plane intersects this brush + if ( m_split == eFrontAndBack ) { + NodeSmartReference node( ( new BrushNode() )->node() ); + Brush* fragment = Node_getBrush( node ); + fragment->copy( *brush ); + Face* newFace = fragment->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection ); + if ( newFace != 0 && m_split != eFront ) { + newFace->flipWinding(); + } + fragment->removeEmptyFaces(); + ASSERT_MESSAGE( !fragment->empty(), "brush left with no faces after split" ); + + Node_getTraversable( path.parent() )->insert( node ); + { + scene::Path fragmentPath = path; + fragmentPath.top() = makeReference( node.get() ); + selectPath( fragmentPath, true ); + } + } + + Face* newFace = brush->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection ); + if ( newFace != 0 && m_split == eFront ) { + newFace->flipWinding(); + } + brush->removeEmptyFaces(); + ASSERT_MESSAGE( !brush->empty(), "brush left with no faces after split" ); + } + else + // the plane does not intersect this brush + if ( m_split != eFrontAndBack && split.counts[ePlaneBack] != 0 ) { + // the brush is "behind" the plane + Path_deleteTop( path ); + } + } + } + } +} }; -void Scene_BrushSplitByPlane(scene::Graph &graph, const Vector3 &p0, const Vector3 &p1, const Vector3 &p2, - const char *shader, EBrushSplit split) -{ - TextureProjection projection; - TexDef_Construct_Default(projection); - graph.traverse(BrushSplitByPlaneSelected(p0, p1, p2, shader, projection, split)); - SceneChangeNotify(); +void Scene_BrushSplitByPlane( scene::Graph& graph, const Vector3& p0, const Vector3& p1, const Vector3& p2, const char* shader, EBrushSplit split ){ + TextureProjection projection; + TexDef_Construct_Default( projection ); + graph.traverse( BrushSplitByPlaneSelected( p0, p1, p2, shader, projection, split ) ); + SceneChangeNotify(); } -class BrushInstanceSetClipPlane : public scene::Graph::Walker { - Plane3 m_plane; +class BrushInstanceSetClipPlane : public scene::Graph::Walker +{ +Plane3 m_plane; public: - BrushInstanceSetClipPlane(const Plane3 &plane) - : m_plane(plane) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - BrushInstance *brush = Instance_getBrush(instance); - if (brush != 0 - && path.top().get().visible() - && brush->isSelected()) { - BrushInstance &brushInstance = *brush; - brushInstance.setClipPlane(m_plane); - } - return true; - } +BrushInstanceSetClipPlane( const Plane3& plane ) + : m_plane( plane ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + BrushInstance* brush = Instance_getBrush( instance ); + if ( brush != 0 + && path.top().get().visible() + && brush->isSelected() ) { + BrushInstance& brushInstance = *brush; + brushInstance.setClipPlane( m_plane ); + } + return true; +} }; -void Scene_BrushSetClipPlane(scene::Graph &graph, const Plane3 &plane) -{ - graph.traverse(BrushInstanceSetClipPlane(plane)); +void Scene_BrushSetClipPlane( scene::Graph& graph, const Plane3& plane ){ + graph.traverse( BrushInstanceSetClipPlane( plane ) ); } /* @@ -533,121 +519,127 @@ void Scene_BrushSetClipPlane(scene::Graph &graph, const Plane3 &plane) CSG_Merge ============= */ -bool Brush_merge(Brush &brush, const brush_vector_t &in, bool onlyshape) -{ - // gather potential outer faces - - { - typedef std::vector Faces; - Faces faces; - for (brush_vector_t::const_iterator i(in.begin()); i != in.end(); ++i) { - (*i)->evaluateBRep(); - for (Brush::const_iterator j((*i)->begin()); j != (*i)->end(); ++j) { - if (!(*j)->contributes()) { - continue; - } - - const Face &face1 = *(*j); - - bool skip = false; - // test faces of all input brushes - //!\todo SPEEDUP: Flag already-skip faces and only test brushes from i+1 upwards. - for (brush_vector_t::const_iterator k(in.begin()); !skip && k != in.end(); ++k) { - if (k != i) { // don't test a brush against itself - for (Brush::const_iterator l((*k)->begin()); !skip && l != (*k)->end(); ++l) { - const Face &face2 = *(*l); - - // face opposes another face - if (plane3_opposing(face1.plane3(), face2.plane3())) { - // skip opposing planes - skip = true; - break; - } - } - } - } - - // check faces already stored - for (Faces::const_iterator m = faces.begin(); !skip && m != faces.end(); ++m) { - const Face &face2 = *(*m); - - // face equals another face - if (plane3_equal(face1.plane3(), face2.plane3())) { - //if the texture/shader references should be the same but are not - if (!onlyshape && !shader_equal(face1.getShader().getShader(), face2.getShader().getShader())) { - return false; - } - // skip duplicate planes - skip = true; - break; - } - - // face1 plane intersects face2 winding or vice versa - if (Winding_PlanesConcave(face1.getWinding(), face2.getWinding(), face1.plane3(), face2.plane3())) { - // result would not be convex - return false; - } - } - - if (!skip) { - faces.push_back(&face1); - } - } - } - for (Faces::const_iterator i = faces.begin(); i != faces.end(); ++i) { - if (!brush.addFace(*(*i))) { - // result would have too many sides - return false; - } - } - } - - brush.removeEmptyFaces(); - - return true; -} - -void CSG_Merge(void) -{ - brush_vector_t selected_brushes; +bool Brush_merge( Brush& brush, const brush_vector_t& in, bool onlyshape ){ + // gather potential outer faces + + { + typedef std::vector Faces; + Faces faces; + for ( brush_vector_t::const_iterator i( in.begin() ); i != in.end(); ++i ) + { + ( *i )->evaluateBRep(); + for ( Brush::const_iterator j( ( *i )->begin() ); j != ( *i )->end(); ++j ) + { + if ( !( *j )->contributes() ) { + continue; + } + + const Face& face1 = *( *j ); + + bool skip = false; + // test faces of all input brushes + //!\todo SPEEDUP: Flag already-skip faces and only test brushes from i+1 upwards. + for ( brush_vector_t::const_iterator k( in.begin() ); !skip && k != in.end(); ++k ) + { + if ( k != i ) { // don't test a brush against itself + for ( Brush::const_iterator l( ( *k )->begin() ); !skip && l != ( *k )->end(); ++l ) + { + const Face& face2 = *( *l ); + + // face opposes another face + if ( plane3_opposing( face1.plane3(), face2.plane3() ) ) { + // skip opposing planes + skip = true; + break; + } + } + } + } + + // check faces already stored + for ( Faces::const_iterator m = faces.begin(); !skip && m != faces.end(); ++m ) + { + const Face& face2 = *( *m ); + + // face equals another face + if ( plane3_equal( face1.plane3(), face2.plane3() ) ) { + //if the texture/shader references should be the same but are not + if ( !onlyshape && !shader_equal( face1.getShader().getShader(), face2.getShader().getShader() ) ) { + return false; + } + // skip duplicate planes + skip = true; + break; + } + + // face1 plane intersects face2 winding or vice versa + if ( Winding_PlanesConcave( face1.getWinding(), face2.getWinding(), face1.plane3(), face2.plane3() ) ) { + // result would not be convex + return false; + } + } + + if ( !skip ) { + faces.push_back( &face1 ); + } + } + } + for ( Faces::const_iterator i = faces.begin(); i != faces.end(); ++i ) + { + if ( !brush.addFace( *( *i ) ) ) { + // result would have too many sides + return false; + } + } + } + + brush.removeEmptyFaces(); + + return true; +} + +void CSG_Merge( void ){ + brush_vector_t selected_brushes; - // remove selected - GlobalSceneGraph().traverse(BrushGatherSelected(selected_brushes)); + // remove selected + GlobalSceneGraph().traverse( BrushGatherSelected( selected_brushes ) ); - if (selected_brushes.empty()) { - globalOutputStream() << "CSG Merge: No brushes selected.\n"; - return; - } + if ( selected_brushes.empty() ) { + globalOutputStream() << "CSG Merge: No brushes selected.\n"; + return; + } - if (selected_brushes.size() < 2) { - globalOutputStream() << "CSG Merge: At least two brushes have to be selected.\n"; - return; - } + if ( selected_brushes.size() < 2 ) { + globalOutputStream() << "CSG Merge: At least two brushes have to be selected.\n"; + return; + } - globalOutputStream() << "CSG Merge: Merging " << Unsigned(selected_brushes.size()) << " brushes.\n"; + globalOutputStream() << "CSG Merge: Merging " << Unsigned( selected_brushes.size() ) << " brushes.\n"; - UndoableCommand undo("brushMerge"); + UndoableCommand undo( "brushMerge" ); - scene::Path merged_path = GlobalSelectionSystem().ultimateSelected().path(); + scene::Path merged_path = GlobalSelectionSystem().ultimateSelected().path(); - NodeSmartReference node((new BrushNode())->node()); - Brush *brush = Node_getBrush(node); - // if the new brush would not be convex - if (!Brush_merge(*brush, selected_brushes, true)) { - globalOutputStream() << "CSG Merge: Failed - result would not be convex.\n"; - } else { - ASSERT_MESSAGE(!brush->empty(), "brush left with no faces after merge"); + NodeSmartReference node( ( new BrushNode() )->node() ); + Brush* brush = Node_getBrush( node ); + // if the new brush would not be convex + if ( !Brush_merge( *brush, selected_brushes, true ) ) { + globalOutputStream() << "CSG Merge: Failed - result would not be convex.\n"; + } + else + { + ASSERT_MESSAGE( !brush->empty(), "brush left with no faces after merge" ); - // free the original brushes - GlobalSceneGraph().traverse(BrushDeleteSelected()); + // free the original brushes + GlobalSceneGraph().traverse( BrushDeleteSelected() ); - merged_path.pop(); - Node_getTraversable(merged_path.top())->insert(node); - merged_path.push(makeReference(node.get())); + merged_path.pop(); + Node_getTraversable( merged_path.top() )->insert( node ); + merged_path.push( makeReference( node.get() ) ); - selectPath(merged_path, true); + selectPath( merged_path, true ); - globalOutputStream() << "CSG Merge: Succeeded.\n"; - SceneChangeNotify(); - } + globalOutputStream() << "CSG Merge: Succeeded.\n"; + SceneChangeNotify(); + } } diff --git a/radiant/csg.h b/radiant/csg.h index 886680e1..e05c9eff 100644 --- a/radiant/csg.h +++ b/radiant/csg.h @@ -22,33 +22,32 @@ #if !defined( INCLUDED_CSG_H ) #define INCLUDED_CSG_H -void CSG_MakeHollow(void); +void CSG_MakeHollow( void ); -void CSG_MakeRoom(void); +void CSG_MakeRoom( void ); -void CSG_Subtract(void); +void CSG_Subtract( void ); -void CSG_Merge(void); +void CSG_Merge( void ); -namespace scene { - class Graph; +namespace scene +{ +class Graph; } -template -class BasicVector3; - +template class BasicVector3; typedef BasicVector3 Vector3; class Plane3; -void Scene_BrushSetClipPlane(scene::Graph &graph, const Plane3 &plane); +void Scene_BrushSetClipPlane( scene::Graph& graph, const Plane3& plane ); -enum EBrushSplit { - eFront, - eBack, - eFrontAndBack, +enum EBrushSplit +{ + eFront, + eBack, + eFrontAndBack, }; -void Scene_BrushSplitByPlane(scene::Graph &graph, const Vector3 &p0, const Vector3 &p1, const Vector3 &p2, - const char *shader, EBrushSplit split); +void Scene_BrushSplitByPlane( scene::Graph& graph, const Vector3& p0, const Vector3& p1, const Vector3& p2, const char* shader, EBrushSplit split ); #endif diff --git a/radiant/entity.cpp b/radiant/entity.cpp index 375e54d6..adb4ed11 100644 --- a/radiant/entity.cpp +++ b/radiant/entity.cpp @@ -49,591 +49,567 @@ #include "uilib/uilib.h" -struct entity_globals_t { - Vector3 color_entity; +struct entity_globals_t +{ + Vector3 color_entity; - entity_globals_t() : - color_entity(0.0f, 0.0f, 0.0f) - { - } + entity_globals_t() : + color_entity( 0.0f, 0.0f, 0.0f ){ + } }; entity_globals_t g_entity_globals; -class EntitySetKeyValueSelected : public scene::Graph::Walker { - const char *m_key; - const char *m_value; +class EntitySetKeyValueSelected : public scene::Graph::Walker +{ +const char* m_key; +const char* m_value; public: - EntitySetKeyValueSelected(const char *key, const char *value) - : m_key(key), m_value(value) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - return true; - } - - void post(const scene::Path &path, scene::Instance &instance) const - { - Entity *entity = Node_getEntity(path.top()); - if (entity != 0 - && (instance.childSelected() || Instance_getSelectable(instance)->isSelected())) { - entity->setKeyValue(m_key, m_value); - } - } +EntitySetKeyValueSelected( const char* key, const char* value ) + : m_key( key ), m_value( value ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + return true; +} + +void post( const scene::Path& path, scene::Instance& instance ) const { + Entity* entity = Node_getEntity( path.top() ); + if ( entity != 0 + && ( instance.childSelected() || Instance_getSelectable( instance )->isSelected() ) ) { + entity->setKeyValue( m_key, m_value ); + } +} }; -class EntitySetClassnameSelected : public scene::Graph::Walker { - const char *m_classname; +class EntitySetClassnameSelected : public scene::Graph::Walker +{ +const char* m_classname; public: - EntitySetClassnameSelected(const char *classname) - : m_classname(classname) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - return true; - } - - void post(const scene::Path &path, scene::Instance &instance) const - { - Entity *entity = Node_getEntity(path.top()); - if (entity != 0 - && (instance.childSelected() || Instance_getSelectable(instance)->isSelected())) { - NodeSmartReference node(GlobalEntityCreator().createEntity( - GlobalEntityClassManager().findOrInsert(m_classname, node_is_group(path.top())))); - - EntityCopyingVisitor visitor(*Node_getEntity(node)); - - entity->forEachKeyValue(visitor); - - NodeSmartReference child(path.top().get()); - NodeSmartReference parent(path.parent().get()); - Node_getTraversable(parent)->erase(child); - if (Node_getTraversable(child) != 0 - && Node_getTraversable(node) != 0 - && node_is_group(node)) { - parentBrushes(child, node); - } - Node_getTraversable(parent)->insert(node); - } - } +EntitySetClassnameSelected( const char* classname ) + : m_classname( classname ){ +} +bool pre( const scene::Path& path, scene::Instance& instance ) const { + return true; +} +void post( const scene::Path& path, scene::Instance& instance ) const { + Entity* entity = Node_getEntity( path.top() ); + if ( entity != 0 + && ( instance.childSelected() || Instance_getSelectable( instance )->isSelected() ) ) { + NodeSmartReference node( GlobalEntityCreator().createEntity( GlobalEntityClassManager().findOrInsert( m_classname, node_is_group( path.top() ) ) ) ); + + EntityCopyingVisitor visitor( *Node_getEntity( node ) ); + + entity->forEachKeyValue( visitor ); + + NodeSmartReference child( path.top().get() ); + NodeSmartReference parent( path.parent().get() ); + Node_getTraversable( parent )->erase( child ); + if ( Node_getTraversable( child ) != 0 + && Node_getTraversable( node ) != 0 + && node_is_group( node ) ) { + parentBrushes( child, node ); + } + Node_getTraversable( parent )->insert( node ); + } +} }; -void Scene_EntitySetKeyValue_Selected(const char *key, const char *value) -{ - GlobalSceneGraph().traverse(EntitySetKeyValueSelected(key, value)); +void Scene_EntitySetKeyValue_Selected( const char* key, const char* value ){ + GlobalSceneGraph().traverse( EntitySetKeyValueSelected( key, value ) ); } -void Scene_EntitySetClassname_Selected(const char *classname) -{ - GlobalSceneGraph().traverse(EntitySetClassnameSelected(classname)); +void Scene_EntitySetClassname_Selected( const char* classname ){ + GlobalSceneGraph().traverse( EntitySetClassnameSelected( classname ) ); } -void Entity_ungroupSelected() -{ - if (GlobalSelectionSystem().countSelected() < 1) { - return; - } +void Entity_ungroupSelected(){ + if ( GlobalSelectionSystem().countSelected() < 1 ) { + return; + } - UndoableCommand undo("ungroupSelectedEntities"); + UndoableCommand undo( "ungroupSelectedEntities" ); - scene::Path world_path(makeReference(GlobalSceneGraph().root())); - world_path.push(makeReference(Map_FindOrInsertWorldspawn(g_map))); + scene::Path world_path( makeReference( GlobalSceneGraph().root() ) ); + world_path.push( makeReference( Map_FindOrInsertWorldspawn( g_map ) ) ); - scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); - scene::Path path = instance.path(); + scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); + scene::Path path = instance.path(); - if (!Node_isEntity(path.top())) { - path.pop(); - } + if ( !Node_isEntity( path.top() ) ) { + path.pop(); + } - if (Node_getEntity(path.top()) != 0 - && node_is_group(path.top())) { - if (world_path.top().get_pointer() != path.top().get_pointer()) { - parentBrushes(path.top(), world_path.top()); - Path_deleteTop(path); - } - } + if ( Node_getEntity( path.top() ) != 0 + && node_is_group( path.top() ) ) { + if ( world_path.top().get_pointer() != path.top().get_pointer() ) { + parentBrushes( path.top(), world_path.top() ); + Path_deleteTop( path ); + } + } } -class EntityFindSelected : public scene::Graph::Walker { +class EntityFindSelected : public scene::Graph::Walker +{ public: - mutable const scene::Path *groupPath; - mutable scene::Instance *groupInstance; - - EntityFindSelected() : groupPath(0), groupInstance(0) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - return true; - } - - void post(const scene::Path &path, scene::Instance &instance) const - { - Entity *entity = Node_getEntity(path.top()); - if (entity != 0 - && Instance_getSelectable(instance)->isSelected() - && node_is_group(path.top()) - && !groupPath) { - groupPath = &path; - groupInstance = &instance; - } - } +mutable const scene::Path *groupPath; +mutable scene::Instance *groupInstance; + +EntityFindSelected() : groupPath( 0 ), groupInstance( 0 ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + return true; +} + +void post( const scene::Path& path, scene::Instance& instance ) const { + Entity* entity = Node_getEntity( path.top() ); + if ( entity != 0 + && Instance_getSelectable( instance )->isSelected() + && node_is_group( path.top() ) + && !groupPath ) { + groupPath = &path; + groupInstance = &instance; + } +} }; -class EntityGroupSelected : public scene::Graph::Walker { - NodeSmartReference group, worldspawn; +class EntityGroupSelected : public scene::Graph::Walker +{ +NodeSmartReference group, worldspawn; //typedef std::pair DeletionPair; //Stack deleteme; public: - EntityGroupSelected(const scene::Path &p) : group(p.top().get()), worldspawn(Map_FindOrInsertWorldspawn(g_map)) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - return true; - } - - void post(const scene::Path &path, scene::Instance &instance) const - { - Selectable *selectable = Instance_getSelectable(instance); - if (selectable && selectable->isSelected()) { - Entity *entity = Node_getEntity(path.top()); - if (entity == 0 && Node_isPrimitive(path.top())) { - NodeSmartReference child(path.top().get()); - NodeSmartReference parent(path.parent().get()); - - if (path.size() >= 3 && parent != worldspawn) { - NodeSmartReference parentparent(path[path.size() - 3].get()); - - Node_getTraversable(parent)->erase(child); - Node_getTraversable(group)->insert(child); - - if (Node_getTraversable(parent)->empty()) { - //deleteme.push(DeletionPair(parentparent, parent)); - Node_getTraversable(parentparent)->erase(parent); - } - } else { - Node_getTraversable(parent)->erase(child); - Node_getTraversable(group)->insert(child); - } - } - } - } -}; +EntityGroupSelected( const scene::Path &p ) : group( p.top().get() ), worldspawn( Map_FindOrInsertWorldspawn( g_map ) ){ +} -void Entity_groupSelected() -{ - if (GlobalSelectionSystem().countSelected() < 1) { - return; - } +bool pre( const scene::Path& path, scene::Instance& instance ) const { + return true; +} - UndoableCommand undo("groupSelectedEntities"); +void post( const scene::Path& path, scene::Instance& instance ) const { + Selectable *selectable = Instance_getSelectable( instance ); + if ( selectable && selectable->isSelected() ) { + Entity* entity = Node_getEntity( path.top() ); + if ( entity == 0 && Node_isPrimitive( path.top() ) ) { + NodeSmartReference child( path.top().get() ); + NodeSmartReference parent( path.parent().get() ); + + if ( path.size() >= 3 && parent != worldspawn ) { + NodeSmartReference parentparent( path[path.size() - 3].get() ); + + Node_getTraversable( parent )->erase( child ); + Node_getTraversable( group )->insert( child ); + + if ( Node_getTraversable( parent )->empty() ) { + //deleteme.push(DeletionPair(parentparent, parent)); + Node_getTraversable( parentparent )->erase( parent ); + } + } + else + { + Node_getTraversable( parent )->erase( child ); + Node_getTraversable( group )->insert( child ); + } + } + } +} +}; + +void Entity_groupSelected(){ + if ( GlobalSelectionSystem().countSelected() < 1 ) { + return; + } + + UndoableCommand undo( "groupSelectedEntities" ); + + scene::Path world_path( makeReference( GlobalSceneGraph().root() ) ); + world_path.push( makeReference( Map_FindOrInsertWorldspawn( g_map ) ) ); + + EntityFindSelected fse; + GlobalSceneGraph().traverse( fse ); + if ( fse.groupPath ) { + GlobalSceneGraph().traverse( EntityGroupSelected( *fse.groupPath ) ); + } + else + { + GlobalSceneGraph().traverse( EntityGroupSelected( world_path ) ); + } +} - scene::Path world_path(makeReference(GlobalSceneGraph().root())); - world_path.push(makeReference(Map_FindOrInsertWorldspawn(g_map))); - EntityFindSelected fse; - GlobalSceneGraph().traverse(fse); - if (fse.groupPath) { - GlobalSceneGraph().traverse(EntityGroupSelected(*fse.groupPath)); - } else { - GlobalSceneGraph().traverse(EntityGroupSelected(world_path)); - } +void Entity_connectSelected(){ + if ( GlobalSelectionSystem().countSelected() == 2 ) { + GlobalEntityCreator().connectEntities( + GlobalSelectionSystem().penultimateSelected().path(), + GlobalSelectionSystem().ultimateSelected().path(), + 0 + ); + } + else + { + globalErrorStream() << "entityConnectSelected: exactly two instances must be selected\n"; + } } +void Entity_killconnectSelected(){ + if ( GlobalSelectionSystem().countSelected() == 2 ) { + GlobalEntityCreator().connectEntities( + GlobalSelectionSystem().penultimateSelected().path(), + GlobalSelectionSystem().ultimateSelected().path(), + 1 + ); + } + else + { + globalErrorStream() << "entityKillConnectSelected: exactly two instances must be selected\n"; + } +} -void Entity_connectSelected() -{ - if (GlobalSelectionSystem().countSelected() == 2) { - GlobalEntityCreator().connectEntities( - GlobalSelectionSystem().penultimateSelected().path(), - GlobalSelectionSystem().ultimateSelected().path(), - 0 - ); - } else { - globalErrorStream() << "entityConnectSelected: exactly two instances must be selected\n"; - } -} - -void Entity_killconnectSelected() -{ - if (GlobalSelectionSystem().countSelected() == 2) { - GlobalEntityCreator().connectEntities( - GlobalSelectionSystem().penultimateSelected().path(), - GlobalSelectionSystem().ultimateSelected().path(), - 1 - ); - } else { - globalErrorStream() << "entityKillConnectSelected: exactly two instances must be selected\n"; - } -} - -AABB Doom3Light_getBounds(const AABB &workzone) -{ - AABB aabb(workzone); - - Vector3 defaultRadius(300, 300, 300); - if (!string_parse_vector3( - EntityClass_valueForKey(*GlobalEntityClassManager().findOrInsert("light", false), "light_radius"), - defaultRadius)) { - globalErrorStream() << "Doom3Light_getBounds: failed to parse default light radius\n"; - } - - if (aabb.extents[0] == 0) { - aabb.extents[0] = defaultRadius[0]; - } - if (aabb.extents[1] == 0) { - aabb.extents[1] = defaultRadius[1]; - } - if (aabb.extents[2] == 0) { - aabb.extents[2] = defaultRadius[2]; - } - - if (aabb_valid(aabb)) { - return aabb; - } - return AABB(Vector3(0, 0, 0), Vector3(64, 64, 64)); +AABB Doom3Light_getBounds( const AABB& workzone ){ + AABB aabb( workzone ); + + Vector3 defaultRadius( 300, 300, 300 ); + if ( !string_parse_vector3( EntityClass_valueForKey( *GlobalEntityClassManager().findOrInsert( "light", false ), "light_radius" ), defaultRadius ) ) { + globalErrorStream() << "Doom3Light_getBounds: failed to parse default light radius\n"; + } + + if ( aabb.extents[0] == 0 ) { + aabb.extents[0] = defaultRadius[0]; + } + if ( aabb.extents[1] == 0 ) { + aabb.extents[1] = defaultRadius[1]; + } + if ( aabb.extents[2] == 0 ) { + aabb.extents[2] = defaultRadius[2]; + } + + if ( aabb_valid( aabb ) ) { + return aabb; + } + return AABB( Vector3( 0, 0, 0 ), Vector3( 64, 64, 64 ) ); } int g_iLastLightIntensity; -void Entity_createFromSelection(const char *name, const Vector3 &origin) -{ +void Entity_createFromSelection( const char* name, const Vector3& origin ){ #if 0 - if ( string_equal_nocase( name, "worldspawn" ) ) { - ui::alert( MainFrame_getWindow( ), "Can't create an entity with worldspawn.", "info" ); - return; - } + if ( string_equal_nocase( name, "worldspawn" ) ) { + ui::alert( MainFrame_getWindow( ), "Can't create an entity with worldspawn.", "info" ); + return; + } #endif - EntityClass *entityClass = GlobalEntityClassManager().findOrInsert(name, true); - - bool isModel = (string_compare_nocase_n(name, "misc_", 5) == 0 && - string_equal_nocase(name + string_length(name) - 5, "model")) // misc_*model (also misc_model) - || string_equal_nocase(name, "model_static") - || (GlobalSelectionSystem().countSelected() == 0 && string_equal_nocase(name, "func_static")); - - bool brushesSelected = Scene_countSelectedBrushes(GlobalSceneGraph()) != 0; - - if (!(entityClass->fixedsize || isModel) && !brushesSelected) { - globalErrorStream() << "failed to create a group entity - no brushes are selected\n"; - return; - } - - AABB workzone(aabb_for_minmax(Select_getWorkZone().d_work_min, Select_getWorkZone().d_work_max)); - - - NodeSmartReference node(GlobalEntityCreator().createEntity(entityClass)); - - Node_getTraversable(GlobalSceneGraph().root())->insert(node); - - scene::Path entitypath(makeReference(GlobalSceneGraph().root())); - entitypath.push(makeReference(node.get())); - scene::Instance &instance = findInstance(entitypath); - - if (entityClass->fixedsize || (isModel && !brushesSelected)) { - Select_Delete(); - - Transformable *transform = Instance_getTransformable(instance); - if (transform != 0) { - transform->setType(TRANSFORM_PRIMITIVE); - transform->setTranslation(origin); - transform->freezeTransform(); - } - - GlobalSelectionSystem().setSelectedAll(false); - - Instance_setSelected(instance, true); - } else { - if (g_pGameDescription->mGameType == "doom3") { - Node_getEntity(node)->setKeyValue("model", Node_getEntity(node)->getKeyValue("name")); - } - - Scene_parentSelectedBrushesToEntity(GlobalSceneGraph(), node); - Scene_forEachChildSelectable(SelectableSetSelected(true), instance.path()); - } - - // tweaking: when right clic dropping a light entity, ask for light value in a custom dialog box - // see SF bug 105383 - - if (g_pGameDescription->mGameType == "hl") { - // FIXME - Hydra: really we need a combined light AND color dialog for halflife. - if (string_equal_nocase(name, "light") - || string_equal_nocase(name, "light_environment") - || string_equal_nocase(name, "light_spot")) { - int intensity = g_iLastLightIntensity; - - if (DoLightIntensityDlg(&intensity) == eIDOK) { - g_iLastLightIntensity = intensity; - char buf[30]; - sprintf(buf, "255 255 255 %d", intensity); - Node_getEntity(node)->setKeyValue("_light", buf); - } - } - } else if (string_equal_nocase(name, "light")) { - if (g_pGameDescription->mGameType != "doom3") { - int intensity = g_iLastLightIntensity; - - if (DoLightIntensityDlg(&intensity) == eIDOK) { - g_iLastLightIntensity = intensity; - char buf[10]; - sprintf(buf, "%d", intensity); - Node_getEntity(node)->setKeyValue("light", buf); - } - } else if (brushesSelected) { // use workzone to set light position/size for doom3 lights, if there are brushes selected - AABB bounds(Doom3Light_getBounds(workzone)); - StringOutputStream key(64); - key << bounds.origin[0] << " " << bounds.origin[1] << " " << bounds.origin[2]; - Node_getEntity(node)->setKeyValue("origin", key.c_str()); - key.clear(); - key << bounds.extents[0] << " " << bounds.extents[1] << " " << bounds.extents[2]; - Node_getEntity(node)->setKeyValue("light_radius", key.c_str()); - } - } - - if (isModel) { - const char *model = misc_model_dialog(MainFrame_getWindow()); - if (model != 0) { - Node_getEntity(node)->setKeyValue("model", model); - } - } + EntityClass* entityClass = GlobalEntityClassManager().findOrInsert( name, true ); + + bool isModel = ( string_compare_nocase_n( name, "misc_", 5 ) == 0 && string_equal_nocase( name + string_length( name ) - 5, "model" ) ) // misc_*model (also misc_model) + || string_equal_nocase( name, "model_static" ) + || ( GlobalSelectionSystem().countSelected() == 0 && string_equal_nocase( name, "func_static" ) ); + + bool brushesSelected = Scene_countSelectedBrushes( GlobalSceneGraph() ) != 0; + + if ( !( entityClass->fixedsize || isModel ) && !brushesSelected ) { + globalErrorStream() << "failed to create a group entity - no brushes are selected\n"; + return; + } + + AABB workzone( aabb_for_minmax( Select_getWorkZone().d_work_min, Select_getWorkZone().d_work_max ) ); + + + NodeSmartReference node( GlobalEntityCreator().createEntity( entityClass ) ); + + Node_getTraversable( GlobalSceneGraph().root() )->insert( node ); + + scene::Path entitypath( makeReference( GlobalSceneGraph().root() ) ); + entitypath.push( makeReference( node.get() ) ); + scene::Instance& instance = findInstance( entitypath ); + + if ( entityClass->fixedsize || ( isModel && !brushesSelected ) ) { + Select_Delete(); + + Transformable* transform = Instance_getTransformable( instance ); + if ( transform != 0 ) { + transform->setType( TRANSFORM_PRIMITIVE ); + transform->setTranslation( origin ); + transform->freezeTransform(); + } + + GlobalSelectionSystem().setSelectedAll( false ); + + Instance_setSelected( instance, true ); + } + else + { + if ( g_pGameDescription->mGameType == "doom3" ) { + Node_getEntity( node )->setKeyValue( "model", Node_getEntity( node )->getKeyValue( "name" ) ); + } + + Scene_parentSelectedBrushesToEntity( GlobalSceneGraph(), node ); + Scene_forEachChildSelectable( SelectableSetSelected( true ), instance.path() ); + } + + // tweaking: when right clic dropping a light entity, ask for light value in a custom dialog box + // see SF bug 105383 + + if ( g_pGameDescription->mGameType == "hl" ) { + // FIXME - Hydra: really we need a combined light AND color dialog for halflife. + if ( string_equal_nocase( name, "light" ) + || string_equal_nocase( name, "light_environment" ) + || string_equal_nocase( name, "light_spot" ) ) { + int intensity = g_iLastLightIntensity; + + if ( DoLightIntensityDlg( &intensity ) == eIDOK ) { + g_iLastLightIntensity = intensity; + char buf[30]; + sprintf( buf, "255 255 255 %d", intensity ); + Node_getEntity( node )->setKeyValue( "_light", buf ); + } + } + } + else if ( string_equal_nocase( name, "light" ) ) { + if ( g_pGameDescription->mGameType != "doom3" ) { + int intensity = g_iLastLightIntensity; + + if ( DoLightIntensityDlg( &intensity ) == eIDOK ) { + g_iLastLightIntensity = intensity; + char buf[10]; + sprintf( buf, "%d", intensity ); + Node_getEntity( node )->setKeyValue( "light", buf ); + } + } + else if ( brushesSelected ) { // use workzone to set light position/size for doom3 lights, if there are brushes selected + AABB bounds( Doom3Light_getBounds( workzone ) ); + StringOutputStream key( 64 ); + key << bounds.origin[0] << " " << bounds.origin[1] << " " << bounds.origin[2]; + Node_getEntity( node )->setKeyValue( "origin", key.c_str() ); + key.clear(); + key << bounds.extents[0] << " " << bounds.extents[1] << " " << bounds.extents[2]; + Node_getEntity( node )->setKeyValue( "light_radius", key.c_str() ); + } + } + + if ( isModel ) { + const char* model = misc_model_dialog(MainFrame_getWindow()); + if ( model != 0 ) { + Node_getEntity( node )->setKeyValue( "model", model ); + } + } } #if 0 bool DoNormalisedColor( Vector3& color ){ - if ( !color_dialog( MainFrame_getWindow( ), color ) ) { - return false; - } - /* - ** scale colors so that at least one component is at 1.0F - */ - - float largest = 0.0F; - - if ( color[0] > largest ) { - largest = color[0]; - } - if ( color[1] > largest ) { - largest = color[1]; - } - if ( color[2] > largest ) { - largest = color[2]; - } - - if ( largest == 0.0F ) { - color[0] = 1.0F; - color[1] = 1.0F; - color[2] = 1.0F; - } - else - { - float scaler = 1.0F / largest; - - color[0] *= scaler; - color[1] *= scaler; - color[2] *= scaler; - } - - return true; + if ( !color_dialog( MainFrame_getWindow( ), color ) ) { + return false; + } + /* + ** scale colors so that at least one component is at 1.0F + */ + + float largest = 0.0F; + + if ( color[0] > largest ) { + largest = color[0]; + } + if ( color[1] > largest ) { + largest = color[1]; + } + if ( color[2] > largest ) { + largest = color[2]; + } + + if ( largest == 0.0F ) { + color[0] = 1.0F; + color[1] = 1.0F; + color[2] = 1.0F; + } + else + { + float scaler = 1.0F / largest; + + color[0] *= scaler; + color[1] *= scaler; + color[2] *= scaler; + } + + return true; } #endif -void NormalizeColor(Vector3 &color) -{ - // scale colors so that at least one component is at 1.0F - - float largest = 0.0F; - - if (color[0] > largest) { - largest = color[0]; - } - if (color[1] > largest) { - largest = color[1]; - } - if (color[2] > largest) { - largest = color[2]; - } - - if (largest == 0.0F) { - color[0] = 1.0F; - color[1] = 1.0F; - color[2] = 1.0F; - } else { - float scaler = 1.0F / largest; - - color[0] *= scaler; - color[1] *= scaler; - color[2] *= scaler; - } -} - -void Entity_normalizeColor() -{ - if (GlobalSelectionSystem().countSelected() != 0) { - const scene::Path &path = GlobalSelectionSystem().ultimateSelected().path(); - Entity *entity = Node_getEntity(path.top()); - - if (entity != 0) { - const char *strColor = entity->getKeyValue("_color"); - if (!string_empty(strColor)) { - Vector3 rgb; - if (string_parse_vector3(strColor, rgb)) { - g_entity_globals.color_entity = rgb; - NormalizeColor(g_entity_globals.color_entity); - - char buffer[128]; - sprintf(buffer, "%g %g %g", g_entity_globals.color_entity[0], - g_entity_globals.color_entity[1], - g_entity_globals.color_entity[2]); - - Scene_EntitySetKeyValue_Selected("_color", buffer); - } - } - } - } -} - -void Entity_setColour() -{ - if (GlobalSelectionSystem().countSelected() != 0) { - bool normalize = false; - const scene::Path &path = GlobalSelectionSystem().ultimateSelected().path(); - Entity *entity = Node_getEntity(path.top()); - - if (entity != 0) { - const char *strColor = entity->getKeyValue("_color"); - if (!string_empty(strColor)) { - Vector3 rgb; - if (string_parse_vector3(strColor, rgb)) { - g_entity_globals.color_entity = rgb; - } - } - - if (g_pGameDescription->mGameType == "doom3") { - normalize = false; - } - - if (color_dialog(MainFrame_getWindow(), g_entity_globals.color_entity)) { - if (normalize) { - NormalizeColor(g_entity_globals.color_entity); - } - - char buffer[128]; - sprintf(buffer, "%g %g %g", g_entity_globals.color_entity[0], - g_entity_globals.color_entity[1], - g_entity_globals.color_entity[2]); - - Scene_EntitySetKeyValue_Selected("_color", buffer); - } - } - } +void NormalizeColor( Vector3& color ){ + // scale colors so that at least one component is at 1.0F + + float largest = 0.0F; + + if ( color[0] > largest ) { + largest = color[0]; + } + if ( color[1] > largest ) { + largest = color[1]; + } + if ( color[2] > largest ) { + largest = color[2]; + } + + if ( largest == 0.0F ) { + color[0] = 1.0F; + color[1] = 1.0F; + color[2] = 1.0F; + } + else + { + float scaler = 1.0F / largest; + + color[0] *= scaler; + color[1] *= scaler; + color[2] *= scaler; + } +} + +void Entity_normalizeColor(){ + if ( GlobalSelectionSystem().countSelected() != 0 ) { + const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path(); + Entity* entity = Node_getEntity( path.top() ); + + if ( entity != 0 ) { + const char* strColor = entity->getKeyValue( "_color" ); + if ( !string_empty( strColor ) ) { + Vector3 rgb; + if ( string_parse_vector3( strColor, rgb ) ) { + g_entity_globals.color_entity = rgb; + NormalizeColor( g_entity_globals.color_entity ); + + char buffer[128]; + sprintf( buffer, "%g %g %g", g_entity_globals.color_entity[0], + g_entity_globals.color_entity[1], + g_entity_globals.color_entity[2] ); + + Scene_EntitySetKeyValue_Selected( "_color", buffer ); + } + } + } + } +} + +void Entity_setColour(){ + if ( GlobalSelectionSystem().countSelected() != 0 ) { + bool normalize = false; + const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path(); + Entity* entity = Node_getEntity( path.top() ); + + if ( entity != 0 ) { + const char* strColor = entity->getKeyValue( "_color" ); + if ( !string_empty( strColor ) ) { + Vector3 rgb; + if ( string_parse_vector3( strColor, rgb ) ) { + g_entity_globals.color_entity = rgb; + } + } + + if ( g_pGameDescription->mGameType == "doom3" ) { + normalize = false; + } + + if ( color_dialog( MainFrame_getWindow(), g_entity_globals.color_entity ) ) { + if ( normalize ) { + NormalizeColor( g_entity_globals.color_entity ); + } + + char buffer[128]; + sprintf( buffer, "%g %g %g", g_entity_globals.color_entity[0], + g_entity_globals.color_entity[1], + g_entity_globals.color_entity[2] ); + + Scene_EntitySetKeyValue_Selected( "_color", buffer ); + } + } + } } CopiedString g_strLastModelFolder = ""; -const char *getLastModelFolderPath() -{ - if (g_strLastModelFolder.empty()) { - GlobalPreferenceSystem().registerPreference("LastModelFolder", make_property_string(g_strLastModelFolder)); - if (g_strLastModelFolder.empty()) { - StringOutputStream buffer(1024); - buffer << g_qeglobals.m_userGamePath.c_str() << "models/"; - if (!file_readable(buffer.c_str())) { - // just go to fsmain - buffer.clear(); - buffer << g_qeglobals.m_userGamePath.c_str() << "/"; - } - g_strLastModelFolder = buffer.c_str(); - } - } - return g_strLastModelFolder.c_str(); -} - -const char *misc_model_dialog(ui::Widget parent) -{ - const char *filename = parent.file_dialog(TRUE, "Choose Model", getLastModelFolderPath(), ModelLoader::Name()); +const char *getLastModelFolderPath(){ + if ( g_strLastModelFolder.empty() ) { + GlobalPreferenceSystem().registerPreference( "LastModelFolder", make_property_string( g_strLastModelFolder ) ); + if ( g_strLastModelFolder.empty() ) { + StringOutputStream buffer( 1024 ); + buffer << g_qeglobals.m_userGamePath.c_str() << "models/"; + if ( !file_readable( buffer.c_str() ) ) { + // just go to fsmain + buffer.clear(); + buffer << g_qeglobals.m_userGamePath.c_str() << "/"; + } + g_strLastModelFolder = buffer.c_str(); + } + } + return g_strLastModelFolder.c_str(); +} - if (filename != NULL) { - g_strLastModelFolder = g_path_get_dirname(filename); - // use VFS to get the correct relative path - const char *relative = path_make_relative(filename, GlobalFileSystem().findRoot(filename)); - if (relative == filename) { - globalOutputStream() << "WARNING: could not extract the relative path, using full path instead\n"; - } - return relative; - } - return 0; +const char *misc_model_dialog( ui::Widget parent ){ + const char *filename = parent.file_dialog( TRUE, "Choose Model", getLastModelFolderPath(), ModelLoader::Name() ); + + if ( filename != NULL ) { + g_strLastModelFolder = g_path_get_dirname( filename ); + // use VFS to get the correct relative path + const char *relative = path_make_relative( filename, GlobalFileSystem().findRoot( filename ) ); + if ( relative == filename ) { + globalOutputStream() << "WARNING: could not extract the relative path, using full path instead\n"; + } + return relative; + } + return 0; } struct LightRadii { - static void Export(const EntityCreator &self, const Callback &returnz) - { - returnz(self.getLightRadii()); - } - - static void Import(EntityCreator &self, bool value) - { - self.setLightRadii(value); - } + static void Export(const EntityCreator &self, const Callback &returnz) { + returnz(self.getLightRadii()); + } + + static void Import(EntityCreator &self, bool value) { + self.setLightRadii(value); + } }; -void Entity_constructPreferences(PreferencesPage &page) -{ - page.appendCheckBox( - "Show", "Light Radii", - make_property(GlobalEntityCreator()) - ); +void Entity_constructPreferences( PreferencesPage& page ){ + page.appendCheckBox( + "Show", "Light Radii", + make_property(GlobalEntityCreator()) + ); } - -void Entity_constructPage(PreferenceGroup &group) -{ - PreferencesPage page(group.createPage("Entities", "Entity Display Preferences")); - Entity_constructPreferences(page); +void Entity_constructPage( PreferenceGroup& group ){ + PreferencesPage page( group.createPage( "Entities", "Entity Display Preferences" ) ); + Entity_constructPreferences( page ); } -void Entity_registerPreferencesPage() -{ - PreferencesDialog_addDisplayPage(makeCallbackF(Entity_constructPage)); +void Entity_registerPreferencesPage(){ + PreferencesDialog_addDisplayPage( makeCallbackF(Entity_constructPage) ); } -void Entity_constructMenu(ui::Menu menu) -{ - create_menu_item_with_mnemonic(menu, "_Regroup", "GroupSelection"); - create_menu_item_with_mnemonic(menu, "_Ungroup", "UngroupSelection"); - create_menu_item_with_mnemonic(menu, "_Connect", "ConnectSelection"); - create_menu_item_with_mnemonic(menu, "_KillConnect", "KillConnectSelection"); - create_menu_item_with_mnemonic(menu, "_Select Color...", "EntityColor"); - create_menu_item_with_mnemonic(menu, "_Normalize Color...", "NormalizeColor"); +void Entity_constructMenu( ui::Menu menu ){ + create_menu_item_with_mnemonic( menu, "_Regroup", "GroupSelection" ); + create_menu_item_with_mnemonic( menu, "_Ungroup", "UngroupSelection" ); + create_menu_item_with_mnemonic( menu, "_Connect", "ConnectSelection" ); + create_menu_item_with_mnemonic( menu, "_KillConnect", "KillConnectSelection" ); + create_menu_item_with_mnemonic( menu, "_Select Color...", "EntityColor" ); + create_menu_item_with_mnemonic( menu, "_Normalize Color...", "NormalizeColor" ); } -void Entity_Construct() -{ - GlobalCommands_insert("EntityColor", makeCallbackF(Entity_setColour), Accelerator('K')); - GlobalCommands_insert("NormalizeColor", makeCallbackF(Entity_normalizeColor)); - GlobalCommands_insert("ConnectSelection", makeCallbackF(Entity_connectSelected), - Accelerator('K', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("KillConnectSelection", makeCallbackF(Entity_killconnectSelected), - Accelerator('K', (GdkModifierType) (GDK_SHIFT_MASK))); - GlobalCommands_insert("GroupSelection", makeCallbackF(Entity_groupSelected)); - GlobalCommands_insert("UngroupSelection", makeCallbackF(Entity_ungroupSelected)); +void Entity_Construct(){ + GlobalCommands_insert( "EntityColor", makeCallbackF(Entity_setColour), Accelerator( 'K' ) ); + GlobalCommands_insert( "NormalizeColor", makeCallbackF(Entity_normalizeColor) ); + GlobalCommands_insert( "ConnectSelection", makeCallbackF(Entity_connectSelected), Accelerator( 'K', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "KillConnectSelection", makeCallbackF(Entity_killconnectSelected), Accelerator( 'K', (GdkModifierType)( GDK_SHIFT_MASK ) ) ); + GlobalCommands_insert( "GroupSelection", makeCallbackF(Entity_groupSelected) ); + GlobalCommands_insert( "UngroupSelection", makeCallbackF(Entity_ungroupSelected) ); - GlobalPreferenceSystem().registerPreference("SI_Colors5", make_property_string(g_entity_globals.color_entity)); - GlobalPreferenceSystem().registerPreference("LastLightIntensity", make_property_string(g_iLastLightIntensity)); + GlobalPreferenceSystem().registerPreference( "SI_Colors5", make_property_string( g_entity_globals.color_entity ) ); + GlobalPreferenceSystem().registerPreference( "LastLightIntensity", make_property_string( g_iLastLightIntensity ) ); - Entity_registerPreferencesPage(); + Entity_registerPreferencesPage(); } -void Entity_Destroy() -{ +void Entity_Destroy(){ } diff --git a/radiant/environment.cpp b/radiant/environment.cpp index 60100cec..484258d7 100644 --- a/radiant/environment.cpp +++ b/radiant/environment.cpp @@ -31,163 +31,160 @@ #include "cmdlib.h" int g_argc; -char const **g_argv; - -void args_init(int argc, char const *argv[]) -{ - int i, j, k; - - for (i = 1; i < argc; i++) { - for (k = i; k < argc; k++) { - if (argv[k] != 0) { - break; - } - } - - if (k > i) { - k -= i; - for (j = i + k; j < argc; j++) { - argv[j - k] = argv[j]; - } - argc -= k; - } - } - - g_argc = argc; - g_argv = argv; +char const** g_argv; + +void args_init( int argc, char const* argv[] ){ + int i, j, k; + + for ( i = 1; i < argc; i++ ) + { + for ( k = i; k < argc; k++ ) + { + if ( argv[k] != 0 ) { + break; + } + } + + if ( k > i ) { + k -= i; + for ( j = i + k; j < argc; j++ ) + { + argv[j - k] = argv[j]; + } + argc -= k; + } + } + + g_argc = argc; + g_argv = argv; } char const *gamedetect_argv_buffer[1024]; -void gamedetect_found_game(char const *game, char *path) -{ - int argc; - static char buf[128]; - - if (g_argv == gamedetect_argv_buffer) { - return; - } - - globalOutputStream() << "Detected game " << game << " in " << path << "\n"; - - sprintf(buf, "-%s-EnginePath", game); - argc = 0; - gamedetect_argv_buffer[argc++] = "-global-gamefile"; - gamedetect_argv_buffer[argc++] = game; - gamedetect_argv_buffer[argc++] = buf; - gamedetect_argv_buffer[argc++] = path; - if ((size_t) (argc + g_argc) >= sizeof(gamedetect_argv_buffer) / sizeof(*gamedetect_argv_buffer) - 1) { - g_argc = sizeof(gamedetect_argv_buffer) / sizeof(*gamedetect_argv_buffer) - g_argc - 1; - } - memcpy(gamedetect_argv_buffer + 4, g_argv, sizeof(*gamedetect_argv_buffer) * g_argc); - g_argc += argc; - g_argv = gamedetect_argv_buffer; +void gamedetect_found_game( char const *game, char *path ){ + int argc; + static char buf[128]; + + if ( g_argv == gamedetect_argv_buffer ) { + return; + } + + globalOutputStream() << "Detected game " << game << " in " << path << "\n"; + + sprintf( buf, "-%s-EnginePath", game ); + argc = 0; + gamedetect_argv_buffer[argc++] = "-global-gamefile"; + gamedetect_argv_buffer[argc++] = game; + gamedetect_argv_buffer[argc++] = buf; + gamedetect_argv_buffer[argc++] = path; + if ( (size_t) ( argc + g_argc ) >= sizeof( gamedetect_argv_buffer ) / sizeof( *gamedetect_argv_buffer ) - 1 ) { + g_argc = sizeof( gamedetect_argv_buffer ) / sizeof( *gamedetect_argv_buffer ) - g_argc - 1; + } + memcpy( gamedetect_argv_buffer + 4, g_argv, sizeof( *gamedetect_argv_buffer ) * g_argc ); + g_argc += argc; + g_argv = gamedetect_argv_buffer; } -bool gamedetect_check_game(char const *gamefile, const char *checkfile1, const char *checkfile2, - char *buf /* must have 64 bytes free after bufpos */, int bufpos) -{ - buf[bufpos] = '/'; - - strcpy(buf + bufpos + 1, checkfile1); - globalOutputStream() << "Checking for a game file in " << buf << "\n"; - if (!file_exists(buf)) { - return false; - } - - if (checkfile2) { - strcpy(buf + bufpos + 1, checkfile2); - globalOutputStream() << "Checking for a game file in " << buf << "\n"; - if (!file_exists(buf)) { - return false; - } - } - - buf[bufpos + 1] = 0; - gamedetect_found_game(gamefile, buf); - return true; +bool gamedetect_check_game( char const *gamefile, const char *checkfile1, const char *checkfile2, char *buf /* must have 64 bytes free after bufpos */, int bufpos ){ + buf[bufpos] = '/'; + + strcpy( buf + bufpos + 1, checkfile1 ); + globalOutputStream() << "Checking for a game file in " << buf << "\n"; + if ( !file_exists( buf ) ) { + return false; + } + + if ( checkfile2 ) { + strcpy( buf + bufpos + 1, checkfile2 ); + globalOutputStream() << "Checking for a game file in " << buf << "\n"; + if ( !file_exists( buf ) ) { + return false; + } + } + + buf[bufpos + 1] = 0; + gamedetect_found_game( gamefile, buf ); + return true; } -void gamedetect() -{ - // if we're inside a Nexuiz install - // default to nexuiz.game (unless the user used an option to inhibit this) - bool nogamedetect = false; - int i; - for (i = 1; i < g_argc - 1; ++i) { - if (g_argv[i][0] == '-') { - if (!strcmp(g_argv[i], "-gamedetect")) { - nogamedetect = !strcmp(g_argv[i + 1], "false"); - } - ++i; - } - } - if (!nogamedetect) { - static char buf[1024 + 64]; - strncpy(buf, environment_get_app_path(), sizeof(buf)); - buf[sizeof(buf) - 1 - 64] = 0; - if (!strlen(buf)) { - return; - } - - char *p = buf + strlen(buf) - 1; // point directly on the slash of get_app_path - while (p != buf) { - // TODO add more games to this - - // try to detect Nexuiz installs +void gamedetect(){ + // if we're inside a Nexuiz install + // default to nexuiz.game (unless the user used an option to inhibit this) + bool nogamedetect = false; + int i; + for ( i = 1; i < g_argc - 1; ++i ) + { + if ( g_argv[i][0] == '-' ) { + if ( !strcmp( g_argv[i], "-gamedetect" ) ) { + nogamedetect = !strcmp( g_argv[i + 1], "false" ); + } + ++i; + } + } + if ( !nogamedetect ) { + static char buf[1024 + 64]; + strncpy( buf, environment_get_app_path(), sizeof( buf ) ); + buf[sizeof( buf ) - 1 - 64] = 0; + if ( !strlen( buf ) ) { + return; + } + + char *p = buf + strlen( buf ) - 1; // point directly on the slash of get_app_path + while ( p != buf ) + { + // TODO add more games to this + + // try to detect Nexuiz installs #if GDEF_OS_WINDOWS - if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "nexuiz.exe", buf, p - buf ) ) + if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "nexuiz.exe", buf, p - buf ) ) #elif GDEF_OS_MACOS - if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "Nexuiz.app/Contents/Info.plist", buf, p - buf ) ) + if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "Nexuiz.app/Contents/Info.plist", buf, p - buf ) ) #else - if (gamedetect_check_game("nexuiz.game", "data/common-spog.pk3", "nexuiz-linux-glx.sh", buf, p - buf)) + if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "nexuiz-linux-glx.sh", buf, p - buf ) ) #endif - { return; } - - // try to detect Quetoo installs - if (gamedetect_check_game("quetoo.game", "default/icons/quetoo.png", NULL, buf, p - buf)) { - return; - } - - // try to detect Warsow installs - if (gamedetect_check_game("warsow.game", "basewsw/dedicated_autoexec.cfg", NULL, buf, p - buf)) { - return; - } - - // we found nothing - // go backwards - --p; - while (p != buf && *p != '/' && *p != '\\') { - --p; - } - } - } + { return; } + + // try to detect Quetoo installs + if ( gamedetect_check_game( "quetoo.game", "default/icons/quetoo.png", NULL, buf, p - buf ) ) { + return; + } + + // try to detect Warsow installs + if ( gamedetect_check_game( "warsow.game", "basewsw/dedicated_autoexec.cfg", NULL, buf, p - buf ) ) { + return; + } + + // we found nothing + // go backwards + --p; + while ( p != buf && *p != '/' && *p != '\\' ) + --p; + } + } } -namespace { - CopiedString home_path; - CopiedString app_path; +namespace +{ +CopiedString home_path; +CopiedString app_path; } -const char *environment_get_home_path() -{ - return home_path.c_str(); +const char* environment_get_home_path(){ + return home_path.c_str(); } -const char *environment_get_app_path() -{ - return app_path.c_str(); +const char* environment_get_app_path(){ + return app_path.c_str(); } -bool portable_app_setup() -{ - StringOutputStream confdir(256); - confdir << app_path.c_str() << "settings/"; - if (file_exists(confdir.c_str())) { - home_path = confdir.c_str(); - return true; - } - return false; +bool portable_app_setup(){ + StringOutputStream confdir( 256 ); + confdir << app_path.c_str() << "settings/"; + if ( file_exists( confdir.c_str() ) ) { + home_path = confdir.c_str(); + return true; + } + return false; } #if GDEF_OS_POSIX @@ -198,71 +195,69 @@ bool portable_app_setup() #include -const char *LINK_NAME = +const char* LINK_NAME = #if GDEF_OS_LINUX - "/proc/self/exe" + "/proc/self/exe" #else // FreeBSD and OSX -"/proc/curproc/file" + "/proc/curproc/file" #endif ; /// brief Returns the filename of the executable belonging to the current process, or 0 if not found. -char const *getexename(char *buf) -{ - /* Now read the symbolic link */ - int ret = readlink(LINK_NAME, buf, PATH_MAX); - - if (ret == -1) { - globalOutputStream() << "getexename: falling back to argv[0]: " << makeQuoted(g_argv[0]); - const char *path = realpath(g_argv[0], buf); - if (path == 0) { - /* In case of an error, leave the handling up to the caller */ - return ""; - } - } - - /* Ensure proper NUL termination */ - buf[ret] = 0; - - /* delete the program name */ - *(strrchr(buf, '/')) = '\0'; - - // NOTE: we build app path with a trailing '/' - // it's a general convention in Radiant to have the slash at the end of directories - if (buf[strlen(buf) - 1] != '/') { - strcat(buf, "/"); - } - - return buf; +char const* getexename( char *buf ){ + /* Now read the symbolic link */ + int ret = readlink( LINK_NAME, buf, PATH_MAX ); + + if ( ret == -1 ) { + globalOutputStream() << "getexename: falling back to argv[0]: " << makeQuoted( g_argv[0] ); + const char* path = realpath( g_argv[0], buf ); + if ( path == 0 ) { + /* In case of an error, leave the handling up to the caller */ + return ""; + } + } + + /* Ensure proper NUL termination */ + buf[ret] = 0; + + /* delete the program name */ + *( strrchr( buf, '/' ) ) = '\0'; + + // NOTE: we build app path with a trailing '/' + // it's a general convention in Radiant to have the slash at the end of directories + if ( buf[strlen( buf ) - 1] != '/' ) { + strcat( buf, "/" ); + } + + return buf; } -void environment_init(int argc, char const *argv[]) -{ - // Give away unnecessary root privileges. - // Important: must be done before calling gtk_init(). - char *loginname; - struct passwd *pw; - seteuid(getuid()); - if (geteuid() == 0 && (loginname = getlogin()) != 0 && - (pw = getpwnam(loginname)) != 0) { - setuid(pw->pw_uid); - } - - args_init(argc, argv); - - { - char real[PATH_MAX]; - app_path = getexename(real); - ASSERT_MESSAGE(!string_empty(app_path.c_str()), "failed to deduce app path"); - } - - if (!portable_app_setup()) { - StringOutputStream home(256); - home << DirectoryCleaned(g_get_user_config_dir()) << "netradiant/"; - Q_mkdir(home.c_str()); - home_path = home.c_str(); - } - gamedetect(); +void environment_init( int argc, char const* argv[] ){ + // Give away unnecessary root privileges. + // Important: must be done before calling gtk_init(). + char *loginname; + struct passwd *pw; + seteuid( getuid() ); + if ( geteuid() == 0 && ( loginname = getlogin() ) != 0 && + ( pw = getpwnam( loginname ) ) != 0 ) { + setuid( pw->pw_uid ); + } + + args_init( argc, argv ); + + { + char real[PATH_MAX]; + app_path = getexename( real ); + ASSERT_MESSAGE( !string_empty( app_path.c_str() ), "failed to deduce app path" ); + } + + if ( !portable_app_setup() ) { + StringOutputStream home( 256 ); + home << DirectoryCleaned( g_get_user_config_dir() ) << "netradiant/"; + Q_mkdir( home.c_str() ); + home_path = home.c_str(); + } + gamedetect(); } #elif GDEF_OS_WINDOWS @@ -270,34 +265,34 @@ void environment_init(int argc, char const *argv[]) #include void environment_init( int argc, char const* argv[] ){ - args_init( argc, argv ); - - { - // get path to the editor - char filename[MAX_PATH + 1]; - GetModuleFileName( 0, filename, MAX_PATH ); - char* last_separator = strrchr( filename, '\\' ); - if ( last_separator != 0 ) { - *( last_separator + 1 ) = '\0'; - } - else - { - filename[0] = '\0'; - } - StringOutputStream app( 256 ); - app << PathCleaned( filename ); - app_path = app.c_str(); - } - - if ( !portable_app_setup() ) { - char *appdata = getenv( "APPDATA" ); - StringOutputStream home( 256 ); - home << PathCleaned( appdata ); - home << "/NetRadiantSettings/"; - Q_mkdir( home.c_str() ); - home_path = home.c_str(); - } - gamedetect(); + args_init( argc, argv ); + + { + // get path to the editor + char filename[MAX_PATH + 1]; + GetModuleFileName( 0, filename, MAX_PATH ); + char* last_separator = strrchr( filename, '\\' ); + if ( last_separator != 0 ) { + *( last_separator + 1 ) = '\0'; + } + else + { + filename[0] = '\0'; + } + StringOutputStream app( 256 ); + app << PathCleaned( filename ); + app_path = app.c_str(); + } + + if ( !portable_app_setup() ) { + char *appdata = getenv( "APPDATA" ); + StringOutputStream home( 256 ); + home << PathCleaned( appdata ); + home << "/NetRadiantSettings/"; + Q_mkdir( home.c_str() ); + home_path = home.c_str(); + } + gamedetect(); } #else diff --git a/radiant/mainframe.cpp b/radiant/mainframe.cpp index 11fc3784..49681238 100644 --- a/radiant/mainframe.cpp +++ b/radiant/mainframe.cpp @@ -102,26 +102,26 @@ #include "texwindow.h" -struct layout_globals_t { - WindowPosition m_position; - - - int nXYHeight; - int nXYWidth; - int nCamWidth; - int nCamHeight; - int nState; - - layout_globals_t() : - m_position(-1, -1, 640, 480), - - nXYHeight(300), - nXYWidth(300), - nCamWidth(200), - nCamHeight(200), - nState(GDK_WINDOW_STATE_MAXIMIZED) - { - } +struct layout_globals_t +{ + WindowPosition m_position; + + + int nXYHeight; + int nXYWidth; + int nCamWidth; + int nCamHeight; + int nState; + + layout_globals_t() : + m_position( -1, -1, 640, 480 ), + + nXYHeight( 300 ), + nXYWidth( 300 ), + nCamWidth( 200 ), + nCamHeight( 200 ), + nState( GDK_WINDOW_STATE_MAXIMIZED ){ + } }; layout_globals_t g_layout_globals; @@ -132,69 +132,62 @@ glwindow_globals_t g_glwindow_globals; bool g_vfsInitialized = false; -void VFS_Init() -{ - if (g_vfsInitialized) { return; } - QE_InitVFS(); - GlobalFileSystem().initialise(); - g_vfsInitialized = true; +void VFS_Init(){ + if ( g_vfsInitialized ) return; + QE_InitVFS(); + GlobalFileSystem().initialise(); + g_vfsInitialized = true; } -void VFS_Shutdown() -{ - if (!g_vfsInitialized) { return; } - GlobalFileSystem().shutdown(); - g_vfsInitialized = false; +void VFS_Shutdown(){ + if ( !g_vfsInitialized ) return; + GlobalFileSystem().shutdown(); + g_vfsInitialized = false; } -void VFS_Refresh() -{ - if (!g_vfsInitialized) { return; } - GlobalFileSystem().clear(); - QE_InitVFS(); - GlobalFileSystem().refresh(); - g_vfsInitialized = true; - // also refresh models - RefreshReferences(); - // also refresh texture browser - TextureBrowser_RefreshShaders(); -} - -void VFS_Restart() -{ - VFS_Shutdown(); - VFS_Init(); +void VFS_Refresh(){ + if ( !g_vfsInitialized ) return; + GlobalFileSystem().clear(); + QE_InitVFS(); + GlobalFileSystem().refresh(); + g_vfsInitialized = true; + // also refresh models + RefreshReferences(); + // also refresh texture browser + TextureBrowser_RefreshShaders(); } -class VFSModuleObserver : public ModuleObserver { +void VFS_Restart(){ + VFS_Shutdown(); + VFS_Init(); +} + +class VFSModuleObserver : public ModuleObserver +{ public: - void realise() - { - VFS_Init(); - } - - void unrealise() - { - VFS_Shutdown(); - } +void realise(){ + VFS_Init(); +} + +void unrealise(){ + VFS_Shutdown(); +} }; VFSModuleObserver g_VFSModuleObserver; -void VFS_Construct() -{ - Radiant_attachHomePathsObserver(g_VFSModuleObserver); +void VFS_Construct(){ + Radiant_attachHomePathsObserver( g_VFSModuleObserver ); } -void VFS_Destroy() -{ - Radiant_detachHomePathsObserver(g_VFSModuleObserver); +void VFS_Destroy(){ + Radiant_detachHomePathsObserver( g_VFSModuleObserver ); } // Home Paths #if GDEF_OS_WINDOWS - #include + #include #include const GUID qFOLDERID_SavedGames = {0x4C5C32FF, 0xBB9D, 0x43b0, {0xB5, 0xB4, 0x2D, 0x72, 0xE5, 0x4E, 0xAA, 0xA4}}; #define qREFKNOWNFOLDERID GUID @@ -204,15 +197,15 @@ typedef HRESULT ( WINAPI qSHGetKnownFolderPath_t )( qREFKNOWNFOLDERID rfid, DWOR static qSHGetKnownFolderPath_t *qSHGetKnownFolderPath; #endif -void HomePaths_Realise() -{ - do { - const char *prefix = g_pGameDescription->getKeyValue("prefix"); - if (!string_empty(prefix)) { - StringOutputStream path(256); +void HomePaths_Realise(){ + do + { + const char* prefix = g_pGameDescription->getKeyValue( "prefix" ); + if ( !string_empty( prefix ) ) { + StringOutputStream path( 256 ); #if GDEF_OS_MACOS - path.clear(); + path.clear(); path << DirectoryCleaned( g_get_home_dir() ) << "Library/Application Support" << ( prefix + 1 ) << "/"; if ( file_is_directory( path.c_str() ) ) { g_qeglobals.m_userEnginePath = path.c_str(); @@ -223,7 +216,7 @@ void HomePaths_Realise() #endif #if GDEF_OS_WINDOWS - TCHAR mydocsdir[MAX_PATH + 1]; + TCHAR mydocsdir[MAX_PATH + 1]; wchar_t *mydocsdirw; HMODULE shfolder = LoadLibrary( "shfolder.dll" ); if ( shfolder ) { @@ -262,72 +255,67 @@ void HomePaths_Realise() #endif #if GDEF_OS_POSIX - path.clear(); - path << DirectoryCleaned(g_get_home_dir()) << prefix << "/"; - g_qeglobals.m_userEnginePath = path.c_str(); - break; + path.clear(); + path << DirectoryCleaned( g_get_home_dir() ) << prefix << "/"; + g_qeglobals.m_userEnginePath = path.c_str(); + break; #endif - } + } - g_qeglobals.m_userEnginePath = EnginePath_get(); - } while (0); + g_qeglobals.m_userEnginePath = EnginePath_get(); + } + while ( 0 ); - Q_mkdir(g_qeglobals.m_userEnginePath.c_str()); + Q_mkdir( g_qeglobals.m_userEnginePath.c_str() ); - { - StringOutputStream path(256); - path << g_qeglobals.m_userEnginePath.c_str() << gamename_get() << '/'; - g_qeglobals.m_userGamePath = path.c_str(); - } - ASSERT_MESSAGE(!string_empty(g_qeglobals.m_userGamePath.c_str()), "HomePaths_Realise: user-game-path is empty"); - Q_mkdir(g_qeglobals.m_userGamePath.c_str()); + { + StringOutputStream path( 256 ); + path << g_qeglobals.m_userEnginePath.c_str() << gamename_get() << '/'; + g_qeglobals.m_userGamePath = path.c_str(); + } + ASSERT_MESSAGE( !string_empty( g_qeglobals.m_userGamePath.c_str() ), "HomePaths_Realise: user-game-path is empty" ); + Q_mkdir( g_qeglobals.m_userGamePath.c_str() ); } ModuleObservers g_homePathObservers; -void Radiant_attachHomePathsObserver(ModuleObserver &observer) -{ - g_homePathObservers.attach(observer); +void Radiant_attachHomePathsObserver( ModuleObserver& observer ){ + g_homePathObservers.attach( observer ); } -void Radiant_detachHomePathsObserver(ModuleObserver &observer) -{ - g_homePathObservers.detach(observer); +void Radiant_detachHomePathsObserver( ModuleObserver& observer ){ + g_homePathObservers.detach( observer ); } -class HomePathsModuleObserver : public ModuleObserver { - std::size_t m_unrealised; +class HomePathsModuleObserver : public ModuleObserver +{ +std::size_t m_unrealised; public: - HomePathsModuleObserver() : m_unrealised(1) - { - } - - void realise() - { - if (--m_unrealised == 0) { - HomePaths_Realise(); - g_homePathObservers.realise(); - } - } - - void unrealise() - { - if (++m_unrealised == 1) { - g_homePathObservers.unrealise(); - } - } +HomePathsModuleObserver() : m_unrealised( 1 ){ +} + +void realise(){ + if ( --m_unrealised == 0 ) { + HomePaths_Realise(); + g_homePathObservers.realise(); + } +} + +void unrealise(){ + if ( ++m_unrealised == 1 ) { + g_homePathObservers.unrealise(); + } +} }; HomePathsModuleObserver g_HomePathsModuleObserver; -void HomePaths_Construct() -{ - Radiant_attachEnginePathObserver(g_HomePathsModuleObserver); +void HomePaths_Construct(){ + Radiant_attachEnginePathObserver( g_HomePathsModuleObserver ); } -void HomePaths_Destroy() -{ - Radiant_detachEnginePathObserver(g_HomePathsModuleObserver); +void HomePaths_Destroy(){ + Radiant_detachEnginePathObserver( g_HomePathsModuleObserver ); } @@ -337,45 +325,39 @@ CopiedString g_strEnginePath; ModuleObservers g_enginePathObservers; std::size_t g_enginepath_unrealised = 1; -void Radiant_attachEnginePathObserver(ModuleObserver &observer) -{ - g_enginePathObservers.attach(observer); +void Radiant_attachEnginePathObserver( ModuleObserver& observer ){ + g_enginePathObservers.attach( observer ); } -void Radiant_detachEnginePathObserver(ModuleObserver &observer) -{ - g_enginePathObservers.detach(observer); +void Radiant_detachEnginePathObserver( ModuleObserver& observer ){ + g_enginePathObservers.detach( observer ); } -void EnginePath_Realise() -{ - if (--g_enginepath_unrealised == 0) { - g_enginePathObservers.realise(); - } +void EnginePath_Realise(){ + if ( --g_enginepath_unrealised == 0 ) { + g_enginePathObservers.realise(); + } } -const char *EnginePath_get() -{ - ASSERT_MESSAGE(g_enginepath_unrealised == 0, "EnginePath_get: engine path not realised"); - return g_strEnginePath.c_str(); +const char* EnginePath_get(){ + ASSERT_MESSAGE( g_enginepath_unrealised == 0, "EnginePath_get: engine path not realised" ); + return g_strEnginePath.c_str(); } -void EnginePath_Unrealise() -{ - if (++g_enginepath_unrealised == 1) { - g_enginePathObservers.unrealise(); - } +void EnginePath_Unrealise(){ + if ( ++g_enginepath_unrealised == 1 ) { + g_enginePathObservers.unrealise(); + } } -void setEnginePath(const char *path) -{ - StringOutputStream buffer(256); - buffer << DirectoryCleaned(path); - if (!path_equal(buffer.c_str(), g_strEnginePath.c_str())) { +void setEnginePath( const char* path ){ + StringOutputStream buffer( 256 ); + buffer << DirectoryCleaned( path ); + if ( !path_equal( buffer.c_str(), g_strEnginePath.c_str() ) ) { #if 0 - while ( !ConfirmModified( "Paths Changed" ) ) + while ( !ConfirmModified( "Paths Changed" ) ) { if ( Map_Unnamed( g_map ) ) { Map_SaveAs(); @@ -388,73 +370,67 @@ void setEnginePath(const char *path) Map_RegionOff(); #endif - ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Changing Engine Path"); + ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Changing Engine Path" ); - EnginePath_Unrealise(); + EnginePath_Unrealise(); - g_strEnginePath = buffer.c_str(); + g_strEnginePath = buffer.c_str(); - EnginePath_Realise(); - } + EnginePath_Realise(); + } } // Pak Path -CopiedString g_strPakPath[g_pakPathCount] = {"", "", "", "", ""}; +CopiedString g_strPakPath[g_pakPathCount] = { "", "", "", "", "" }; ModuleObservers g_pakPathObservers[g_pakPathCount]; -std::size_t g_pakpath_unrealised[g_pakPathCount] = {1, 1, 1, 1, 1}; +std::size_t g_pakpath_unrealised[g_pakPathCount] = { 1, 1, 1, 1, 1 }; -void Radiant_attachPakPathObserver(int num, ModuleObserver &observer) -{ - g_pakPathObservers[num].attach(observer); +void Radiant_attachPakPathObserver( int num, ModuleObserver& observer ){ + g_pakPathObservers[num].attach( observer ); } -void Radiant_detachPakPathObserver(int num, ModuleObserver &observer) -{ - g_pakPathObservers[num].detach(observer); +void Radiant_detachPakPathObserver( int num, ModuleObserver& observer ){ + g_pakPathObservers[num].detach( observer ); } -void PakPath_Realise(int num) -{ - if (--g_pakpath_unrealised[num] == 0) { - g_pakPathObservers[num].realise(); - } +void PakPath_Realise( int num ){ + if ( --g_pakpath_unrealised[num] == 0 ) { + g_pakPathObservers[num].realise(); + } } -const char *PakPath_get(int num) -{ - std::string message = "PakPath_get: pak path " + std::to_string(num) + " not realised"; - ASSERT_MESSAGE(g_pakpath_unrealised[num] == 0, message.c_str()); - return g_strPakPath[num].c_str(); +const char* PakPath_get( int num ){ + std::string message = "PakPath_get: pak path " + std::to_string(num) + " not realised"; + ASSERT_MESSAGE( g_pakpath_unrealised[num] == 0, message.c_str() ); + return g_strPakPath[num].c_str(); } -void PakPath_Unrealise(int num) -{ - if (++g_pakpath_unrealised[num] == 1) { - g_pakPathObservers[num].unrealise(); - } +void PakPath_Unrealise( int num ){ + if ( ++g_pakpath_unrealised[num] == 1 ) { + g_pakPathObservers[num].unrealise(); + } } -void setPakPath(int num, const char *path) -{ - if (!g_strcmp0(path, "")) { - g_strPakPath[num] = ""; - return; - } +void setPakPath( int num, const char* path ){ + if (!g_strcmp0( path, "")) { + g_strPakPath[num] = ""; + return; + } - StringOutputStream buffer(256); - buffer << DirectoryCleaned(path); - if (!path_equal(buffer.c_str(), g_strPakPath[num].c_str())) { - std::string message = "Changing Pak Path " + std::to_string(num); - ScopeDisableScreenUpdates disableScreenUpdates("Processing...", message.c_str()); + StringOutputStream buffer( 256 ); + buffer << DirectoryCleaned( path ); + if ( !path_equal( buffer.c_str(), g_strPakPath[num].c_str() ) ) { + std::string message = "Changing Pak Path " + std::to_string(num); + ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", message.c_str() ); - PakPath_Unrealise(num); + PakPath_Unrealise(num); - g_strPakPath[num] = buffer.c_str(); + g_strPakPath[num] = buffer.c_str(); - PakPath_Realise(num); - } + PakPath_Realise(num); + } } @@ -462,30 +438,27 @@ void setPakPath(int num, const char *path) CopiedString g_strAppPath; ///< holds the full path of the executable -const char *AppPath_get() -{ - return g_strAppPath.c_str(); +const char* AppPath_get(){ + return g_strAppPath.c_str(); } /// the path to the local rc-dir -const char *LocalRcPath_get(void) -{ - static CopiedString rc_path; - if (rc_path.empty()) { - StringOutputStream stream(256); - stream << GlobalRadiant().getSettingsPath() << g_pGameDescription->mGameFile.c_str() << "/"; - rc_path = stream.c_str(); - } - return rc_path.c_str(); +const char* LocalRcPath_get( void ){ + static CopiedString rc_path; + if ( rc_path.empty() ) { + StringOutputStream stream( 256 ); + stream << GlobalRadiant().getSettingsPath() << g_pGameDescription->mGameFile.c_str() << "/"; + rc_path = stream.c_str(); + } + return rc_path.c_str(); } /// directory for temp files /// NOTE: on *nix this is were we check for .pid CopiedString g_strSettingsPath; -const char *SettingsPath_get() -{ - return g_strSettingsPath.c_str(); +const char* SettingsPath_get(){ + return g_strSettingsPath.c_str(); } @@ -500,235 +473,210 @@ const char *SettingsPath_get() */ CopiedString g_strGameToolsPath; ///< this is set by g_GamesDialog -const char *GameToolsPath_get() -{ - return g_strGameToolsPath.c_str(); +const char* GameToolsPath_get(){ + return g_strGameToolsPath.c_str(); } struct EnginePath { - static void Export(const CopiedString &self, const Callback &returnz) - { - returnz(self.c_str()); - } - - static void Import(CopiedString &self, const char *value) - { - setEnginePath(value); - } + static void Export(const CopiedString &self, const Callback &returnz) { + returnz(self.c_str()); + } + + static void Import(CopiedString &self, const char *value) { + setEnginePath( value ); +} }; struct PakPath0 { - static void Export(const CopiedString &self, const Callback &returnz) - { - returnz(self.c_str()); - } - - static void Import(CopiedString &self, const char *value) - { - setPakPath(0, value); - } + static void Export( const CopiedString &self, const Callback &returnz ) { + returnz( self.c_str() ); + } + + static void Import( CopiedString &self, const char *value ) { + setPakPath( 0, value ); + } }; struct PakPath1 { - static void Export(const CopiedString &self, const Callback &returnz) - { - returnz(self.c_str()); - } - - static void Import(CopiedString &self, const char *value) - { - setPakPath(1, value); - } + static void Export( const CopiedString &self, const Callback &returnz ) { + returnz( self.c_str() ); + } + + static void Import( CopiedString &self, const char *value ) { + setPakPath( 1, value ); + } }; struct PakPath2 { - static void Export(const CopiedString &self, const Callback &returnz) - { - returnz(self.c_str()); - } - - static void Import(CopiedString &self, const char *value) - { - setPakPath(2, value); - } + static void Export( const CopiedString &self, const Callback &returnz ) { + returnz( self.c_str() ); + } + + static void Import( CopiedString &self, const char *value ) { + setPakPath( 2, value ); + } }; struct PakPath3 { - static void Export(const CopiedString &self, const Callback &returnz) - { - returnz(self.c_str()); - } - - static void Import(CopiedString &self, const char *value) - { - setPakPath(3, value); - } + static void Export( const CopiedString &self, const Callback &returnz ) { + returnz( self.c_str() ); + } + + static void Import( CopiedString &self, const char *value ) { + setPakPath( 3, value ); + } }; struct PakPath4 { - static void Export(const CopiedString &self, const Callback &returnz) - { - returnz(self.c_str()); - } - - static void Import(CopiedString &self, const char *value) - { - setPakPath(4, value); - } + static void Export( const CopiedString &self, const Callback &returnz ) { + returnz( self.c_str() ); + } + + static void Import( CopiedString &self, const char *value ) { + setPakPath( 4, value ); + } }; bool g_disableEnginePath = false; bool g_disableHomePath = false; -void Paths_constructPreferences(PreferencesPage &page) -{ - page.appendPathEntry("Engine Path", true, make_property(g_strEnginePath)); - - page.appendCheckBox( - "", "Do not use Engine Path", - g_disableEnginePath - ); - - page.appendCheckBox( - "", "Do not use Home Path", - g_disableHomePath - ); - - for (int i = 0; i < g_pakPathCount; i++) { - std::string label = "Pak Path " + std::to_string(i); - switch (i) { - case 0: - page.appendPathEntry(label.c_str(), true, make_property(g_strPakPath[i])); - break; - case 1: - page.appendPathEntry(label.c_str(), true, make_property(g_strPakPath[i])); - break; - case 2: - page.appendPathEntry(label.c_str(), true, make_property(g_strPakPath[i])); - break; - case 3: - page.appendPathEntry(label.c_str(), true, make_property(g_strPakPath[i])); - break; - case 4: - page.appendPathEntry(label.c_str(), true, make_property(g_strPakPath[i])); - break; - } - } -} - -void Paths_constructPage(PreferenceGroup &group) -{ - PreferencesPage page(group.createPage("Paths", "Path Settings")); - Paths_constructPreferences(page); +void Paths_constructPreferences( PreferencesPage& page ){ + page.appendPathEntry( "Engine Path", true, make_property(g_strEnginePath) ); + + page.appendCheckBox( + "", "Do not use Engine Path", + g_disableEnginePath + ); + + page.appendCheckBox( + "", "Do not use Home Path", + g_disableHomePath + ); + + for ( int i = 0; i < g_pakPathCount; i++ ) { + std::string label = "Pak Path " + std::to_string(i); + switch (i) { + case 0: + page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); + break; + case 1: + page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); + break; + case 2: + page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); + break; + case 3: + page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); + break; + case 4: + page.appendPathEntry( label.c_str(), true, make_property( g_strPakPath[i] ) ); + break; + } + } } -void Paths_registerPreferencesPage() -{ - PreferencesDialog_addSettingsPage(makeCallbackF(Paths_constructPage)); +void Paths_constructPage( PreferenceGroup& group ){ + PreferencesPage page( group.createPage( "Paths", "Path Settings" ) ); + Paths_constructPreferences( page ); +} + +void Paths_registerPreferencesPage(){ + PreferencesDialog_addSettingsPage( makeCallbackF(Paths_constructPage) ); } -class PathsDialog : public Dialog { +class PathsDialog : public Dialog +{ public: - ui::Window BuildDialog() - { - auto frame = create_dialog_frame("Path settings", ui::Shadow::ETCHED_IN); +ui::Window BuildDialog(){ + auto frame = create_dialog_frame( "Path settings", ui::Shadow::ETCHED_IN ); - auto vbox2 = create_dialog_vbox(0, 4); - frame.add(vbox2); + auto vbox2 = create_dialog_vbox( 0, 4 ); + frame.add(vbox2); - { - PreferencesPage preferencesPage(*this, vbox2); - Paths_constructPreferences(preferencesPage); - } + { + PreferencesPage preferencesPage( *this, vbox2 ); + Paths_constructPreferences( preferencesPage ); + } - return ui::Window(create_simple_modal_dialog_window("Engine Path Not Found", m_modal, frame)); - } + return ui::Window(create_simple_modal_dialog_window( "Engine Path Not Found", m_modal, frame )); +} }; PathsDialog g_PathsDialog; -void EnginePath_verify() -{ - if (!file_exists(g_strEnginePath.c_str())) { - g_PathsDialog.Create(); - g_PathsDialog.DoModal(); - g_PathsDialog.Destroy(); - } +void EnginePath_verify(){ + if ( !file_exists( g_strEnginePath.c_str() ) ) { + g_PathsDialog.Create(); + g_PathsDialog.DoModal(); + g_PathsDialog.Destroy(); + } } -namespace { - CopiedString g_gamename; - CopiedString g_gamemode; - ModuleObservers g_gameNameObservers; - ModuleObservers g_gameModeObservers; +namespace +{ +CopiedString g_gamename; +CopiedString g_gamemode; +ModuleObservers g_gameNameObservers; +ModuleObservers g_gameModeObservers; } -void Radiant_attachGameNameObserver(ModuleObserver &observer) -{ - g_gameNameObservers.attach(observer); +void Radiant_attachGameNameObserver( ModuleObserver& observer ){ + g_gameNameObservers.attach( observer ); } -void Radiant_detachGameNameObserver(ModuleObserver &observer) -{ - g_gameNameObservers.detach(observer); +void Radiant_detachGameNameObserver( ModuleObserver& observer ){ + g_gameNameObservers.detach( observer ); } -const char *basegame_get() -{ - return g_pGameDescription->getRequiredKeyValue("basegame"); +const char* basegame_get(){ + return g_pGameDescription->getRequiredKeyValue( "basegame" ); } -const char *gamename_get() -{ - const char *gamename = g_gamename.c_str(); - if (string_empty(gamename)) { - return basegame_get(); - } - return gamename; +const char* gamename_get(){ + const char* gamename = g_gamename.c_str(); + if ( string_empty( gamename ) ) { + return basegame_get(); + } + return gamename; } -void gamename_set(const char *gamename) -{ - if (!string_equal(gamename, g_gamename.c_str())) { - g_gameNameObservers.unrealise(); - g_gamename = gamename; - g_gameNameObservers.realise(); - } +void gamename_set( const char* gamename ){ + if ( !string_equal( gamename, g_gamename.c_str() ) ) { + g_gameNameObservers.unrealise(); + g_gamename = gamename; + g_gameNameObservers.realise(); + } } -void Radiant_attachGameModeObserver(ModuleObserver &observer) -{ - g_gameModeObservers.attach(observer); +void Radiant_attachGameModeObserver( ModuleObserver& observer ){ + g_gameModeObservers.attach( observer ); } -void Radiant_detachGameModeObserver(ModuleObserver &observer) -{ - g_gameModeObservers.detach(observer); +void Radiant_detachGameModeObserver( ModuleObserver& observer ){ + g_gameModeObservers.detach( observer ); } -const char *gamemode_get() -{ - return g_gamemode.c_str(); +const char* gamemode_get(){ + return g_gamemode.c_str(); } -void gamemode_set(const char *gamemode) -{ - if (!string_equal(gamemode, g_gamemode.c_str())) { - g_gameModeObservers.unrealise(); - g_gamemode = gamemode; - g_gameModeObservers.realise(); - } +void gamemode_set( const char* gamemode ){ + if ( !string_equal( gamemode, g_gamemode.c_str() ) ) { + g_gameModeObservers.unrealise(); + g_gamemode = gamemode; + g_gameModeObservers.realise(); + } } #include "os/dir.h" -const char *const c_library_extension = +const char* const c_library_extension = #if defined( CMAKE_SHARED_MODULE_SUFFIX ) - CMAKE_SHARED_MODULE_SUFFIX + CMAKE_SHARED_MODULE_SUFFIX #elif GDEF_OS_WINDOWS - "dll" + "dll" #elif GDEF_OS_MACOS "dylib" #elif GDEF_OS_LINUX || GDEF_OS_BSD @@ -736,62 +684,57 @@ const char *const c_library_extension = #endif ; -void Radiant_loadModules(const char *path) -{ - Directory_forEach(path, matchFileExtension(c_library_extension, [&](const char *name) { - char fullname[1024]; - ASSERT_MESSAGE(strlen(path) + strlen(name) < 1024, ""); - strcpy(fullname, path); - strcat(fullname, name); - globalOutputStream() << "Found '" << fullname << "'\n"; - GlobalModuleServer_loadModule(fullname); - })); +void Radiant_loadModules( const char* path ){ + Directory_forEach(path, matchFileExtension(c_library_extension, [&](const char *name) { + char fullname[1024]; + ASSERT_MESSAGE(strlen(path) + strlen(name) < 1024, ""); + strcpy(fullname, path); + strcat(fullname, name); + globalOutputStream() << "Found '" << fullname << "'\n"; + GlobalModuleServer_loadModule(fullname); + })); } -void Radiant_loadModulesFromRoot(const char *directory) -{ - { - StringOutputStream path(256); - path << directory << g_pluginsDir; - Radiant_loadModules(path.c_str()); - } +void Radiant_loadModulesFromRoot( const char* directory ){ + { + StringOutputStream path( 256 ); + path << directory << g_pluginsDir; + Radiant_loadModules( path.c_str() ); + } - if (!string_equal(g_pluginsDir, g_modulesDir)) { - StringOutputStream path(256); - path << directory << g_modulesDir; - Radiant_loadModules(path.c_str()); - } + if ( !string_equal( g_pluginsDir, g_modulesDir ) ) { + StringOutputStream path( 256 ); + path << directory << g_modulesDir; + Radiant_loadModules( path.c_str() ); + } } //! Make COLOR_BRUSHES override worldspawn eclass colour. -void SetWorldspawnColour(const Vector3 &colour) -{ - EntityClass *worldspawn = GlobalEntityClassManager().findOrInsert("worldspawn", true); - eclass_release_state(worldspawn); - worldspawn->color = colour; - eclass_capture_state(worldspawn); +void SetWorldspawnColour( const Vector3& colour ){ + EntityClass* worldspawn = GlobalEntityClassManager().findOrInsert( "worldspawn", true ); + eclass_release_state( worldspawn ); + worldspawn->color = colour; + eclass_capture_state( worldspawn ); } -class WorldspawnColourEntityClassObserver : public ModuleObserver { - std::size_t m_unrealised; +class WorldspawnColourEntityClassObserver : public ModuleObserver +{ +std::size_t m_unrealised; public: - WorldspawnColourEntityClassObserver() : m_unrealised(1) - { - } - - void realise() - { - if (--m_unrealised == 0) { - SetWorldspawnColour(g_xywindow_globals.color_brushes); - } - } - - void unrealise() - { - if (++m_unrealised == 1) { - } - } +WorldspawnColourEntityClassObserver() : m_unrealised( 1 ){ +} + +void realise(){ + if ( --m_unrealised == 0 ) { + SetWorldspawnColour( g_xywindow_globals.color_brushes ); + } +} + +void unrealise(){ + if ( ++m_unrealised == 1 ) { + } +} }; WorldspawnColourEntityClassObserver g_WorldspawnColourEntityClassObserver; @@ -799,426 +742,386 @@ WorldspawnColourEntityClassObserver g_WorldspawnColourEntityClassObserver; ModuleObservers g_gameToolsPathObservers; -void Radiant_attachGameToolsPathObserver(ModuleObserver &observer) -{ - g_gameToolsPathObservers.attach(observer); +void Radiant_attachGameToolsPathObserver( ModuleObserver& observer ){ + g_gameToolsPathObservers.attach( observer ); } -void Radiant_detachGameToolsPathObserver(ModuleObserver &observer) -{ - g_gameToolsPathObservers.detach(observer); +void Radiant_detachGameToolsPathObserver( ModuleObserver& observer ){ + g_gameToolsPathObservers.detach( observer ); } -void Radiant_Initialise() -{ - GlobalModuleServer_Initialise(); +void Radiant_Initialise(){ + GlobalModuleServer_Initialise(); - Radiant_loadModulesFromRoot(AppPath_get()); + Radiant_loadModulesFromRoot( AppPath_get() ); - Preferences_Load(); + Preferences_Load(); - bool success = Radiant_Construct(GlobalModuleServer_get()); - ASSERT_MESSAGE(success, "module system failed to initialise - see radiant.log for error messages"); + bool success = Radiant_Construct( GlobalModuleServer_get() ); + ASSERT_MESSAGE( success, "module system failed to initialise - see radiant.log for error messages" ); - g_gameToolsPathObservers.realise(); - g_gameModeObservers.realise(); - g_gameNameObservers.realise(); + g_gameToolsPathObservers.realise(); + g_gameModeObservers.realise(); + g_gameNameObservers.realise(); } -void Radiant_Shutdown() -{ - g_gameNameObservers.unrealise(); - g_gameModeObservers.unrealise(); - g_gameToolsPathObservers.unrealise(); +void Radiant_Shutdown(){ + g_gameNameObservers.unrealise(); + g_gameModeObservers.unrealise(); + g_gameToolsPathObservers.unrealise(); - if (!g_preferences_globals.disable_ini) { - globalOutputStream() << "Start writing prefs\n"; - Preferences_Save(); - globalOutputStream() << "Done prefs\n"; - } + if ( !g_preferences_globals.disable_ini ) { + globalOutputStream() << "Start writing prefs\n"; + Preferences_Save(); + globalOutputStream() << "Done prefs\n"; + } - Radiant_Destroy(); + Radiant_Destroy(); - GlobalModuleServer_Shutdown(); + GlobalModuleServer_Shutdown(); } -void Exit() -{ - if (ConfirmModified("Exit Radiant")) { - gtk_main_quit(); - } +void Exit(){ + if ( ConfirmModified( "Exit Radiant" ) ) { + gtk_main_quit(); + } } -void Undo() -{ - GlobalUndoSystem().undo(); - SceneChangeNotify(); +void Undo(){ + GlobalUndoSystem().undo(); + SceneChangeNotify(); } -void Redo() -{ - GlobalUndoSystem().redo(); - SceneChangeNotify(); +void Redo(){ + GlobalUndoSystem().redo(); + SceneChangeNotify(); } -void deleteSelection() -{ - UndoableCommand undo("deleteSelected"); - Select_Delete(); +void deleteSelection(){ + UndoableCommand undo( "deleteSelected" ); + Select_Delete(); } -void Map_ExportSelected(TextOutputStream &ostream) -{ - Map_ExportSelected(ostream, Map_getFormat(g_map)); +void Map_ExportSelected( TextOutputStream& ostream ){ + Map_ExportSelected( ostream, Map_getFormat( g_map ) ); } -void Map_ImportSelected(TextInputStream &istream) -{ - Map_ImportSelected(istream, Map_getFormat(g_map)); +void Map_ImportSelected( TextInputStream& istream ){ + Map_ImportSelected( istream, Map_getFormat( g_map ) ); } -void Selection_Copy() -{ - clipboard_copy(Map_ExportSelected); +void Selection_Copy(){ + clipboard_copy( Map_ExportSelected ); } -void Selection_Paste() -{ - clipboard_paste(Map_ImportSelected); +void Selection_Paste(){ + clipboard_paste( Map_ImportSelected ); } -void Copy() -{ - if (SelectedFaces_empty()) { - Selection_Copy(); - } else { - SelectedFaces_copyTexture(); - } +void Copy(){ + if ( SelectedFaces_empty() ) { + Selection_Copy(); + } + else + { + SelectedFaces_copyTexture(); + } } -void Paste() -{ - if (SelectedFaces_empty()) { - UndoableCommand undo("paste"); +void Paste(){ + if ( SelectedFaces_empty() ) { + UndoableCommand undo( "paste" ); - GlobalSelectionSystem().setSelectedAll(false); - Selection_Paste(); - } else { - SelectedFaces_pasteTexture(); - } + GlobalSelectionSystem().setSelectedAll( false ); + Selection_Paste(); + } + else + { + SelectedFaces_pasteTexture(); + } } -void PasteToCamera() -{ - CamWnd &camwnd = *g_pParentWnd->GetCamWnd(); - GlobalSelectionSystem().setSelectedAll(false); +void PasteToCamera(){ + CamWnd& camwnd = *g_pParentWnd->GetCamWnd(); + GlobalSelectionSystem().setSelectedAll( false ); - UndoableCommand undo("pasteToCamera"); + UndoableCommand undo( "pasteToCamera" ); - Selection_Paste(); + Selection_Paste(); - // Work out the delta - Vector3 mid; - Select_GetMid(mid); - Vector3 delta = vector3_subtracted(vector3_snapped(Camera_getOrigin(camwnd), GetSnapGridSize()), mid); + // Work out the delta + Vector3 mid; + Select_GetMid( mid ); + Vector3 delta = vector3_subtracted( vector3_snapped( Camera_getOrigin( camwnd ), GetSnapGridSize() ), mid ); - // Move to camera - GlobalSelectionSystem().translateSelected(delta); + // Move to camera + GlobalSelectionSystem().translateSelected( delta ); } -void ColorScheme_Original() -{ - TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), Vector3(0.25f, 0.25f, 0.25f)); - - g_camwindow_globals.color_selbrushes3d = Vector3(1.0f, 0.0f, 0.0f); - g_camwindow_globals.color_cameraback = Vector3(0.25f, 0.25f, 0.25f); - CamWnd_Update(*g_pParentWnd->GetCamWnd()); - - g_xywindow_globals.color_gridback = Vector3(1.0f, 1.0f, 1.0f); - g_xywindow_globals.color_gridminor = Vector3(0.75f, 0.75f, 0.75f); - g_xywindow_globals.color_gridmajor = Vector3(0.5f, 0.5f, 0.5f); - g_xywindow_globals.color_gridminor_alt = Vector3(0.5f, 0.0f, 0.0f); - g_xywindow_globals.color_gridmajor_alt = Vector3(1.0f, 0.0f, 0.0f); - g_xywindow_globals.color_gridblock = Vector3(0.0f, 0.0f, 1.0f); - g_xywindow_globals.color_gridtext = Vector3(0.0f, 0.0f, 0.0f); - g_xywindow_globals.color_selbrushes = Vector3(1.0f, 0.0f, 0.0f); - g_xywindow_globals.color_clipper = Vector3(0.0f, 0.0f, 1.0f); - g_xywindow_globals.color_brushes = Vector3(0.0f, 0.0f, 0.0f); - SetWorldspawnColour(g_xywindow_globals.color_brushes); - g_xywindow_globals.color_viewname = Vector3(0.5f, 0.0f, 0.75f); - XY_UpdateAllWindows(); -} - -void ColorScheme_QER() -{ - TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), Vector3(0.25f, 0.25f, 0.25f)); - - g_camwindow_globals.color_cameraback = Vector3(0.25f, 0.25f, 0.25f); - g_camwindow_globals.color_selbrushes3d = Vector3(1.0f, 0.0f, 0.0f); - CamWnd_Update(*g_pParentWnd->GetCamWnd()); - - g_xywindow_globals.color_gridback = Vector3(1.0f, 1.0f, 1.0f); - g_xywindow_globals.color_gridminor = Vector3(1.0f, 1.0f, 1.0f); - g_xywindow_globals.color_gridmajor = Vector3(0.5f, 0.5f, 0.5f); - g_xywindow_globals.color_gridblock = Vector3(0.0f, 0.0f, 1.0f); - g_xywindow_globals.color_gridtext = Vector3(0.0f, 0.0f, 0.0f); - g_xywindow_globals.color_selbrushes = Vector3(1.0f, 0.0f, 0.0f); - g_xywindow_globals.color_clipper = Vector3(0.0f, 0.0f, 1.0f); - g_xywindow_globals.color_brushes = Vector3(0.0f, 0.0f, 0.0f); - SetWorldspawnColour(g_xywindow_globals.color_brushes); - g_xywindow_globals.color_viewname = Vector3(0.5f, 0.0f, 0.75f); - XY_UpdateAllWindows(); -} - -void ColorScheme_Black() -{ - TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), Vector3(0.25f, 0.25f, 0.25f)); +void ColorScheme_Original(){ + TextureBrowser_setBackgroundColour( GlobalTextureBrowser(), Vector3( 0.25f, 0.25f, 0.25f ) ); + + g_camwindow_globals.color_selbrushes3d = Vector3( 1.0f, 0.0f, 0.0f ); + g_camwindow_globals.color_cameraback = Vector3( 0.25f, 0.25f, 0.25f ); + CamWnd_Update( *g_pParentWnd->GetCamWnd() ); + + g_xywindow_globals.color_gridback = Vector3( 1.0f, 1.0f, 1.0f ); + g_xywindow_globals.color_gridminor = Vector3( 0.75f, 0.75f, 0.75f ); + g_xywindow_globals.color_gridmajor = Vector3( 0.5f, 0.5f, 0.5f ); + g_xywindow_globals.color_gridminor_alt = Vector3( 0.5f, 0.0f, 0.0f ); + g_xywindow_globals.color_gridmajor_alt = Vector3( 1.0f, 0.0f, 0.0f ); + g_xywindow_globals.color_gridblock = Vector3( 0.0f, 0.0f, 1.0f ); + g_xywindow_globals.color_gridtext = Vector3( 0.0f, 0.0f, 0.0f ); + g_xywindow_globals.color_selbrushes = Vector3( 1.0f, 0.0f, 0.0f ); + g_xywindow_globals.color_clipper = Vector3( 0.0f, 0.0f, 1.0f ); + g_xywindow_globals.color_brushes = Vector3( 0.0f, 0.0f, 0.0f ); + SetWorldspawnColour( g_xywindow_globals.color_brushes ); + g_xywindow_globals.color_viewname = Vector3( 0.5f, 0.0f, 0.75f ); + XY_UpdateAllWindows(); +} - g_camwindow_globals.color_cameraback = Vector3(0.25f, 0.25f, 0.25f); - g_camwindow_globals.color_selbrushes3d = Vector3(1.0f, 0.0f, 0.0f); - CamWnd_Update(*g_pParentWnd->GetCamWnd()); +void ColorScheme_QER(){ + TextureBrowser_setBackgroundColour( GlobalTextureBrowser(), Vector3( 0.25f, 0.25f, 0.25f ) ); - g_xywindow_globals.color_gridback = Vector3(0.0f, 0.0f, 0.0f); - g_xywindow_globals.color_gridminor = Vector3(0.2f, 0.2f, 0.2f); - g_xywindow_globals.color_gridmajor = Vector3(0.3f, 0.5f, 0.5f); - g_xywindow_globals.color_gridblock = Vector3(0.0f, 0.0f, 1.0f); - g_xywindow_globals.color_gridtext = Vector3(1.0f, 1.0f, 1.0f); - g_xywindow_globals.color_selbrushes = Vector3(1.0f, 0.0f, 0.0f); - g_xywindow_globals.color_clipper = Vector3(0.0f, 0.0f, 1.0f); - g_xywindow_globals.color_brushes = Vector3(1.0f, 1.0f, 1.0f); - SetWorldspawnColour(g_xywindow_globals.color_brushes); - g_xywindow_globals.color_viewname = Vector3(0.7f, 0.7f, 0.0f); - XY_UpdateAllWindows(); + g_camwindow_globals.color_cameraback = Vector3( 0.25f, 0.25f, 0.25f ); + g_camwindow_globals.color_selbrushes3d = Vector3( 1.0f, 0.0f, 0.0f ); + CamWnd_Update( *g_pParentWnd->GetCamWnd() ); + + g_xywindow_globals.color_gridback = Vector3( 1.0f, 1.0f, 1.0f ); + g_xywindow_globals.color_gridminor = Vector3( 1.0f, 1.0f, 1.0f ); + g_xywindow_globals.color_gridmajor = Vector3( 0.5f, 0.5f, 0.5f ); + g_xywindow_globals.color_gridblock = Vector3( 0.0f, 0.0f, 1.0f ); + g_xywindow_globals.color_gridtext = Vector3( 0.0f, 0.0f, 0.0f ); + g_xywindow_globals.color_selbrushes = Vector3( 1.0f, 0.0f, 0.0f ); + g_xywindow_globals.color_clipper = Vector3( 0.0f, 0.0f, 1.0f ); + g_xywindow_globals.color_brushes = Vector3( 0.0f, 0.0f, 0.0f ); + SetWorldspawnColour( g_xywindow_globals.color_brushes ); + g_xywindow_globals.color_viewname = Vector3( 0.5f, 0.0f, 0.75f ); + XY_UpdateAllWindows(); +} + +void ColorScheme_Black(){ + TextureBrowser_setBackgroundColour( GlobalTextureBrowser(), Vector3( 0.25f, 0.25f, 0.25f ) ); + + g_camwindow_globals.color_cameraback = Vector3( 0.25f, 0.25f, 0.25f ); + g_camwindow_globals.color_selbrushes3d = Vector3( 1.0f, 0.0f, 0.0f ); + CamWnd_Update( *g_pParentWnd->GetCamWnd() ); + + g_xywindow_globals.color_gridback = Vector3( 0.0f, 0.0f, 0.0f ); + g_xywindow_globals.color_gridminor = Vector3( 0.2f, 0.2f, 0.2f ); + g_xywindow_globals.color_gridmajor = Vector3( 0.3f, 0.5f, 0.5f ); + g_xywindow_globals.color_gridblock = Vector3( 0.0f, 0.0f, 1.0f ); + g_xywindow_globals.color_gridtext = Vector3( 1.0f, 1.0f, 1.0f ); + g_xywindow_globals.color_selbrushes = Vector3( 1.0f, 0.0f, 0.0f ); + g_xywindow_globals.color_clipper = Vector3( 0.0f, 0.0f, 1.0f ); + g_xywindow_globals.color_brushes = Vector3( 1.0f, 1.0f, 1.0f ); + SetWorldspawnColour( g_xywindow_globals.color_brushes ); + g_xywindow_globals.color_viewname = Vector3( 0.7f, 0.7f, 0.0f ); + XY_UpdateAllWindows(); } /* ydnar: to emulate maya/max/lightwave color schemes */ -void ColorScheme_Ydnar() +void ColorScheme_Ydnar(){ + TextureBrowser_setBackgroundColour( GlobalTextureBrowser(), Vector3( 0.25f, 0.25f, 0.25f ) ); + + g_camwindow_globals.color_cameraback = Vector3( 0.25f, 0.25f, 0.25f ); + g_camwindow_globals.color_selbrushes3d = Vector3( 1.0f, 0.0f, 0.0f ); + CamWnd_Update( *g_pParentWnd->GetCamWnd() ); + + g_xywindow_globals.color_gridback = Vector3( 0.77f, 0.77f, 0.77f ); + g_xywindow_globals.color_gridminor = Vector3( 0.83f, 0.83f, 0.83f ); + g_xywindow_globals.color_gridmajor = Vector3( 0.89f, 0.89f, 0.89f ); + g_xywindow_globals.color_gridblock = Vector3( 1.0f, 1.0f, 1.0f ); + g_xywindow_globals.color_gridtext = Vector3( 0.0f, 0.0f, 0.0f ); + g_xywindow_globals.color_selbrushes = Vector3( 1.0f, 0.0f, 0.0f ); + g_xywindow_globals.color_clipper = Vector3( 0.0f, 0.0f, 1.0f ); + g_xywindow_globals.color_brushes = Vector3( 0.0f, 0.0f, 0.0f ); + SetWorldspawnColour( g_xywindow_globals.color_brushes ); + g_xywindow_globals.color_viewname = Vector3( 0.5f, 0.0f, 0.75f ); + XY_UpdateAllWindows(); +} + +typedef Callback GetColourCallback; +typedef Callback SetColourCallback; + +class ChooseColour { - TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), Vector3(0.25f, 0.25f, 0.25f)); - - g_camwindow_globals.color_cameraback = Vector3(0.25f, 0.25f, 0.25f); - g_camwindow_globals.color_selbrushes3d = Vector3(1.0f, 0.0f, 0.0f); - CamWnd_Update(*g_pParentWnd->GetCamWnd()); - - g_xywindow_globals.color_gridback = Vector3(0.77f, 0.77f, 0.77f); - g_xywindow_globals.color_gridminor = Vector3(0.83f, 0.83f, 0.83f); - g_xywindow_globals.color_gridmajor = Vector3(0.89f, 0.89f, 0.89f); - g_xywindow_globals.color_gridblock = Vector3(1.0f, 1.0f, 1.0f); - g_xywindow_globals.color_gridtext = Vector3(0.0f, 0.0f, 0.0f); - g_xywindow_globals.color_selbrushes = Vector3(1.0f, 0.0f, 0.0f); - g_xywindow_globals.color_clipper = Vector3(0.0f, 0.0f, 1.0f); - g_xywindow_globals.color_brushes = Vector3(0.0f, 0.0f, 0.0f); - SetWorldspawnColour(g_xywindow_globals.color_brushes); - g_xywindow_globals.color_viewname = Vector3(0.5f, 0.0f, 0.75f); - XY_UpdateAllWindows(); -} - -typedef Callback GetColourCallback; -typedef Callback SetColourCallback; - -class ChooseColour { - GetColourCallback m_get; - SetColourCallback m_set; +GetColourCallback m_get; +SetColourCallback m_set; public: - ChooseColour(const GetColourCallback &get, const SetColourCallback &set) - : m_get(get), m_set(set) - { - } - - void operator()() - { - Vector3 colour; - m_get(colour); - color_dialog(MainFrame_getWindow(), colour); - m_set(colour); - } +ChooseColour( const GetColourCallback& get, const SetColourCallback& set ) + : m_get( get ), m_set( set ){ +} + +void operator()(){ + Vector3 colour; + m_get( colour ); + color_dialog( MainFrame_getWindow(), colour ); + m_set( colour ); +} }; -void Colour_get(const Vector3 &colour, Vector3 &other) -{ - other = colour; +void Colour_get( const Vector3& colour, Vector3& other ){ + other = colour; } -typedef ConstReferenceCaller ColourGetCaller; +typedef ConstReferenceCaller ColourGetCaller; -void Colour_set(Vector3 &colour, const Vector3 &other) -{ - colour = other; - SceneChangeNotify(); +void Colour_set( Vector3& colour, const Vector3& other ){ + colour = other; + SceneChangeNotify(); } -typedef ReferenceCaller ColourSetCaller; +typedef ReferenceCaller ColourSetCaller; -void BrushColour_set(const Vector3 &other) -{ - g_xywindow_globals.color_brushes = other; - SetWorldspawnColour(g_xywindow_globals.color_brushes); - SceneChangeNotify(); +void BrushColour_set( const Vector3& other ){ + g_xywindow_globals.color_brushes = other; + SetWorldspawnColour( g_xywindow_globals.color_brushes ); + SceneChangeNotify(); } -typedef FreeCaller BrushColourSetCaller; +typedef FreeCaller BrushColourSetCaller; -void ClipperColour_set(const Vector3 &other) -{ - g_xywindow_globals.color_clipper = other; - Brush_clipperColourChanged(); - SceneChangeNotify(); +void ClipperColour_set( const Vector3& other ){ + g_xywindow_globals.color_clipper = other; + Brush_clipperColourChanged(); + SceneChangeNotify(); } -typedef FreeCaller ClipperColourSetCaller; +typedef FreeCaller ClipperColourSetCaller; -void TextureBrowserColour_get(Vector3 &other) -{ - other = TextureBrowser_getBackgroundColour(GlobalTextureBrowser()); +void TextureBrowserColour_get( Vector3& other ){ + other = TextureBrowser_getBackgroundColour( GlobalTextureBrowser() ); } -typedef FreeCaller TextureBrowserColourGetCaller; +typedef FreeCaller TextureBrowserColourGetCaller; -void TextureBrowserColour_set(const Vector3 &other) -{ - TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), other); +void TextureBrowserColour_set( const Vector3& other ){ + TextureBrowser_setBackgroundColour( GlobalTextureBrowser(), other ); } -typedef FreeCaller TextureBrowserColourSetCaller; +typedef FreeCaller TextureBrowserColourSetCaller; -class ColoursMenu { +class ColoursMenu +{ public: - ChooseColour m_textureback; - ChooseColour m_xyback; - ChooseColour m_gridmajor; - ChooseColour m_gridminor; - ChooseColour m_gridmajor_alt; - ChooseColour m_gridminor_alt; - ChooseColour m_gridtext; - ChooseColour m_gridblock; - ChooseColour m_cameraback; - ChooseColour m_brush; - ChooseColour m_selectedbrush; - ChooseColour m_selectedbrush3d; - ChooseColour m_clipper; - ChooseColour m_viewname; - - ColoursMenu() : - m_textureback(TextureBrowserColourGetCaller(), TextureBrowserColourSetCaller()), - m_xyback(ColourGetCaller(g_xywindow_globals.color_gridback), - ColourSetCaller(g_xywindow_globals.color_gridback)), - m_gridmajor(ColourGetCaller(g_xywindow_globals.color_gridmajor), - ColourSetCaller(g_xywindow_globals.color_gridmajor)), - m_gridminor(ColourGetCaller(g_xywindow_globals.color_gridminor), - ColourSetCaller(g_xywindow_globals.color_gridminor)), - m_gridmajor_alt(ColourGetCaller(g_xywindow_globals.color_gridmajor_alt), - ColourSetCaller(g_xywindow_globals.color_gridmajor_alt)), - m_gridminor_alt(ColourGetCaller(g_xywindow_globals.color_gridminor_alt), - ColourSetCaller(g_xywindow_globals.color_gridminor_alt)), - m_gridtext(ColourGetCaller(g_xywindow_globals.color_gridtext), - ColourSetCaller(g_xywindow_globals.color_gridtext)), - m_gridblock(ColourGetCaller(g_xywindow_globals.color_gridblock), - ColourSetCaller(g_xywindow_globals.color_gridblock)), - m_cameraback(ColourGetCaller(g_camwindow_globals.color_cameraback), - ColourSetCaller(g_camwindow_globals.color_cameraback)), - m_brush(ColourGetCaller(g_xywindow_globals.color_brushes), BrushColourSetCaller()), - m_selectedbrush(ColourGetCaller(g_xywindow_globals.color_selbrushes), - ColourSetCaller(g_xywindow_globals.color_selbrushes)), - m_selectedbrush3d(ColourGetCaller(g_camwindow_globals.color_selbrushes3d), - ColourSetCaller(g_camwindow_globals.color_selbrushes3d)), - m_clipper(ColourGetCaller(g_xywindow_globals.color_clipper), ClipperColourSetCaller()), - m_viewname(ColourGetCaller(g_xywindow_globals.color_viewname), - ColourSetCaller(g_xywindow_globals.color_viewname)) - { - } +ChooseColour m_textureback; +ChooseColour m_xyback; +ChooseColour m_gridmajor; +ChooseColour m_gridminor; +ChooseColour m_gridmajor_alt; +ChooseColour m_gridminor_alt; +ChooseColour m_gridtext; +ChooseColour m_gridblock; +ChooseColour m_cameraback; +ChooseColour m_brush; +ChooseColour m_selectedbrush; +ChooseColour m_selectedbrush3d; +ChooseColour m_clipper; +ChooseColour m_viewname; + +ColoursMenu() : + m_textureback( TextureBrowserColourGetCaller(), TextureBrowserColourSetCaller() ), + m_xyback( ColourGetCaller( g_xywindow_globals.color_gridback ), ColourSetCaller( g_xywindow_globals.color_gridback ) ), + m_gridmajor( ColourGetCaller( g_xywindow_globals.color_gridmajor ), ColourSetCaller( g_xywindow_globals.color_gridmajor ) ), + m_gridminor( ColourGetCaller( g_xywindow_globals.color_gridminor ), ColourSetCaller( g_xywindow_globals.color_gridminor ) ), + m_gridmajor_alt( ColourGetCaller( g_xywindow_globals.color_gridmajor_alt ), ColourSetCaller( g_xywindow_globals.color_gridmajor_alt ) ), + m_gridminor_alt( ColourGetCaller( g_xywindow_globals.color_gridminor_alt ), ColourSetCaller( g_xywindow_globals.color_gridminor_alt ) ), + m_gridtext( ColourGetCaller( g_xywindow_globals.color_gridtext ), ColourSetCaller( g_xywindow_globals.color_gridtext ) ), + m_gridblock( ColourGetCaller( g_xywindow_globals.color_gridblock ), ColourSetCaller( g_xywindow_globals.color_gridblock ) ), + m_cameraback( ColourGetCaller( g_camwindow_globals.color_cameraback ), ColourSetCaller( g_camwindow_globals.color_cameraback ) ), + m_brush( ColourGetCaller( g_xywindow_globals.color_brushes ), BrushColourSetCaller() ), + m_selectedbrush( ColourGetCaller( g_xywindow_globals.color_selbrushes ), ColourSetCaller( g_xywindow_globals.color_selbrushes ) ), + m_selectedbrush3d( ColourGetCaller( g_camwindow_globals.color_selbrushes3d ), ColourSetCaller( g_camwindow_globals.color_selbrushes3d ) ), + m_clipper( ColourGetCaller( g_xywindow_globals.color_clipper ), ClipperColourSetCaller() ), + m_viewname( ColourGetCaller( g_xywindow_globals.color_viewname ), ColourSetCaller( g_xywindow_globals.color_viewname ) ){ +} }; ColoursMenu g_ColoursMenu; -ui::MenuItem create_colours_menu() -{ - auto colours_menu_item = new_sub_menu_item_with_mnemonic("Colors"); - auto menu_in_menu = ui::Menu::from(gtk_menu_item_get_submenu(colours_menu_item)); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu_in_menu); - } - - auto menu_3 = create_sub_menu_with_mnemonic(menu_in_menu, "Themes"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu_3); - } - - create_menu_item_with_mnemonic(menu_3, "QE4 Original", "ColorSchemeOriginal"); - create_menu_item_with_mnemonic(menu_3, "Q3Radiant Original", "ColorSchemeQER"); - create_menu_item_with_mnemonic(menu_3, "Black and Green", "ColorSchemeBlackAndGreen"); - create_menu_item_with_mnemonic(menu_3, "Maya/Max/Lightwave Emulation", "ColorSchemeYdnar"); - - menu_separator(menu_in_menu); - - create_menu_item_with_mnemonic(menu_in_menu, "_Texture Background...", "ChooseTextureBackgroundColor"); - create_menu_item_with_mnemonic(menu_in_menu, "Grid Background...", "ChooseGridBackgroundColor"); - create_menu_item_with_mnemonic(menu_in_menu, "Grid Major...", "ChooseGridMajorColor"); - create_menu_item_with_mnemonic(menu_in_menu, "Grid Minor...", "ChooseGridMinorColor"); - create_menu_item_with_mnemonic(menu_in_menu, "Grid Major Small...", "ChooseSmallGridMajorColor"); - create_menu_item_with_mnemonic(menu_in_menu, "Grid Minor Small...", "ChooseSmallGridMinorColor"); - create_menu_item_with_mnemonic(menu_in_menu, "Grid Text...", "ChooseGridTextColor"); - create_menu_item_with_mnemonic(menu_in_menu, "Grid Block...", "ChooseGridBlockColor"); - create_menu_item_with_mnemonic(menu_in_menu, "Default Brush...", "ChooseBrushColor"); - create_menu_item_with_mnemonic(menu_in_menu, "Camera Background...", "ChooseCameraBackgroundColor"); - create_menu_item_with_mnemonic(menu_in_menu, "Selected Brush...", "ChooseSelectedBrushColor"); - create_menu_item_with_mnemonic(menu_in_menu, "Selected Brush (Camera)...", "ChooseCameraSelectedBrushColor"); - create_menu_item_with_mnemonic(menu_in_menu, "Clipper...", "ChooseClipperColor"); - create_menu_item_with_mnemonic(menu_in_menu, "Active View name...", "ChooseOrthoViewNameColor"); - - return colours_menu_item; -} - - -void Restart() -{ - PluginsMenu_clear(); - PluginToolbar_clear(); +ui::MenuItem create_colours_menu(){ + auto colours_menu_item = new_sub_menu_item_with_mnemonic( "Colors" ); + auto menu_in_menu = ui::Menu::from( gtk_menu_item_get_submenu( colours_menu_item ) ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu_in_menu ); + } + + auto menu_3 = create_sub_menu_with_mnemonic( menu_in_menu, "Themes" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu_3 ); + } - Radiant_Shutdown(); - Radiant_Initialise(); + create_menu_item_with_mnemonic( menu_3, "QE4 Original", "ColorSchemeOriginal" ); + create_menu_item_with_mnemonic( menu_3, "Q3Radiant Original", "ColorSchemeQER" ); + create_menu_item_with_mnemonic( menu_3, "Black and Green", "ColorSchemeBlackAndGreen" ); + create_menu_item_with_mnemonic( menu_3, "Maya/Max/Lightwave Emulation", "ColorSchemeYdnar" ); - PluginsMenu_populate(); + menu_separator( menu_in_menu ); - PluginToolbar_populate(); + create_menu_item_with_mnemonic( menu_in_menu, "_Texture Background...", "ChooseTextureBackgroundColor" ); + create_menu_item_with_mnemonic( menu_in_menu, "Grid Background...", "ChooseGridBackgroundColor" ); + create_menu_item_with_mnemonic( menu_in_menu, "Grid Major...", "ChooseGridMajorColor" ); + create_menu_item_with_mnemonic( menu_in_menu, "Grid Minor...", "ChooseGridMinorColor" ); + create_menu_item_with_mnemonic( menu_in_menu, "Grid Major Small...", "ChooseSmallGridMajorColor" ); + create_menu_item_with_mnemonic( menu_in_menu, "Grid Minor Small...", "ChooseSmallGridMinorColor" ); + create_menu_item_with_mnemonic( menu_in_menu, "Grid Text...", "ChooseGridTextColor" ); + create_menu_item_with_mnemonic( menu_in_menu, "Grid Block...", "ChooseGridBlockColor" ); + create_menu_item_with_mnemonic( menu_in_menu, "Default Brush...", "ChooseBrushColor" ); + create_menu_item_with_mnemonic( menu_in_menu, "Camera Background...", "ChooseCameraBackgroundColor" ); + create_menu_item_with_mnemonic( menu_in_menu, "Selected Brush...", "ChooseSelectedBrushColor" ); + create_menu_item_with_mnemonic( menu_in_menu, "Selected Brush (Camera)...", "ChooseCameraSelectedBrushColor" ); + create_menu_item_with_mnemonic( menu_in_menu, "Clipper...", "ChooseClipperColor" ); + create_menu_item_with_mnemonic( menu_in_menu, "Active View name...", "ChooseOrthoViewNameColor" ); + + return colours_menu_item; } -void thunk_OnSleep() -{ - g_pParentWnd->OnSleep(); +void Restart(){ + PluginsMenu_clear(); + PluginToolbar_clear(); + + Radiant_Shutdown(); + Radiant_Initialise(); + + PluginsMenu_populate(); + + PluginToolbar_populate(); } -void OpenHelpURL() -{ - OpenURL("https://gitlab.com/xonotic/xonotic/wikis/Mapping"); + +void thunk_OnSleep(){ + g_pParentWnd->OnSleep(); } -void OpenBugReportURL() -{ - OpenURL("https://gitlab.com/xonotic/netradiant/issues"); +void OpenHelpURL(){ + OpenURL( "https://gitlab.com/xonotic/xonotic/wikis/Mapping" ); +} + +void OpenBugReportURL(){ + OpenURL( "https://gitlab.com/xonotic/netradiant/issues" ); } ui::Widget g_page_console{ui::null}; -void Console_ToggleShow() -{ - GroupDialog_showPage(g_page_console); +void Console_ToggleShow(){ + GroupDialog_showPage( g_page_console ); } ui::Widget g_page_entity{ui::null}; -void EntityInspector_ToggleShow() -{ - GroupDialog_showPage(g_page_entity); +void EntityInspector_ToggleShow(){ + GroupDialog_showPage( g_page_entity ); } -void SetClipMode(bool enable); +void SetClipMode( bool enable ); void ModeChangeNotify(); @@ -1229,1535 +1132,1457 @@ bool g_currentToolModeSupportsComponentEditing = false; ToolMode g_defaultToolMode = 0; -void SelectionSystem_DefaultMode() -{ - GlobalSelectionSystem().SetMode(SelectionSystem::ePrimitive); - GlobalSelectionSystem().SetComponentMode(SelectionSystem::eDefault); - ModeChangeNotify(); +void SelectionSystem_DefaultMode(){ + GlobalSelectionSystem().SetMode( SelectionSystem::ePrimitive ); + GlobalSelectionSystem().SetComponentMode( SelectionSystem::eDefault ); + ModeChangeNotify(); } -bool EdgeMode() -{ - return GlobalSelectionSystem().Mode() == SelectionSystem::eComponent - && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eEdge; +bool EdgeMode(){ + return GlobalSelectionSystem().Mode() == SelectionSystem::eComponent + && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eEdge; } -bool VertexMode() -{ - return GlobalSelectionSystem().Mode() == SelectionSystem::eComponent - && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex; +bool VertexMode(){ + return GlobalSelectionSystem().Mode() == SelectionSystem::eComponent + && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eVertex; } -bool FaceMode() -{ - return GlobalSelectionSystem().Mode() == SelectionSystem::eComponent - && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eFace; +bool FaceMode(){ + return GlobalSelectionSystem().Mode() == SelectionSystem::eComponent + && GlobalSelectionSystem().ComponentMode() == SelectionSystem::eFace; } -template -class BoolFunctionExport { +template +class BoolFunctionExport +{ public: - static void apply(const Callback &importCallback) - { - importCallback(BoolFunction()); - } +static void apply( const Callback & importCallback ){ + importCallback( BoolFunction() ); +} }; typedef FreeCaller &), &BoolFunctionExport::apply> EdgeModeApplyCaller; EdgeModeApplyCaller g_edgeMode_button_caller; -Callback &)> g_edgeMode_button_callback(g_edgeMode_button_caller); -ToggleItem g_edgeMode_button(g_edgeMode_button_callback); +Callback &)> g_edgeMode_button_callback( g_edgeMode_button_caller ); +ToggleItem g_edgeMode_button( g_edgeMode_button_callback ); typedef FreeCaller &), &BoolFunctionExport::apply> VertexModeApplyCaller; VertexModeApplyCaller g_vertexMode_button_caller; -Callback &)> g_vertexMode_button_callback(g_vertexMode_button_caller); -ToggleItem g_vertexMode_button(g_vertexMode_button_callback); +Callback &)> g_vertexMode_button_callback( g_vertexMode_button_caller ); +ToggleItem g_vertexMode_button( g_vertexMode_button_callback ); typedef FreeCaller &), &BoolFunctionExport::apply> FaceModeApplyCaller; FaceModeApplyCaller g_faceMode_button_caller; -Callback &)> g_faceMode_button_callback(g_faceMode_button_caller); -ToggleItem g_faceMode_button(g_faceMode_button_callback); +Callback &)> g_faceMode_button_callback( g_faceMode_button_caller ); +ToggleItem g_faceMode_button( g_faceMode_button_callback ); -void ComponentModeChanged() -{ - g_edgeMode_button.update(); - g_vertexMode_button.update(); - g_faceMode_button.update(); +void ComponentModeChanged(){ + g_edgeMode_button.update(); + g_vertexMode_button.update(); + g_faceMode_button.update(); } -void ComponentMode_SelectionChanged(const Selectable &selectable) -{ - if (GlobalSelectionSystem().Mode() == SelectionSystem::eComponent - && GlobalSelectionSystem().countSelected() == 0) { - SelectionSystem_DefaultMode(); - ComponentModeChanged(); - } +void ComponentMode_SelectionChanged( const Selectable& selectable ){ + if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent + && GlobalSelectionSystem().countSelected() == 0 ) { + SelectionSystem_DefaultMode(); + ComponentModeChanged(); + } } -void SelectEdgeMode() -{ +void SelectEdgeMode(){ #if 0 - if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { + if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { GlobalSelectionSystem().Select( false ); } #endif - if (EdgeMode()) { - SelectionSystem_DefaultMode(); - } else if (GlobalSelectionSystem().countSelected() != 0) { - if (!g_currentToolModeSupportsComponentEditing) { - g_defaultToolMode(); - } + if ( EdgeMode() ) { + SelectionSystem_DefaultMode(); + } + else if ( GlobalSelectionSystem().countSelected() != 0 ) { + if ( !g_currentToolModeSupportsComponentEditing ) { + g_defaultToolMode(); + } - GlobalSelectionSystem().SetMode(SelectionSystem::eComponent); - GlobalSelectionSystem().SetComponentMode(SelectionSystem::eEdge); - } + GlobalSelectionSystem().SetMode( SelectionSystem::eComponent ); + GlobalSelectionSystem().SetComponentMode( SelectionSystem::eEdge ); + } - ComponentModeChanged(); + ComponentModeChanged(); - ModeChangeNotify(); + ModeChangeNotify(); } -void SelectVertexMode() -{ +void SelectVertexMode(){ #if 0 - if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { + if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { GlobalSelectionSystem().Select( false ); } #endif - if (VertexMode()) { - SelectionSystem_DefaultMode(); - } else if (GlobalSelectionSystem().countSelected() != 0) { - if (!g_currentToolModeSupportsComponentEditing) { - g_defaultToolMode(); - } + if ( VertexMode() ) { + SelectionSystem_DefaultMode(); + } + else if ( GlobalSelectionSystem().countSelected() != 0 ) { + if ( !g_currentToolModeSupportsComponentEditing ) { + g_defaultToolMode(); + } - GlobalSelectionSystem().SetMode(SelectionSystem::eComponent); - GlobalSelectionSystem().SetComponentMode(SelectionSystem::eVertex); - } + GlobalSelectionSystem().SetMode( SelectionSystem::eComponent ); + GlobalSelectionSystem().SetComponentMode( SelectionSystem::eVertex ); + } - ComponentModeChanged(); + ComponentModeChanged(); - ModeChangeNotify(); + ModeChangeNotify(); } -void SelectFaceMode() -{ +void SelectFaceMode(){ #if 0 - if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { + if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { GlobalSelectionSystem().Select( false ); } #endif - if (FaceMode()) { - SelectionSystem_DefaultMode(); - } else if (GlobalSelectionSystem().countSelected() != 0) { - if (!g_currentToolModeSupportsComponentEditing) { - g_defaultToolMode(); - } + if ( FaceMode() ) { + SelectionSystem_DefaultMode(); + } + else if ( GlobalSelectionSystem().countSelected() != 0 ) { + if ( !g_currentToolModeSupportsComponentEditing ) { + g_defaultToolMode(); + } - GlobalSelectionSystem().SetMode(SelectionSystem::eComponent); - GlobalSelectionSystem().SetComponentMode(SelectionSystem::eFace); - } + GlobalSelectionSystem().SetMode( SelectionSystem::eComponent ); + GlobalSelectionSystem().SetComponentMode( SelectionSystem::eFace ); + } - ComponentModeChanged(); + ComponentModeChanged(); - ModeChangeNotify(); + ModeChangeNotify(); } -class CloneSelected : public scene::Graph::Walker { - bool doMakeUnique; - NodeSmartReference worldspawn; +class CloneSelected : public scene::Graph::Walker +{ +bool doMakeUnique; +NodeSmartReference worldspawn; public: - CloneSelected(bool d) : doMakeUnique(d), worldspawn(Map_FindOrInsertWorldspawn(g_map)) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - if (path.size() == 1) { - return true; - } - - // ignore worldspawn, but keep checking children - NodeSmartReference me(path.top().get()); - if (me == worldspawn) { - return true; - } - - if (!path.top().get().isRoot()) { - Selectable *selectable = Instance_getSelectable(instance); - if (selectable != 0 - && selectable->isSelected()) { - return false; - } - } - - return true; - } - - void post(const scene::Path &path, scene::Instance &instance) const - { - if (path.size() == 1) { - return; - } - - // ignore worldspawn, but keep checking children - NodeSmartReference me(path.top().get()); - if (me == worldspawn) { - return; - } - - if (!path.top().get().isRoot()) { - Selectable *selectable = Instance_getSelectable(instance); - if (selectable != 0 - && selectable->isSelected()) { - NodeSmartReference clone(Node_Clone(path.top())); - if (doMakeUnique) { - Map_gatherNamespaced(clone); - } - Node_getTraversable(path.parent().get())->insert(clone); - } - } - } -}; +CloneSelected( bool d ) : doMakeUnique( d ), worldspawn( Map_FindOrInsertWorldspawn( g_map ) ){ +} -void Scene_Clone_Selected(scene::Graph &graph, bool doMakeUnique) -{ - graph.traverse(CloneSelected(doMakeUnique)); +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( path.size() == 1 ) { + return true; + } - Map_mergeClonedNames(); + // ignore worldspawn, but keep checking children + NodeSmartReference me( path.top().get() ); + if ( me == worldspawn ) { + return true; + } + + if ( !path.top().get().isRoot() ) { + Selectable* selectable = Instance_getSelectable( instance ); + if ( selectable != 0 + && selectable->isSelected() ) { + return false; + } + } + + return true; } -enum ENudgeDirection { - eNudgeUp = 1, - eNudgeDown = 3, - eNudgeLeft = 0, - eNudgeRight = 2, -}; +void post( const scene::Path& path, scene::Instance& instance ) const { + if ( path.size() == 1 ) { + return; + } -struct AxisBase { - Vector3 x; - Vector3 y; - Vector3 z; + // ignore worldspawn, but keep checking children + NodeSmartReference me( path.top().get() ); + if ( me == worldspawn ) { + return; + } - AxisBase(const Vector3 &x_, const Vector3 &y_, const Vector3 &z_) - : x(x_), y(y_), z(z_) - { - } + if ( !path.top().get().isRoot() ) { + Selectable* selectable = Instance_getSelectable( instance ); + if ( selectable != 0 + && selectable->isSelected() ) { + NodeSmartReference clone( Node_Clone( path.top() ) ); + if ( doMakeUnique ) { + Map_gatherNamespaced( clone ); + } + Node_getTraversable( path.parent().get() )->insert( clone ); + } + } +} }; -AxisBase AxisBase_forViewType(VIEWTYPE viewtype) -{ - switch (viewtype) { - case XY: - return AxisBase(g_vector3_axis_x, g_vector3_axis_y, g_vector3_axis_z); - case XZ: - return AxisBase(g_vector3_axis_x, g_vector3_axis_z, g_vector3_axis_y); - case YZ: - return AxisBase(g_vector3_axis_y, g_vector3_axis_z, g_vector3_axis_x); - } +void Scene_Clone_Selected( scene::Graph& graph, bool doMakeUnique ){ + graph.traverse( CloneSelected( doMakeUnique ) ); - ERROR_MESSAGE("invalid viewtype"); - return AxisBase(Vector3(0, 0, 0), Vector3(0, 0, 0), Vector3(0, 0, 0)); + Map_mergeClonedNames(); } -Vector3 AxisBase_axisForDirection(const AxisBase &axes, ENudgeDirection direction) +enum ENudgeDirection { - switch (direction) { - case eNudgeLeft: - return vector3_negated(axes.x); - case eNudgeUp: - return axes.y; - case eNudgeRight: - return axes.x; - case eNudgeDown: - return vector3_negated(axes.y); - } - - ERROR_MESSAGE("invalid direction"); - return Vector3(0, 0, 0); -} - -void NudgeSelection(ENudgeDirection direction, float fAmount, VIEWTYPE viewtype) + eNudgeUp = 1, + eNudgeDown = 3, + eNudgeLeft = 0, + eNudgeRight = 2, +}; + +struct AxisBase { - AxisBase axes(AxisBase_forViewType(viewtype)); - Vector3 view_direction(vector3_negated(axes.z)); - Vector3 nudge(vector3_scaled(AxisBase_axisForDirection(axes, direction), fAmount)); - GlobalSelectionSystem().NudgeManipulator(nudge, view_direction); + Vector3 x; + Vector3 y; + Vector3 z; + + AxisBase( const Vector3& x_, const Vector3& y_, const Vector3& z_ ) + : x( x_ ), y( y_ ), z( z_ ){ + } +}; + +AxisBase AxisBase_forViewType( VIEWTYPE viewtype ){ + switch ( viewtype ) + { + case XY: + return AxisBase( g_vector3_axis_x, g_vector3_axis_y, g_vector3_axis_z ); + case XZ: + return AxisBase( g_vector3_axis_x, g_vector3_axis_z, g_vector3_axis_y ); + case YZ: + return AxisBase( g_vector3_axis_y, g_vector3_axis_z, g_vector3_axis_x ); + } + + ERROR_MESSAGE( "invalid viewtype" ); + return AxisBase( Vector3( 0, 0, 0 ), Vector3( 0, 0, 0 ), Vector3( 0, 0, 0 ) ); } -void Selection_Clone() -{ - if (GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive) { - UndoableCommand undo("cloneSelected"); +Vector3 AxisBase_axisForDirection( const AxisBase& axes, ENudgeDirection direction ){ + switch ( direction ) + { + case eNudgeLeft: + return vector3_negated( axes.x ); + case eNudgeUp: + return axes.y; + case eNudgeRight: + return axes.x; + case eNudgeDown: + return vector3_negated( axes.y ); + } - Scene_Clone_Selected(GlobalSceneGraph(), false); + ERROR_MESSAGE( "invalid direction" ); + return Vector3( 0, 0, 0 ); +} - //NudgeSelection(eNudgeRight, GetGridSize(), GlobalXYWnd_getCurrentViewType()); - //NudgeSelection(eNudgeDown, GetGridSize(), GlobalXYWnd_getCurrentViewType()); - } +void NudgeSelection( ENudgeDirection direction, float fAmount, VIEWTYPE viewtype ){ + AxisBase axes( AxisBase_forViewType( viewtype ) ); + Vector3 view_direction( vector3_negated( axes.z ) ); + Vector3 nudge( vector3_scaled( AxisBase_axisForDirection( axes, direction ), fAmount ) ); + GlobalSelectionSystem().NudgeManipulator( nudge, view_direction ); } -void Selection_Clone_MakeUnique() -{ - if (GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive) { - UndoableCommand undo("cloneSelectedMakeUnique"); +void Selection_Clone(){ + if ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) { + UndoableCommand undo( "cloneSelected" ); + + Scene_Clone_Selected( GlobalSceneGraph(), false ); + + //NudgeSelection(eNudgeRight, GetGridSize(), GlobalXYWnd_getCurrentViewType()); + //NudgeSelection(eNudgeDown, GetGridSize(), GlobalXYWnd_getCurrentViewType()); + } +} + +void Selection_Clone_MakeUnique(){ + if ( GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) { + UndoableCommand undo( "cloneSelectedMakeUnique" ); - Scene_Clone_Selected(GlobalSceneGraph(), true); + Scene_Clone_Selected( GlobalSceneGraph(), true ); - //NudgeSelection(eNudgeRight, GetGridSize(), GlobalXYWnd_getCurrentViewType()); - //NudgeSelection(eNudgeDown, GetGridSize(), GlobalXYWnd_getCurrentViewType()); - } + //NudgeSelection(eNudgeRight, GetGridSize(), GlobalXYWnd_getCurrentViewType()); + //NudgeSelection(eNudgeDown, GetGridSize(), GlobalXYWnd_getCurrentViewType()); + } } // called when the escape key is used (either on the main window or on an inspector) -void Selection_Deselect() -{ - if (GlobalSelectionSystem().Mode() == SelectionSystem::eComponent) { - if (GlobalSelectionSystem().countSelectedComponents() != 0) { - GlobalSelectionSystem().setSelectedAllComponents(false); - } else { - SelectionSystem_DefaultMode(); - ComponentModeChanged(); - } - } else { - if (GlobalSelectionSystem().countSelectedComponents() != 0) { - GlobalSelectionSystem().setSelectedAllComponents(false); - } else { - GlobalSelectionSystem().setSelectedAll(false); - } - } -} - - -void Selection_NudgeUp() -{ - UndoableCommand undo("nudgeSelectedUp"); - NudgeSelection(eNudgeUp, GetGridSize(), GlobalXYWnd_getCurrentViewType()); +void Selection_Deselect(){ + if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { + if ( GlobalSelectionSystem().countSelectedComponents() != 0 ) { + GlobalSelectionSystem().setSelectedAllComponents( false ); + } + else + { + SelectionSystem_DefaultMode(); + ComponentModeChanged(); + } + } + else + { + if ( GlobalSelectionSystem().countSelectedComponents() != 0 ) { + GlobalSelectionSystem().setSelectedAllComponents( false ); + } + else + { + GlobalSelectionSystem().setSelectedAll( false ); + } + } } -void Selection_NudgeDown() -{ - UndoableCommand undo("nudgeSelectedDown"); - NudgeSelection(eNudgeDown, GetGridSize(), GlobalXYWnd_getCurrentViewType()); + +void Selection_NudgeUp(){ + UndoableCommand undo( "nudgeSelectedUp" ); + NudgeSelection( eNudgeUp, GetGridSize(), GlobalXYWnd_getCurrentViewType() ); } -void Selection_NudgeLeft() -{ - UndoableCommand undo("nudgeSelectedLeft"); - NudgeSelection(eNudgeLeft, GetGridSize(), GlobalXYWnd_getCurrentViewType()); +void Selection_NudgeDown(){ + UndoableCommand undo( "nudgeSelectedDown" ); + NudgeSelection( eNudgeDown, GetGridSize(), GlobalXYWnd_getCurrentViewType() ); } -void Selection_NudgeRight() -{ - UndoableCommand undo("nudgeSelectedRight"); - NudgeSelection(eNudgeRight, GetGridSize(), GlobalXYWnd_getCurrentViewType()); +void Selection_NudgeLeft(){ + UndoableCommand undo( "nudgeSelectedLeft" ); + NudgeSelection( eNudgeLeft, GetGridSize(), GlobalXYWnd_getCurrentViewType() ); } +void Selection_NudgeRight(){ + UndoableCommand undo( "nudgeSelectedRight" ); + NudgeSelection( eNudgeRight, GetGridSize(), GlobalXYWnd_getCurrentViewType() ); +} -void TranslateToolExport(const Callback &importCallback) -{ - importCallback(GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eTranslate); + +void TranslateToolExport( const Callback & importCallback ){ + importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eTranslate ); } -void RotateToolExport(const Callback &importCallback) -{ - importCallback(GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eRotate); +void RotateToolExport( const Callback & importCallback ){ + importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eRotate ); } -void ScaleToolExport(const Callback &importCallback) -{ - importCallback(GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eScale); +void ScaleToolExport( const Callback & importCallback ){ + importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eScale ); } -void DragToolExport(const Callback &importCallback) -{ - importCallback(GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eDrag); +void DragToolExport( const Callback & importCallback ){ + importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eDrag ); } -void ClipperToolExport(const Callback &importCallback) -{ - importCallback(GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip); +void ClipperToolExport( const Callback & importCallback ){ + importCallback( GlobalSelectionSystem().ManipulatorMode() == SelectionSystem::eClip ); } FreeCaller &), TranslateToolExport> g_translatemode_button_caller; -Callback &)> g_translatemode_button_callback(g_translatemode_button_caller); -ToggleItem g_translatemode_button(g_translatemode_button_callback); +Callback &)> g_translatemode_button_callback( g_translatemode_button_caller ); +ToggleItem g_translatemode_button( g_translatemode_button_callback ); FreeCaller &), RotateToolExport> g_rotatemode_button_caller; -Callback &)> g_rotatemode_button_callback(g_rotatemode_button_caller); -ToggleItem g_rotatemode_button(g_rotatemode_button_callback); +Callback &)> g_rotatemode_button_callback( g_rotatemode_button_caller ); +ToggleItem g_rotatemode_button( g_rotatemode_button_callback ); FreeCaller &), ScaleToolExport> g_scalemode_button_caller; -Callback &)> g_scalemode_button_callback(g_scalemode_button_caller); -ToggleItem g_scalemode_button(g_scalemode_button_callback); +Callback &)> g_scalemode_button_callback( g_scalemode_button_caller ); +ToggleItem g_scalemode_button( g_scalemode_button_callback ); FreeCaller &), DragToolExport> g_dragmode_button_caller; -Callback &)> g_dragmode_button_callback(g_dragmode_button_caller); -ToggleItem g_dragmode_button(g_dragmode_button_callback); +Callback &)> g_dragmode_button_callback( g_dragmode_button_caller ); +ToggleItem g_dragmode_button( g_dragmode_button_callback ); FreeCaller &), ClipperToolExport> g_clipper_button_caller; -Callback &)> g_clipper_button_callback(g_clipper_button_caller); -ToggleItem g_clipper_button(g_clipper_button_callback); +Callback &)> g_clipper_button_callback( g_clipper_button_caller ); +ToggleItem g_clipper_button( g_clipper_button_callback ); -void ToolChanged() -{ - g_translatemode_button.update(); - g_rotatemode_button.update(); - g_scalemode_button.update(); - g_dragmode_button.update(); - g_clipper_button.update(); +void ToolChanged(){ + g_translatemode_button.update(); + g_rotatemode_button.update(); + g_scalemode_button.update(); + g_dragmode_button.update(); + g_clipper_button.update(); } -const char *const c_ResizeMode_status = "QE4 Drag Tool: move and resize objects"; +const char* const c_ResizeMode_status = "QE4 Drag Tool: move and resize objects"; -void DragMode() -{ - if (g_currentToolMode == DragMode && g_defaultToolMode != DragMode) { - g_defaultToolMode(); - } else { - g_currentToolMode = DragMode; - g_currentToolModeSupportsComponentEditing = true; +void DragMode(){ + if ( g_currentToolMode == DragMode && g_defaultToolMode != DragMode ) { + g_defaultToolMode(); + } + else + { + g_currentToolMode = DragMode; + g_currentToolModeSupportsComponentEditing = true; - OnClipMode(false); + OnClipMode( false ); - Sys_Status(c_ResizeMode_status); - GlobalSelectionSystem().SetManipulatorMode(SelectionSystem::eDrag); - ToolChanged(); - ModeChangeNotify(); - } + Sys_Status( c_ResizeMode_status ); + GlobalSelectionSystem().SetManipulatorMode( SelectionSystem::eDrag ); + ToolChanged(); + ModeChangeNotify(); + } } -const char *const c_TranslateMode_status = "Translate Tool: translate objects and components"; +const char* const c_TranslateMode_status = "Translate Tool: translate objects and components"; -void TranslateMode() -{ - if (g_currentToolMode == TranslateMode && g_defaultToolMode != TranslateMode) { - g_defaultToolMode(); - } else { - g_currentToolMode = TranslateMode; - g_currentToolModeSupportsComponentEditing = true; +void TranslateMode(){ + if ( g_currentToolMode == TranslateMode && g_defaultToolMode != TranslateMode ) { + g_defaultToolMode(); + } + else + { + g_currentToolMode = TranslateMode; + g_currentToolModeSupportsComponentEditing = true; - OnClipMode(false); + OnClipMode( false ); - Sys_Status(c_TranslateMode_status); - GlobalSelectionSystem().SetManipulatorMode(SelectionSystem::eTranslate); - ToolChanged(); - ModeChangeNotify(); - } + Sys_Status( c_TranslateMode_status ); + GlobalSelectionSystem().SetManipulatorMode( SelectionSystem::eTranslate ); + ToolChanged(); + ModeChangeNotify(); + } } -const char *const c_RotateMode_status = "Rotate Tool: rotate objects and components"; +const char* const c_RotateMode_status = "Rotate Tool: rotate objects and components"; -void RotateMode() -{ - if (g_currentToolMode == RotateMode && g_defaultToolMode != RotateMode) { - g_defaultToolMode(); - } else { - g_currentToolMode = RotateMode; - g_currentToolModeSupportsComponentEditing = true; +void RotateMode(){ + if ( g_currentToolMode == RotateMode && g_defaultToolMode != RotateMode ) { + g_defaultToolMode(); + } + else + { + g_currentToolMode = RotateMode; + g_currentToolModeSupportsComponentEditing = true; - OnClipMode(false); + OnClipMode( false ); - Sys_Status(c_RotateMode_status); - GlobalSelectionSystem().SetManipulatorMode(SelectionSystem::eRotate); - ToolChanged(); - ModeChangeNotify(); - } + Sys_Status( c_RotateMode_status ); + GlobalSelectionSystem().SetManipulatorMode( SelectionSystem::eRotate ); + ToolChanged(); + ModeChangeNotify(); + } } -const char *const c_ScaleMode_status = "Scale Tool: scale objects and components"; +const char* const c_ScaleMode_status = "Scale Tool: scale objects and components"; -void ScaleMode() -{ - if (g_currentToolMode == ScaleMode && g_defaultToolMode != ScaleMode) { - g_defaultToolMode(); - } else { - g_currentToolMode = ScaleMode; - g_currentToolModeSupportsComponentEditing = true; +void ScaleMode(){ + if ( g_currentToolMode == ScaleMode && g_defaultToolMode != ScaleMode ) { + g_defaultToolMode(); + } + else + { + g_currentToolMode = ScaleMode; + g_currentToolModeSupportsComponentEditing = true; - OnClipMode(false); + OnClipMode( false ); - Sys_Status(c_ScaleMode_status); - GlobalSelectionSystem().SetManipulatorMode(SelectionSystem::eScale); - ToolChanged(); - ModeChangeNotify(); - } + Sys_Status( c_ScaleMode_status ); + GlobalSelectionSystem().SetManipulatorMode( SelectionSystem::eScale ); + ToolChanged(); + ModeChangeNotify(); + } } -const char *const c_ClipperMode_status = "Clipper Tool: apply clip planes to objects"; +const char* const c_ClipperMode_status = "Clipper Tool: apply clip planes to objects"; -void ClipperMode() -{ - if (g_currentToolMode == ClipperMode && g_defaultToolMode != ClipperMode) { - g_defaultToolMode(); - } else { - g_currentToolMode = ClipperMode; - g_currentToolModeSupportsComponentEditing = false; +void ClipperMode(){ + if ( g_currentToolMode == ClipperMode && g_defaultToolMode != ClipperMode ) { + g_defaultToolMode(); + } + else + { + g_currentToolMode = ClipperMode; + g_currentToolModeSupportsComponentEditing = false; - SelectionSystem_DefaultMode(); + SelectionSystem_DefaultMode(); - OnClipMode(true); + OnClipMode( true ); - Sys_Status(c_ClipperMode_status); - GlobalSelectionSystem().SetManipulatorMode(SelectionSystem::eClip); - ToolChanged(); - ModeChangeNotify(); - } + Sys_Status( c_ClipperMode_status ); + GlobalSelectionSystem().SetManipulatorMode( SelectionSystem::eClip ); + ToolChanged(); + ModeChangeNotify(); + } } -void Texdef_Rotate(float angle) -{ - StringOutputStream command; - command << "brushRotateTexture -angle " << angle; - UndoableCommand undo(command.c_str()); - Select_RotateTexture(angle); +void Texdef_Rotate( float angle ){ + StringOutputStream command; + command << "brushRotateTexture -angle " << angle; + UndoableCommand undo( command.c_str() ); + Select_RotateTexture( angle ); } -void Texdef_RotateClockwise() -{ - Texdef_Rotate(static_cast( fabs(g_si_globals.rotate))); +void Texdef_RotateClockwise(){ + Texdef_Rotate( static_cast( fabs( g_si_globals.rotate ) ) ); } -void Texdef_RotateAntiClockwise() -{ - Texdef_Rotate(static_cast( -fabs(g_si_globals.rotate))); +void Texdef_RotateAntiClockwise(){ + Texdef_Rotate( static_cast( -fabs( g_si_globals.rotate ) ) ); } -void Texdef_Scale(float x, float y) -{ - StringOutputStream command; - command << "brushScaleTexture -x " << x << " -y " << y; - UndoableCommand undo(command.c_str()); - Select_ScaleTexture(x, y); +void Texdef_Scale( float x, float y ){ + StringOutputStream command; + command << "brushScaleTexture -x " << x << " -y " << y; + UndoableCommand undo( command.c_str() ); + Select_ScaleTexture( x, y ); } -void Texdef_ScaleUp() -{ - Texdef_Scale(0, g_si_globals.scale[1]); +void Texdef_ScaleUp(){ + Texdef_Scale( 0, g_si_globals.scale[1] ); } -void Texdef_ScaleDown() -{ - Texdef_Scale(0, -g_si_globals.scale[1]); +void Texdef_ScaleDown(){ + Texdef_Scale( 0, -g_si_globals.scale[1] ); } -void Texdef_ScaleLeft() -{ - Texdef_Scale(-g_si_globals.scale[0], 0); +void Texdef_ScaleLeft(){ + Texdef_Scale( -g_si_globals.scale[0],0 ); } -void Texdef_ScaleRight() -{ - Texdef_Scale(g_si_globals.scale[0], 0); +void Texdef_ScaleRight(){ + Texdef_Scale( g_si_globals.scale[0],0 ); } -void Texdef_Shift(float x, float y) -{ - StringOutputStream command; - command << "brushShiftTexture -x " << x << " -y " << y; - UndoableCommand undo(command.c_str()); - Select_ShiftTexture(x, y); +void Texdef_Shift( float x, float y ){ + StringOutputStream command; + command << "brushShiftTexture -x " << x << " -y " << y; + UndoableCommand undo( command.c_str() ); + Select_ShiftTexture( x, y ); } -void Texdef_ShiftLeft() -{ - Texdef_Shift(-g_si_globals.shift[0], 0); +void Texdef_ShiftLeft(){ + Texdef_Shift( -g_si_globals.shift[0], 0 ); } -void Texdef_ShiftRight() -{ - Texdef_Shift(g_si_globals.shift[0], 0); +void Texdef_ShiftRight(){ + Texdef_Shift( g_si_globals.shift[0], 0 ); } -void Texdef_ShiftUp() -{ - Texdef_Shift(0, g_si_globals.shift[1]); +void Texdef_ShiftUp(){ + Texdef_Shift( 0, g_si_globals.shift[1] ); } -void Texdef_ShiftDown() -{ - Texdef_Shift(0, -g_si_globals.shift[1]); +void Texdef_ShiftDown(){ + Texdef_Shift( 0, -g_si_globals.shift[1] ); } -class SnappableSnapToGridSelected : public scene::Graph::Walker { - float m_snap; + +class SnappableSnapToGridSelected : public scene::Graph::Walker +{ +float m_snap; public: - SnappableSnapToGridSelected(float snap) - : m_snap(snap) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - if (path.top().get().visible()) { - Snappable *snappable = Node_getSnappable(path.top()); - if (snappable != 0 - && Instance_getSelectable(instance)->isSelected()) { - snappable->snapto(m_snap); - } - } - return true; - } +SnappableSnapToGridSelected( float snap ) + : m_snap( snap ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get().visible() ) { + Snappable* snappable = Node_getSnappable( path.top() ); + if ( snappable != 0 + && Instance_getSelectable( instance )->isSelected() ) { + snappable->snapto( m_snap ); + } + } + return true; +} }; -void Scene_SnapToGrid_Selected(scene::Graph &graph, float snap) -{ - graph.traverse(SnappableSnapToGridSelected(snap)); +void Scene_SnapToGrid_Selected( scene::Graph& graph, float snap ){ + graph.traverse( SnappableSnapToGridSelected( snap ) ); } -class ComponentSnappableSnapToGridSelected : public scene::Graph::Walker { - float m_snap; +class ComponentSnappableSnapToGridSelected : public scene::Graph::Walker +{ +float m_snap; public: - ComponentSnappableSnapToGridSelected(float snap) - : m_snap(snap) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - if (path.top().get().visible()) { - ComponentSnappable *componentSnappable = Instance_getComponentSnappable(instance); - if (componentSnappable != 0 - && Instance_getSelectable(instance)->isSelected()) { - componentSnappable->snapComponents(m_snap); - } - } - return true; - } +ComponentSnappableSnapToGridSelected( float snap ) + : m_snap( snap ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get().visible() ) { + ComponentSnappable* componentSnappable = Instance_getComponentSnappable( instance ); + if ( componentSnappable != 0 + && Instance_getSelectable( instance )->isSelected() ) { + componentSnappable->snapComponents( m_snap ); + } + } + return true; +} }; -void Scene_SnapToGrid_Component_Selected(scene::Graph &graph, float snap) -{ - graph.traverse(ComponentSnappableSnapToGridSelected(snap)); +void Scene_SnapToGrid_Component_Selected( scene::Graph& graph, float snap ){ + graph.traverse( ComponentSnappableSnapToGridSelected( snap ) ); } -void Selection_SnapToGrid() -{ - StringOutputStream command; - command << "snapSelected -grid " << GetGridSize(); - UndoableCommand undo(command.c_str()); +void Selection_SnapToGrid(){ + StringOutputStream command; + command << "snapSelected -grid " << GetGridSize(); + UndoableCommand undo( command.c_str() ); - if (GlobalSelectionSystem().Mode() == SelectionSystem::eComponent) { - Scene_SnapToGrid_Component_Selected(GlobalSceneGraph(), GetGridSize()); - } else { - Scene_SnapToGrid_Selected(GlobalSceneGraph(), GetGridSize()); - } + if ( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent ) { + Scene_SnapToGrid_Component_Selected( GlobalSceneGraph(), GetGridSize() ); + } + else + { + Scene_SnapToGrid_Selected( GlobalSceneGraph(), GetGridSize() ); + } } -static gint qe_every_second(gpointer data) -{ - GdkModifierType mask; +static gint qe_every_second( gpointer data ){ + GdkModifierType mask; - gdk_window_get_pointer(0, 0, 0, &mask); + gdk_window_get_pointer( 0, 0, 0, &mask ); - if ((mask & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) == 0) { - QE_CheckAutoSave(); - } + if ( ( mask & ( GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK ) ) == 0 ) { + QE_CheckAutoSave(); + } - return TRUE; + return TRUE; } guint s_qe_every_second_id = 0; -void EverySecondTimer_enable() -{ - if (s_qe_every_second_id == 0) { - s_qe_every_second_id = g_timeout_add(1000, qe_every_second, 0); - } +void EverySecondTimer_enable(){ + if ( s_qe_every_second_id == 0 ) { + s_qe_every_second_id = g_timeout_add( 1000, qe_every_second, 0 ); + } } -void EverySecondTimer_disable() -{ - if (s_qe_every_second_id != 0) { - g_source_remove(s_qe_every_second_id); - s_qe_every_second_id = 0; - } +void EverySecondTimer_disable(){ + if ( s_qe_every_second_id != 0 ) { + g_source_remove( s_qe_every_second_id ); + s_qe_every_second_id = 0; + } } -gint window_realize_remove_decoration(ui::Widget widget, gpointer data) -{ - gdk_window_set_decorations(gtk_widget_get_window(widget), - (GdkWMDecoration) (GDK_DECOR_ALL | GDK_DECOR_MENU | GDK_DECOR_MINIMIZE | - GDK_DECOR_MAXIMIZE)); - return FALSE; +gint window_realize_remove_decoration( ui::Widget widget, gpointer data ){ + gdk_window_set_decorations( gtk_widget_get_window(widget), (GdkWMDecoration)( GDK_DECOR_ALL | GDK_DECOR_MENU | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE ) ); + return FALSE; } -class WaitDialog { +class WaitDialog +{ public: - ui::Window m_window{ui::null}; - ui::Label m_label{ui::null}; +ui::Window m_window{ui::null}; +ui::Label m_label{ui::null}; }; -WaitDialog create_wait_dialog(const char *title, const char *text) -{ - WaitDialog dialog; +WaitDialog create_wait_dialog( const char* title, const char* text ){ + WaitDialog dialog; - dialog.m_window = MainFrame_getWindow().create_floating_window(title); - gtk_window_set_resizable(dialog.m_window, FALSE); - gtk_container_set_border_width(GTK_CONTAINER(dialog.m_window), 0); - gtk_window_set_position(dialog.m_window, GTK_WIN_POS_CENTER_ON_PARENT); + dialog.m_window = MainFrame_getWindow().create_floating_window(title); + gtk_window_set_resizable( dialog.m_window, FALSE ); + gtk_container_set_border_width( GTK_CONTAINER( dialog.m_window ), 0 ); + gtk_window_set_position( dialog.m_window, GTK_WIN_POS_CENTER_ON_PARENT ); - dialog.m_window.connect("realize", G_CALLBACK(window_realize_remove_decoration), 0); + dialog.m_window.connect( "realize", G_CALLBACK( window_realize_remove_decoration ), 0 ); - { - dialog.m_label = ui::Label(text); - gtk_misc_set_alignment(GTK_MISC(dialog.m_label), 0.0, 0.5); - gtk_label_set_justify(dialog.m_label, GTK_JUSTIFY_LEFT); - dialog.m_label.show(); - dialog.m_label.dimensions(200, -1); + { + dialog.m_label = ui::Label( text ); + gtk_misc_set_alignment( GTK_MISC( dialog.m_label ), 0.0, 0.5 ); + gtk_label_set_justify( dialog.m_label, GTK_JUSTIFY_LEFT ); + dialog.m_label.show(); + dialog.m_label.dimensions(200, -1); - dialog.m_window.add(dialog.m_label); - } - return dialog; + dialog.m_window.add(dialog.m_label); + } + return dialog; } -namespace { - clock_t g_lastRedrawTime = 0; - const clock_t c_redrawInterval = clock_t(CLOCKS_PER_SEC / 10); +namespace +{ +clock_t g_lastRedrawTime = 0; +const clock_t c_redrawInterval = clock_t( CLOCKS_PER_SEC / 10 ); - bool redrawRequired() - { - clock_t currentTime = std::clock(); - if (currentTime - g_lastRedrawTime >= c_redrawInterval) { - g_lastRedrawTime = currentTime; - return true; - } - return false; - } +bool redrawRequired(){ + clock_t currentTime = std::clock(); + if ( currentTime - g_lastRedrawTime >= c_redrawInterval ) { + g_lastRedrawTime = currentTime; + return true; + } + return false; +} } -bool MainFrame_isActiveApp() -{ - //globalOutputStream() << "listing\n"; - GList *list = gtk_window_list_toplevels(); - for (GList *i = list; i != 0; i = g_list_next(i)) { - //globalOutputStream() << "toplevel.. "; - if (gtk_window_is_active(ui::Window::from(i->data))) { - //globalOutputStream() << "is active\n"; - return true; - } - //globalOutputStream() << "not active\n"; - } - return false; +bool MainFrame_isActiveApp(){ + //globalOutputStream() << "listing\n"; + GList* list = gtk_window_list_toplevels(); + for ( GList* i = list; i != 0; i = g_list_next( i ) ) + { + //globalOutputStream() << "toplevel.. "; + if ( gtk_window_is_active( ui::Window::from( i->data ) ) ) { + //globalOutputStream() << "is active\n"; + return true; + } + //globalOutputStream() << "not active\n"; + } + return false; } typedef std::list StringStack; StringStack g_wait_stack; WaitDialog g_wait; -bool ScreenUpdates_Enabled() -{ - return g_wait_stack.empty(); +bool ScreenUpdates_Enabled(){ + return g_wait_stack.empty(); } -void ScreenUpdates_process() -{ - if (redrawRequired() && g_wait.m_window.visible()) { - ui::process(); - } +void ScreenUpdates_process(){ + if ( redrawRequired() && g_wait.m_window.visible() ) { + ui::process(); + } } -void ScreenUpdates_Disable(const char *message, const char *title) -{ - if (g_wait_stack.empty()) { - EverySecondTimer_disable(); +void ScreenUpdates_Disable( const char* message, const char* title ){ + if ( g_wait_stack.empty() ) { + EverySecondTimer_disable(); - ui::process(); + ui::process(); - bool isActiveApp = MainFrame_isActiveApp(); + bool isActiveApp = MainFrame_isActiveApp(); - g_wait = create_wait_dialog(title, message); - gtk_grab_add(g_wait.m_window); + g_wait = create_wait_dialog( title, message ); + gtk_grab_add( g_wait.m_window ); - if (isActiveApp) { - g_wait.m_window.show(); - ScreenUpdates_process(); - } - } else if (g_wait.m_window.visible()) { - g_wait.m_label.text(message); - ScreenUpdates_process(); - } - g_wait_stack.push_back(message); + if ( isActiveApp ) { + g_wait.m_window.show(); + ScreenUpdates_process(); + } + } + else if ( g_wait.m_window.visible() ) { + g_wait.m_label.text(message); + ScreenUpdates_process(); + } + g_wait_stack.push_back( message ); } -void ScreenUpdates_Enable() -{ - ASSERT_MESSAGE(!ScreenUpdates_Enabled(), "screen updates already enabled"); - g_wait_stack.pop_back(); - if (g_wait_stack.empty()) { - EverySecondTimer_enable(); - //gtk_widget_set_sensitive(MainFrame_getWindow(), TRUE); +void ScreenUpdates_Enable(){ + ASSERT_MESSAGE( !ScreenUpdates_Enabled(), "screen updates already enabled" ); + g_wait_stack.pop_back(); + if ( g_wait_stack.empty() ) { + EverySecondTimer_enable(); + //gtk_widget_set_sensitive(MainFrame_getWindow(), TRUE); + + gtk_grab_remove( g_wait.m_window ); + destroy_floating_window( g_wait.m_window ); + g_wait.m_window = ui::Window{ui::null}; + + //gtk_window_present(MainFrame_getWindow()); + } + else if ( g_wait.m_window.visible() ) { + g_wait.m_label.text(g_wait_stack.back().c_str()); + ScreenUpdates_process(); + } +} + + +void GlobalCamera_UpdateWindow(){ + if ( g_pParentWnd != 0 ) { + CamWnd_Update( *g_pParentWnd->GetCamWnd() ); + } +} + +void XY_UpdateWindow( MainFrame& mainframe ){ + if ( mainframe.GetXYWnd() != 0 ) { + XYWnd_Update( *mainframe.GetXYWnd() ); + } +} + +void XZ_UpdateWindow( MainFrame& mainframe ){ + if ( mainframe.GetXZWnd() != 0 ) { + XYWnd_Update( *mainframe.GetXZWnd() ); + } +} + +void YZ_UpdateWindow( MainFrame& mainframe ){ + if ( mainframe.GetYZWnd() != 0 ) { + XYWnd_Update( *mainframe.GetYZWnd() ); + } +} + +void XY_UpdateAllWindows( MainFrame& mainframe ){ + XY_UpdateWindow( mainframe ); + XZ_UpdateWindow( mainframe ); + YZ_UpdateWindow( mainframe ); +} + +void XY_UpdateAllWindows(){ + if ( g_pParentWnd != 0 ) { + XY_UpdateAllWindows( *g_pParentWnd ); + } +} - gtk_grab_remove(g_wait.m_window); - destroy_floating_window(g_wait.m_window); - g_wait.m_window = ui::Window{ui::null}; +void UpdateAllWindows(){ + GlobalCamera_UpdateWindow(); + XY_UpdateAllWindows(); +} + + +void ModeChangeNotify(){ + SceneChangeNotify(); +} + +void ClipperChangeNotify(){ + GlobalCamera_UpdateWindow(); + XY_UpdateAllWindows(); +} + + +LatchedValue g_Layout_viewStyle( 0, "Window Layout" ); +LatchedValue g_Layout_enableDetachableMenus( true, "Detachable Menus" ); +LatchedValue g_Layout_enablePatchToolbar( true, "Patch Toolbar" ); +LatchedValue g_Layout_enablePluginToolbar( true, "Plugin Toolbar" ); + + +ui::MenuItem create_file_menu(){ + // File menu + auto file_menu_item = new_sub_menu_item_with_mnemonic( "_File" ); + auto menu = ui::Menu::from( gtk_menu_item_get_submenu( file_menu_item ) ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } + + create_menu_item_with_mnemonic( menu, "_New Map", "NewMap" ); + menu_separator( menu ); + +#if 0 + //++timo temporary experimental stuff for sleep mode.. + create_menu_item_with_mnemonic( menu, "_Sleep", "Sleep" ); + menu_separator( menu ); + // end experimental +#endif + + create_menu_item_with_mnemonic( menu, "_Open...", "OpenMap" ); + + create_menu_item_with_mnemonic( menu, "_Import...", "ImportMap" ); + create_menu_item_with_mnemonic( menu, "_Save", "SaveMap" ); + create_menu_item_with_mnemonic( menu, "Save _as...", "SaveMapAs" ); + create_menu_item_with_mnemonic( menu, "_Export selected...", "ExportSelected" ); + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "Save re_gion...", "SaveRegion" ); + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "_Refresh models", "RefreshReferences" ); + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "Pro_ject settings...", "ProjectSettings" ); + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "_Pointfile...", "TogglePointfile" ); + menu_separator( menu ); + MRU_constructMenu( menu ); + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "E_xit", "Exit" ); - //gtk_window_present(MainFrame_getWindow()); - } else if (g_wait.m_window.visible()) { - g_wait.m_label.text(g_wait_stack.back().c_str()); - ScreenUpdates_process(); - } + return file_menu_item; } +ui::MenuItem create_edit_menu(){ + // Edit menu + auto edit_menu_item = new_sub_menu_item_with_mnemonic( "_Edit" ); + auto menu = ui::Menu::from( gtk_menu_item_get_submenu( edit_menu_item ) ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } + create_menu_item_with_mnemonic( menu, "_Undo", "Undo" ); + create_menu_item_with_mnemonic( menu, "_Redo", "Redo" ); + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "_Copy", "Copy" ); + create_menu_item_with_mnemonic( menu, "_Paste", "Paste" ); + create_menu_item_with_mnemonic( menu, "P_aste To Camera", "PasteToCamera" ); + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "_Duplicate", "CloneSelection" ); + create_menu_item_with_mnemonic( menu, "Duplicate, make uni_que", "CloneSelectionAndMakeUnique" ); + create_menu_item_with_mnemonic( menu, "D_elete", "DeleteSelection" ); + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "Pa_rent", "ParentSelection" ); + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "C_lear Selection", "UnSelectSelection" ); + create_menu_item_with_mnemonic( menu, "_Invert Selection", "InvertSelection" ); + create_menu_item_with_mnemonic( menu, "Select i_nside", "SelectInside" ); + create_menu_item_with_mnemonic( menu, "Select _touching", "SelectTouching" ); + + auto convert_menu = create_sub_menu_with_mnemonic( menu, "E_xpand Selection" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( convert_menu ); + } + create_menu_item_with_mnemonic( convert_menu, "To Whole _Entities", "ExpandSelectionToEntities" ); -void GlobalCamera_UpdateWindow() -{ - if (g_pParentWnd != 0) { - CamWnd_Update(*g_pParentWnd->GetCamWnd()); - } -} + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "Pre_ferences...", "Preferences" ); -void XY_UpdateWindow(MainFrame &mainframe) -{ - if (mainframe.GetXYWnd() != 0) { - XYWnd_Update(*mainframe.GetXYWnd()); - } + return edit_menu_item; } -void XZ_UpdateWindow(MainFrame &mainframe) -{ - if (mainframe.GetXZWnd() != 0) { - XYWnd_Update(*mainframe.GetXZWnd()); - } +void fill_view_xy_top_menu( ui::Menu menu ){ + create_check_menu_item_with_mnemonic( menu, "XY (Top) View", "ToggleView" ); } -void YZ_UpdateWindow(MainFrame &mainframe) -{ - if (mainframe.GetYZWnd() != 0) { - XYWnd_Update(*mainframe.GetYZWnd()); - } -} -void XY_UpdateAllWindows(MainFrame &mainframe) -{ - XY_UpdateWindow(mainframe); - XZ_UpdateWindow(mainframe); - YZ_UpdateWindow(mainframe); +void fill_view_yz_side_menu( ui::Menu menu ){ + create_check_menu_item_with_mnemonic( menu, "YZ (Side) View", "ToggleSideView" ); } -void XY_UpdateAllWindows() -{ - if (g_pParentWnd != 0) { - XY_UpdateAllWindows(*g_pParentWnd); - } -} -void UpdateAllWindows() -{ - GlobalCamera_UpdateWindow(); - XY_UpdateAllWindows(); +void fill_view_xz_front_menu( ui::Menu menu ){ + create_check_menu_item_with_mnemonic( menu, "XZ (Front) View", "ToggleFrontView" ); } -void ModeChangeNotify() -{ - SceneChangeNotify(); -} +ui::Widget g_toggle_z_item{ui::null}; +ui::Widget g_toggle_console_item{ui::null}; +ui::Widget g_toggle_entity_item{ui::null}; +ui::Widget g_toggle_entitylist_item{ui::null}; -void ClipperChangeNotify() -{ - GlobalCamera_UpdateWindow(); - XY_UpdateAllWindows(); -} +ui::MenuItem create_view_menu( MainFrame::EViewStyle style ){ + // View menu + auto view_menu_item = new_sub_menu_item_with_mnemonic( "Vie_w" ); + auto menu = ui::Menu::from( gtk_menu_item_get_submenu( view_menu_item ) ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } + if ( style == MainFrame::eFloating ) { + fill_view_camera_menu( menu ); + fill_view_xy_top_menu( menu ); + fill_view_yz_side_menu( menu ); + fill_view_xz_front_menu( menu ); + } + if ( style == MainFrame::eFloating || style == MainFrame::eSplit ) { + create_menu_item_with_mnemonic( menu, "Console View", "ToggleConsole" ); + create_menu_item_with_mnemonic( menu, "Texture Browser", "ToggleTextures" ); + create_menu_item_with_mnemonic( menu, "Entity Inspector", "ToggleEntityInspector" ); + } + else + { + create_menu_item_with_mnemonic( menu, "Entity Inspector", "ViewEntityInfo" ); + } + create_menu_item_with_mnemonic( menu, "_Surface Inspector", "SurfaceInspector" ); + create_menu_item_with_mnemonic( menu, "Entity List", "EntityList" ); -LatchedValue g_Layout_viewStyle(0, "Window Layout"); -LatchedValue g_Layout_enableDetachableMenus(true, "Detachable Menus"); -LatchedValue g_Layout_enablePatchToolbar(true, "Patch Toolbar"); -LatchedValue g_Layout_enablePluginToolbar(true, "Plugin Toolbar"); + menu_separator( menu ); + { + auto camera_menu = create_sub_menu_with_mnemonic( menu, "Camera" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( camera_menu ); + } + create_menu_item_with_mnemonic( camera_menu, "_Center", "CenterView" ); + create_menu_item_with_mnemonic( camera_menu, "_Up Floor", "UpFloor" ); + create_menu_item_with_mnemonic( camera_menu, "_Down Floor", "DownFloor" ); + menu_separator( camera_menu ); + create_menu_item_with_mnemonic( camera_menu, "Far Clip Plane In", "CubicClipZoomIn" ); + create_menu_item_with_mnemonic( camera_menu, "Far Clip Plane Out", "CubicClipZoomOut" ); + menu_separator( camera_menu ); + create_menu_item_with_mnemonic( camera_menu, "Next leak spot", "NextLeakSpot" ); + create_menu_item_with_mnemonic( camera_menu, "Previous leak spot", "PrevLeakSpot" ); + menu_separator( camera_menu ); + create_menu_item_with_mnemonic( camera_menu, "Look Through Selected", "LookThroughSelected" ); + create_menu_item_with_mnemonic( camera_menu, "Look Through Camera", "LookThroughCamera" ); + } + menu_separator( menu ); + { + auto orthographic_menu = create_sub_menu_with_mnemonic( menu, "Orthographic" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( orthographic_menu ); + } + if ( style == MainFrame::eRegular || style == MainFrame::eRegularLeft || style == MainFrame::eFloating ) { + create_menu_item_with_mnemonic( orthographic_menu, "_Next (XY, YZ, XY)", "NextView" ); + create_menu_item_with_mnemonic( orthographic_menu, "XY (Top)", "ViewTop" ); + create_menu_item_with_mnemonic( orthographic_menu, "YZ", "ViewSide" ); + create_menu_item_with_mnemonic( orthographic_menu, "XZ", "ViewFront" ); + menu_separator( orthographic_menu ); + } + create_menu_item_with_mnemonic( orthographic_menu, "_XY 100%", "Zoom100" ); + create_menu_item_with_mnemonic( orthographic_menu, "XY Zoom _In", "ZoomIn" ); + create_menu_item_with_mnemonic( orthographic_menu, "XY Zoom _Out", "ZoomOut" ); + } -ui::MenuItem create_file_menu() -{ - // File menu - auto file_menu_item = new_sub_menu_item_with_mnemonic("_File"); - auto menu = ui::Menu::from(gtk_menu_item_get_submenu(file_menu_item)); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } + menu_separator( menu ); - create_menu_item_with_mnemonic(menu, "_New Map", "NewMap"); - menu_separator(menu); + { + auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Show" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu_in_menu ); + } + create_check_menu_item_with_mnemonic( menu_in_menu, "Show _Angles", "ShowAngles" ); + create_check_menu_item_with_mnemonic( menu_in_menu, "Show _Names", "ShowNames" ); + create_check_menu_item_with_mnemonic( menu_in_menu, "Show Blocks", "ShowBlocks" ); + create_check_menu_item_with_mnemonic( menu_in_menu, "Show C_oordinates", "ShowCoordinates" ); + create_check_menu_item_with_mnemonic( menu_in_menu, "Show Window Outline", "ShowWindowOutline" ); + create_check_menu_item_with_mnemonic( menu_in_menu, "Show Axes", "ShowAxes" ); + create_check_menu_item_with_mnemonic( menu_in_menu, "Show Workzone", "ShowWorkzone" ); + create_check_menu_item_with_mnemonic( menu_in_menu, "Show Stats", "ShowStats" ); + } -#if 0 - //++timo temporary experimental stuff for sleep mode.. - create_menu_item_with_mnemonic( menu, "_Sleep", "Sleep" ); + { + auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Filter" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu_in_menu ); + } + Filters_constructMenu( menu_in_menu ); + } menu_separator( menu ); - // end experimental -#endif - - create_menu_item_with_mnemonic(menu, "_Open...", "OpenMap"); - - create_menu_item_with_mnemonic(menu, "_Import...", "ImportMap"); - create_menu_item_with_mnemonic(menu, "_Save", "SaveMap"); - create_menu_item_with_mnemonic(menu, "Save _as...", "SaveMapAs"); - create_menu_item_with_mnemonic(menu, "_Export selected...", "ExportSelected"); - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "Save re_gion...", "SaveRegion"); - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "_Refresh models", "RefreshReferences"); - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "Pro_ject settings...", "ProjectSettings"); - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "_Pointfile...", "TogglePointfile"); - menu_separator(menu); - MRU_constructMenu(menu); - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "E_xit", "Exit"); - - return file_menu_item; -} - -ui::MenuItem create_edit_menu() -{ - // Edit menu - auto edit_menu_item = new_sub_menu_item_with_mnemonic("_Edit"); - auto menu = ui::Menu::from(gtk_menu_item_get_submenu(edit_menu_item)); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } - create_menu_item_with_mnemonic(menu, "_Undo", "Undo"); - create_menu_item_with_mnemonic(menu, "_Redo", "Redo"); - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "_Copy", "Copy"); - create_menu_item_with_mnemonic(menu, "_Paste", "Paste"); - create_menu_item_with_mnemonic(menu, "P_aste To Camera", "PasteToCamera"); - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "_Duplicate", "CloneSelection"); - create_menu_item_with_mnemonic(menu, "Duplicate, make uni_que", "CloneSelectionAndMakeUnique"); - create_menu_item_with_mnemonic(menu, "D_elete", "DeleteSelection"); - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "Pa_rent", "ParentSelection"); - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "C_lear Selection", "UnSelectSelection"); - create_menu_item_with_mnemonic(menu, "_Invert Selection", "InvertSelection"); - create_menu_item_with_mnemonic(menu, "Select i_nside", "SelectInside"); - create_menu_item_with_mnemonic(menu, "Select _touching", "SelectTouching"); - - auto convert_menu = create_sub_menu_with_mnemonic(menu, "E_xpand Selection"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(convert_menu); - } - create_menu_item_with_mnemonic(convert_menu, "To Whole _Entities", "ExpandSelectionToEntities"); - - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "Pre_ferences...", "Preferences"); - - return edit_menu_item; -} - -void fill_view_xy_top_menu(ui::Menu menu) -{ - create_check_menu_item_with_mnemonic(menu, "XY (Top) View", "ToggleView"); -} + { + auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Hide/Show" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu_in_menu ); + } + create_menu_item_with_mnemonic( menu_in_menu, "Hide Selected", "HideSelected" ); + create_menu_item_with_mnemonic( menu_in_menu, "Show Hidden", "ShowHidden" ); + } + menu_separator( menu ); + { + auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Region" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu_in_menu ); + } + create_menu_item_with_mnemonic( menu_in_menu, "_Off", "RegionOff" ); + create_menu_item_with_mnemonic( menu_in_menu, "_Set XY", "RegionSetXY" ); + create_menu_item_with_mnemonic( menu_in_menu, "Set _Brush", "RegionSetBrush" ); + create_menu_item_with_mnemonic( menu_in_menu, "Set Se_lected Brushes", "RegionSetSelection" ); + } + command_connect_accelerator( "CenterXYView" ); -void fill_view_yz_side_menu(ui::Menu menu) -{ - create_check_menu_item_with_mnemonic(menu, "YZ (Side) View", "ToggleSideView"); + return view_menu_item; } +ui::MenuItem create_selection_menu(){ + // Selection menu + auto selection_menu_item = new_sub_menu_item_with_mnemonic( "M_odify" ); + auto menu = ui::Menu::from( gtk_menu_item_get_submenu( selection_menu_item ) ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } -void fill_view_xz_front_menu(ui::Menu menu) -{ - create_check_menu_item_with_mnemonic(menu, "XZ (Front) View", "ToggleFrontView"); -} + { + auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Components" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu_in_menu ); + } + create_check_menu_item_with_mnemonic( menu_in_menu, "_Edges", "DragEdges" ); + create_check_menu_item_with_mnemonic( menu_in_menu, "_Vertices", "DragVertices" ); + create_check_menu_item_with_mnemonic( menu_in_menu, "_Faces", "DragFaces" ); + } + menu_separator( menu ); -ui::Widget g_toggle_z_item{ui::null}; -ui::Widget g_toggle_console_item{ui::null}; -ui::Widget g_toggle_entity_item{ui::null}; -ui::Widget g_toggle_entitylist_item{ui::null}; + { + auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Nudge" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu_in_menu ); + } + create_menu_item_with_mnemonic( menu_in_menu, "Nudge Left", "SelectNudgeLeft" ); + create_menu_item_with_mnemonic( menu_in_menu, "Nudge Right", "SelectNudgeRight" ); + create_menu_item_with_mnemonic( menu_in_menu, "Nudge Up", "SelectNudgeUp" ); + create_menu_item_with_mnemonic( menu_in_menu, "Nudge Down", "SelectNudgeDown" ); + } + { + auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Rotate" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu_in_menu ); + } + create_menu_item_with_mnemonic( menu_in_menu, "Rotate X", "RotateSelectionX" ); + create_menu_item_with_mnemonic( menu_in_menu, "Rotate Y", "RotateSelectionY" ); + create_menu_item_with_mnemonic( menu_in_menu, "Rotate Z", "RotateSelectionZ" ); + } + { + auto menu_in_menu = create_sub_menu_with_mnemonic( menu, "Flip" ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu_in_menu ); + } + create_menu_item_with_mnemonic( menu_in_menu, "Flip _X", "MirrorSelectionX" ); + create_menu_item_with_mnemonic( menu_in_menu, "Flip _Y", "MirrorSelectionY" ); + create_menu_item_with_mnemonic( menu_in_menu, "Flip _Z", "MirrorSelectionZ" ); + } + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "Arbitrary rotation...", "ArbitraryRotation" ); + create_menu_item_with_mnemonic( menu, "Arbitrary scale...", "ArbitraryScale" ); -ui::MenuItem create_view_menu(MainFrame::EViewStyle style) -{ - // View menu - auto view_menu_item = new_sub_menu_item_with_mnemonic("Vie_w"); - auto menu = ui::Menu::from(gtk_menu_item_get_submenu(view_menu_item)); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } - - if (style == MainFrame::eFloating) { - fill_view_camera_menu(menu); - fill_view_xy_top_menu(menu); - fill_view_yz_side_menu(menu); - fill_view_xz_front_menu(menu); - } - if (style == MainFrame::eFloating || style == MainFrame::eSplit) { - create_menu_item_with_mnemonic(menu, "Console View", "ToggleConsole"); - create_menu_item_with_mnemonic(menu, "Texture Browser", "ToggleTextures"); - create_menu_item_with_mnemonic(menu, "Entity Inspector", "ToggleEntityInspector"); - } else { - create_menu_item_with_mnemonic(menu, "Entity Inspector", "ViewEntityInfo"); - } - create_menu_item_with_mnemonic(menu, "_Surface Inspector", "SurfaceInspector"); - create_menu_item_with_mnemonic(menu, "Entity List", "EntityList"); - - menu_separator(menu); - { - auto camera_menu = create_sub_menu_with_mnemonic(menu, "Camera"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(camera_menu); - } - create_menu_item_with_mnemonic(camera_menu, "_Center", "CenterView"); - create_menu_item_with_mnemonic(camera_menu, "_Up Floor", "UpFloor"); - create_menu_item_with_mnemonic(camera_menu, "_Down Floor", "DownFloor"); - menu_separator(camera_menu); - create_menu_item_with_mnemonic(camera_menu, "Far Clip Plane In", "CubicClipZoomIn"); - create_menu_item_with_mnemonic(camera_menu, "Far Clip Plane Out", "CubicClipZoomOut"); - menu_separator(camera_menu); - create_menu_item_with_mnemonic(camera_menu, "Next leak spot", "NextLeakSpot"); - create_menu_item_with_mnemonic(camera_menu, "Previous leak spot", "PrevLeakSpot"); - menu_separator(camera_menu); - create_menu_item_with_mnemonic(camera_menu, "Look Through Selected", "LookThroughSelected"); - create_menu_item_with_mnemonic(camera_menu, "Look Through Camera", "LookThroughCamera"); - } - menu_separator(menu); - { - auto orthographic_menu = create_sub_menu_with_mnemonic(menu, "Orthographic"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(orthographic_menu); - } - if (style == MainFrame::eRegular || style == MainFrame::eRegularLeft || style == MainFrame::eFloating) { - create_menu_item_with_mnemonic(orthographic_menu, "_Next (XY, YZ, XY)", "NextView"); - create_menu_item_with_mnemonic(orthographic_menu, "XY (Top)", "ViewTop"); - create_menu_item_with_mnemonic(orthographic_menu, "YZ", "ViewSide"); - create_menu_item_with_mnemonic(orthographic_menu, "XZ", "ViewFront"); - menu_separator(orthographic_menu); - } - - create_menu_item_with_mnemonic(orthographic_menu, "_XY 100%", "Zoom100"); - create_menu_item_with_mnemonic(orthographic_menu, "XY Zoom _In", "ZoomIn"); - create_menu_item_with_mnemonic(orthographic_menu, "XY Zoom _Out", "ZoomOut"); - } - - menu_separator(menu); - - { - auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Show"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu_in_menu); - } - create_check_menu_item_with_mnemonic(menu_in_menu, "Show _Angles", "ShowAngles"); - create_check_menu_item_with_mnemonic(menu_in_menu, "Show _Names", "ShowNames"); - create_check_menu_item_with_mnemonic(menu_in_menu, "Show Blocks", "ShowBlocks"); - create_check_menu_item_with_mnemonic(menu_in_menu, "Show C_oordinates", "ShowCoordinates"); - create_check_menu_item_with_mnemonic(menu_in_menu, "Show Window Outline", "ShowWindowOutline"); - create_check_menu_item_with_mnemonic(menu_in_menu, "Show Axes", "ShowAxes"); - create_check_menu_item_with_mnemonic(menu_in_menu, "Show Workzone", "ShowWorkzone"); - create_check_menu_item_with_mnemonic(menu_in_menu, "Show Stats", "ShowStats"); - } - - { - auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Filter"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu_in_menu); - } - Filters_constructMenu(menu_in_menu); - } - menu_separator(menu); - { - auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Hide/Show"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu_in_menu); - } - create_menu_item_with_mnemonic(menu_in_menu, "Hide Selected", "HideSelected"); - create_menu_item_with_mnemonic(menu_in_menu, "Show Hidden", "ShowHidden"); - } - menu_separator(menu); - { - auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Region"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu_in_menu); - } - create_menu_item_with_mnemonic(menu_in_menu, "_Off", "RegionOff"); - create_menu_item_with_mnemonic(menu_in_menu, "_Set XY", "RegionSetXY"); - create_menu_item_with_mnemonic(menu_in_menu, "Set _Brush", "RegionSetBrush"); - create_menu_item_with_mnemonic(menu_in_menu, "Set Se_lected Brushes", "RegionSetSelection"); - } - - command_connect_accelerator("CenterXYView"); - - return view_menu_item; -} - -ui::MenuItem create_selection_menu() -{ - // Selection menu - auto selection_menu_item = new_sub_menu_item_with_mnemonic("M_odify"); - auto menu = ui::Menu::from(gtk_menu_item_get_submenu(selection_menu_item)); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } - - { - auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Components"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu_in_menu); - } - create_check_menu_item_with_mnemonic(menu_in_menu, "_Edges", "DragEdges"); - create_check_menu_item_with_mnemonic(menu_in_menu, "_Vertices", "DragVertices"); - create_check_menu_item_with_mnemonic(menu_in_menu, "_Faces", "DragFaces"); - } - - menu_separator(menu); - - { - auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Nudge"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu_in_menu); - } - create_menu_item_with_mnemonic(menu_in_menu, "Nudge Left", "SelectNudgeLeft"); - create_menu_item_with_mnemonic(menu_in_menu, "Nudge Right", "SelectNudgeRight"); - create_menu_item_with_mnemonic(menu_in_menu, "Nudge Up", "SelectNudgeUp"); - create_menu_item_with_mnemonic(menu_in_menu, "Nudge Down", "SelectNudgeDown"); - } - { - auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Rotate"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu_in_menu); - } - create_menu_item_with_mnemonic(menu_in_menu, "Rotate X", "RotateSelectionX"); - create_menu_item_with_mnemonic(menu_in_menu, "Rotate Y", "RotateSelectionY"); - create_menu_item_with_mnemonic(menu_in_menu, "Rotate Z", "RotateSelectionZ"); - } - { - auto menu_in_menu = create_sub_menu_with_mnemonic(menu, "Flip"); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu_in_menu); - } - create_menu_item_with_mnemonic(menu_in_menu, "Flip _X", "MirrorSelectionX"); - create_menu_item_with_mnemonic(menu_in_menu, "Flip _Y", "MirrorSelectionY"); - create_menu_item_with_mnemonic(menu_in_menu, "Flip _Z", "MirrorSelectionZ"); - } - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "Arbitrary rotation...", "ArbitraryRotation"); - create_menu_item_with_mnemonic(menu, "Arbitrary scale...", "ArbitraryScale"); - - return selection_menu_item; -} - -ui::MenuItem create_bsp_menu() -{ - // BSP menu - auto bsp_menu_item = new_sub_menu_item_with_mnemonic("_Build"); - auto menu = ui::Menu::from(gtk_menu_item_get_submenu(bsp_menu_item)); + return selection_menu_item; +} + +ui::MenuItem create_bsp_menu(){ + // BSP menu + auto bsp_menu_item = new_sub_menu_item_with_mnemonic( "_Build" ); + auto menu = ui::Menu::from( gtk_menu_item_get_submenu( bsp_menu_item ) ); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } - create_menu_item_with_mnemonic(menu, "Customize...", "BuildMenuCustomize"); + create_menu_item_with_mnemonic( menu, "Customize...", "BuildMenuCustomize" ); - menu_separator(menu); + menu_separator( menu ); - Build_constructMenu(menu); + Build_constructMenu( menu ); - g_bsp_menu = menu; + g_bsp_menu = menu; - return bsp_menu_item; + return bsp_menu_item; } -ui::MenuItem create_grid_menu() -{ - // Grid menu - auto grid_menu_item = new_sub_menu_item_with_mnemonic("_Grid"); - auto menu = ui::Menu::from(gtk_menu_item_get_submenu(grid_menu_item)); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } +ui::MenuItem create_grid_menu(){ + // Grid menu + auto grid_menu_item = new_sub_menu_item_with_mnemonic( "_Grid" ); + auto menu = ui::Menu::from( gtk_menu_item_get_submenu( grid_menu_item ) ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } - Grid_constructMenu(menu); + Grid_constructMenu( menu ); - return grid_menu_item; + return grid_menu_item; } -ui::MenuItem create_misc_menu() -{ - // Misc menu - auto misc_menu_item = new_sub_menu_item_with_mnemonic("M_isc"); - auto menu = ui::Menu::from(gtk_menu_item_get_submenu(misc_menu_item)); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } +ui::MenuItem create_misc_menu(){ + // Misc menu + auto misc_menu_item = new_sub_menu_item_with_mnemonic( "M_isc" ); + auto menu = ui::Menu::from( gtk_menu_item_get_submenu( misc_menu_item ) ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } #if 0 - create_menu_item_with_mnemonic( menu, "_Benchmark", makeCallbackF(GlobalCamera_Benchmark) ); + create_menu_item_with_mnemonic( menu, "_Benchmark", makeCallbackF(GlobalCamera_Benchmark) ); #endif menu.add(create_colours_menu()); - create_menu_item_with_mnemonic(menu, "Find brush...", "FindBrush"); - create_menu_item_with_mnemonic(menu, "Map Info...", "MapInfo"); - // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=394 + create_menu_item_with_mnemonic( menu, "Find brush...", "FindBrush" ); + create_menu_item_with_mnemonic( menu, "Map Info...", "MapInfo" ); + // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=394 // create_menu_item_with_mnemonic(menu, "_Print XY View", FreeCaller()); - create_menu_item_with_mnemonic(menu, "_Background select", makeCallbackF(WXY_BackgroundSelect)); - return misc_menu_item; + create_menu_item_with_mnemonic( menu, "_Background select", makeCallbackF(WXY_BackgroundSelect) ); + return misc_menu_item; } -ui::MenuItem create_entity_menu() -{ - // Brush menu - auto entity_menu_item = new_sub_menu_item_with_mnemonic("E_ntity"); - auto menu = ui::Menu::from(gtk_menu_item_get_submenu(entity_menu_item)); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } +ui::MenuItem create_entity_menu(){ + // Brush menu + auto entity_menu_item = new_sub_menu_item_with_mnemonic( "E_ntity" ); + auto menu = ui::Menu::from( gtk_menu_item_get_submenu( entity_menu_item ) ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } - Entity_constructMenu(menu); + Entity_constructMenu( menu ); - return entity_menu_item; + return entity_menu_item; } -ui::MenuItem create_brush_menu() -{ - // Brush menu - auto brush_menu_item = new_sub_menu_item_with_mnemonic("B_rush"); - auto menu = ui::Menu::from(gtk_menu_item_get_submenu(brush_menu_item)); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } +ui::MenuItem create_brush_menu(){ + // Brush menu + auto brush_menu_item = new_sub_menu_item_with_mnemonic( "B_rush" ); + auto menu = ui::Menu::from( gtk_menu_item_get_submenu( brush_menu_item ) ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } - Brush_constructMenu(menu); + Brush_constructMenu( menu ); - return brush_menu_item; + return brush_menu_item; } -ui::MenuItem create_patch_menu() -{ - // Curve menu - auto patch_menu_item = new_sub_menu_item_with_mnemonic("_Curve"); - auto menu = ui::Menu::from(gtk_menu_item_get_submenu(patch_menu_item)); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } +ui::MenuItem create_patch_menu(){ + // Curve menu + auto patch_menu_item = new_sub_menu_item_with_mnemonic( "_Curve" ); + auto menu = ui::Menu::from( gtk_menu_item_get_submenu( patch_menu_item ) ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } - Patch_constructMenu(menu); + Patch_constructMenu( menu ); - return patch_menu_item; + return patch_menu_item; } -ui::MenuItem create_help_menu() -{ - // Help menu - auto help_menu_item = new_sub_menu_item_with_mnemonic("_Help"); - auto menu = ui::Menu::from(gtk_menu_item_get_submenu(help_menu_item)); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } +ui::MenuItem create_help_menu(){ + // Help menu + auto help_menu_item = new_sub_menu_item_with_mnemonic( "_Help" ); + auto menu = ui::Menu::from( gtk_menu_item_get_submenu( help_menu_item ) ); + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } - create_menu_item_with_mnemonic(menu, "Manual", "OpenManual"); + create_menu_item_with_mnemonic( menu, "Manual", "OpenManual" ); - // this creates all the per-game drop downs for the game pack helps - // it will take care of hooking the Sys_OpenURL calls etc. - create_game_help_menu(menu); + // this creates all the per-game drop downs for the game pack helps + // it will take care of hooking the Sys_OpenURL calls etc. + create_game_help_menu( menu ); - create_menu_item_with_mnemonic(menu, "Bug report", makeCallbackF(OpenBugReportURL)); - create_menu_item_with_mnemonic(menu, "Shortcuts list", makeCallbackF(DoCommandListDlg)); - create_menu_item_with_mnemonic(menu, "_About", makeCallbackF(DoAbout)); + create_menu_item_with_mnemonic( menu, "Bug report", makeCallbackF(OpenBugReportURL) ); + create_menu_item_with_mnemonic( menu, "Shortcuts list", makeCallbackF(DoCommandListDlg) ); + create_menu_item_with_mnemonic( menu, "_About", makeCallbackF(DoAbout) ); - return help_menu_item; + return help_menu_item; } -ui::MenuBar create_main_menu(MainFrame::EViewStyle style) -{ - auto menu_bar = ui::MenuBar::from(gtk_menu_bar_new()); - menu_bar.show(); +ui::MenuBar create_main_menu( MainFrame::EViewStyle style ){ + auto menu_bar = ui::MenuBar::from( gtk_menu_bar_new() ); + menu_bar.show(); - menu_bar.add(create_file_menu()); - menu_bar.add(create_edit_menu()); - menu_bar.add(create_view_menu(style)); - menu_bar.add(create_selection_menu()); - menu_bar.add(create_bsp_menu()); - menu_bar.add(create_grid_menu()); - menu_bar.add(create_misc_menu()); - menu_bar.add(create_entity_menu()); - menu_bar.add(create_brush_menu()); - menu_bar.add(create_patch_menu()); - menu_bar.add(create_plugins_menu()); - menu_bar.add(create_help_menu()); + menu_bar.add(create_file_menu()); + menu_bar.add(create_edit_menu()); + menu_bar.add(create_view_menu(style)); + menu_bar.add(create_selection_menu()); + menu_bar.add(create_bsp_menu()); + menu_bar.add(create_grid_menu()); + menu_bar.add(create_misc_menu()); + menu_bar.add(create_entity_menu()); + menu_bar.add(create_brush_menu()); + menu_bar.add(create_patch_menu()); + menu_bar.add(create_plugins_menu()); + menu_bar.add(create_help_menu()); - return menu_bar; + return menu_bar; } -void PatchInspector_registerShortcuts() -{ - command_connect_accelerator("PatchInspector"); +void PatchInspector_registerShortcuts(){ + command_connect_accelerator( "PatchInspector" ); } -void Patch_registerShortcuts() -{ - command_connect_accelerator("InvertCurveTextureX"); - command_connect_accelerator("InvertCurveTextureY"); - command_connect_accelerator("PatchInsertInsertColumn"); - command_connect_accelerator("PatchInsertInsertRow"); - command_connect_accelerator("PatchDeleteLastColumn"); - command_connect_accelerator("PatchDeleteLastRow"); - command_connect_accelerator("NaturalizePatch"); - //command_connect_accelerator("CapCurrentCurve"); +void Patch_registerShortcuts(){ + command_connect_accelerator( "InvertCurveTextureX" ); + command_connect_accelerator( "InvertCurveTextureY" ); + command_connect_accelerator( "PatchInsertInsertColumn" ); + command_connect_accelerator( "PatchInsertInsertRow" ); + command_connect_accelerator( "PatchDeleteLastColumn" ); + command_connect_accelerator( "PatchDeleteLastRow" ); + command_connect_accelerator( "NaturalizePatch" ); + //command_connect_accelerator("CapCurrentCurve"); } -void Manipulators_registerShortcuts() -{ - toggle_add_accelerator("MouseRotate"); - toggle_add_accelerator("MouseTranslate"); - toggle_add_accelerator("MouseScale"); - toggle_add_accelerator("MouseDrag"); - toggle_add_accelerator("ToggleClipper"); +void Manipulators_registerShortcuts(){ + toggle_add_accelerator( "MouseRotate" ); + toggle_add_accelerator( "MouseTranslate" ); + toggle_add_accelerator( "MouseScale" ); + toggle_add_accelerator( "MouseDrag" ); + toggle_add_accelerator( "ToggleClipper" ); } -void TexdefNudge_registerShortcuts() -{ - command_connect_accelerator("TexRotateClock"); - command_connect_accelerator("TexRotateCounter"); - command_connect_accelerator("TexScaleUp"); - command_connect_accelerator("TexScaleDown"); - command_connect_accelerator("TexScaleLeft"); - command_connect_accelerator("TexScaleRight"); - command_connect_accelerator("TexShiftUp"); - command_connect_accelerator("TexShiftDown"); - command_connect_accelerator("TexShiftLeft"); - command_connect_accelerator("TexShiftRight"); -} - -void SelectNudge_registerShortcuts() -{ - command_connect_accelerator("MoveSelectionDOWN"); - command_connect_accelerator("MoveSelectionUP"); - //command_connect_accelerator("SelectNudgeLeft"); - //command_connect_accelerator("SelectNudgeRight"); - //command_connect_accelerator("SelectNudgeUp"); - //command_connect_accelerator("SelectNudgeDown"); +void TexdefNudge_registerShortcuts(){ + command_connect_accelerator( "TexRotateClock" ); + command_connect_accelerator( "TexRotateCounter" ); + command_connect_accelerator( "TexScaleUp" ); + command_connect_accelerator( "TexScaleDown" ); + command_connect_accelerator( "TexScaleLeft" ); + command_connect_accelerator( "TexScaleRight" ); + command_connect_accelerator( "TexShiftUp" ); + command_connect_accelerator( "TexShiftDown" ); + command_connect_accelerator( "TexShiftLeft" ); + command_connect_accelerator( "TexShiftRight" ); } -void SnapToGrid_registerShortcuts() -{ - command_connect_accelerator("SnapToGrid"); +void SelectNudge_registerShortcuts(){ + command_connect_accelerator( "MoveSelectionDOWN" ); + command_connect_accelerator( "MoveSelectionUP" ); + //command_connect_accelerator("SelectNudgeLeft"); + //command_connect_accelerator("SelectNudgeRight"); + //command_connect_accelerator("SelectNudgeUp"); + //command_connect_accelerator("SelectNudgeDown"); } -void SelectByType_registerShortcuts() -{ - command_connect_accelerator("SelectAllOfType"); +void SnapToGrid_registerShortcuts(){ + command_connect_accelerator( "SnapToGrid" ); } -void SurfaceInspector_registerShortcuts() -{ - command_connect_accelerator("FitTexture"); +void SelectByType_registerShortcuts(){ + command_connect_accelerator( "SelectAllOfType" ); +} + +void SurfaceInspector_registerShortcuts(){ + command_connect_accelerator( "FitTexture" ); } -void register_shortcuts() -{ - PatchInspector_registerShortcuts(); - Patch_registerShortcuts(); - Grid_registerShortcuts(); - XYWnd_registerShortcuts(); - CamWnd_registerShortcuts(); - Manipulators_registerShortcuts(); - SurfaceInspector_registerShortcuts(); - TexdefNudge_registerShortcuts(); - SelectNudge_registerShortcuts(); - SnapToGrid_registerShortcuts(); - SelectByType_registerShortcuts(); -} - -void File_constructToolbar(ui::Toolbar toolbar) -{ - toolbar_append_button(toolbar, "Open an existing map (CTRL + O)", "file_open.png", "OpenMap"); - toolbar_append_button(toolbar, "Save the active map (CTRL + S)", "file_save.png", "SaveMap"); +void register_shortcuts(){ + PatchInspector_registerShortcuts(); + Patch_registerShortcuts(); + Grid_registerShortcuts(); + XYWnd_registerShortcuts(); + CamWnd_registerShortcuts(); + Manipulators_registerShortcuts(); + SurfaceInspector_registerShortcuts(); + TexdefNudge_registerShortcuts(); + SelectNudge_registerShortcuts(); + SnapToGrid_registerShortcuts(); + SelectByType_registerShortcuts(); } -void UndoRedo_constructToolbar(ui::Toolbar toolbar) -{ - toolbar_append_button(toolbar, "Undo (CTRL + Z)", "undo.png", "Undo"); - toolbar_append_button(toolbar, "Redo (CTRL + Y)", "redo.png", "Redo"); +void File_constructToolbar( ui::Toolbar toolbar ){ + toolbar_append_button( toolbar, "Open an existing map (CTRL + O)", "file_open.png", "OpenMap" ); + toolbar_append_button( toolbar, "Save the active map (CTRL + S)", "file_save.png", "SaveMap" ); } -void RotateFlip_constructToolbar(ui::Toolbar toolbar) -{ - toolbar_append_button(toolbar, "x-axis Flip", "brush_flipx.png", "MirrorSelectionX"); - toolbar_append_button(toolbar, "x-axis Rotate", "brush_rotatex.png", "RotateSelectionX"); - toolbar_append_button(toolbar, "y-axis Flip", "brush_flipy.png", "MirrorSelectionY"); - toolbar_append_button(toolbar, "y-axis Rotate", "brush_rotatey.png", "RotateSelectionY"); - toolbar_append_button(toolbar, "z-axis Flip", "brush_flipz.png", "MirrorSelectionZ"); - toolbar_append_button(toolbar, "z-axis Rotate", "brush_rotatez.png", "RotateSelectionZ"); +void UndoRedo_constructToolbar( ui::Toolbar toolbar ){ + toolbar_append_button( toolbar, "Undo (CTRL + Z)", "undo.png", "Undo" ); + toolbar_append_button( toolbar, "Redo (CTRL + Y)", "redo.png", "Redo" ); } -void Select_constructToolbar(ui::Toolbar toolbar) -{ - toolbar_append_button(toolbar, "Select touching", "selection_selecttouching.png", "SelectTouching"); - toolbar_append_button(toolbar, "Select inside", "selection_selectinside.png", "SelectInside"); +void RotateFlip_constructToolbar( ui::Toolbar toolbar ){ + toolbar_append_button( toolbar, "x-axis Flip", "brush_flipx.png", "MirrorSelectionX" ); + toolbar_append_button( toolbar, "x-axis Rotate", "brush_rotatex.png", "RotateSelectionX" ); + toolbar_append_button( toolbar, "y-axis Flip", "brush_flipy.png", "MirrorSelectionY" ); + toolbar_append_button( toolbar, "y-axis Rotate", "brush_rotatey.png", "RotateSelectionY" ); + toolbar_append_button( toolbar, "z-axis Flip", "brush_flipz.png", "MirrorSelectionZ" ); + toolbar_append_button( toolbar, "z-axis Rotate", "brush_rotatez.png", "RotateSelectionZ" ); } -void CSG_constructToolbar(ui::Toolbar toolbar) -{ - toolbar_append_button(toolbar, "CSG Subtract (SHIFT + U)", "selection_csgsubtract.png", "CSGSubtract"); - toolbar_append_button(toolbar, "CSG Merge (CTRL + U)", "selection_csgmerge.png", "CSGMerge"); - toolbar_append_button(toolbar, "Make Hollow", "selection_makehollow.png", "CSGMakeHollow"); - toolbar_append_button(toolbar, "Make Room", "selection_makeroom.png", "CSGMakeRoom"); +void Select_constructToolbar( ui::Toolbar toolbar ){ + toolbar_append_button( toolbar, "Select touching", "selection_selecttouching.png", "SelectTouching" ); + toolbar_append_button( toolbar, "Select inside", "selection_selectinside.png", "SelectInside" ); } -void ComponentModes_constructToolbar(ui::Toolbar toolbar) -{ - toolbar_append_toggle_button(toolbar, "Select Vertices (V)", "modify_vertices.png", "DragVertices"); - toolbar_append_toggle_button(toolbar, "Select Edges (E)", "modify_edges.png", "DragEdges"); - toolbar_append_toggle_button(toolbar, "Select Faces (F)", "modify_faces.png", "DragFaces"); +void CSG_constructToolbar( ui::Toolbar toolbar ){ + toolbar_append_button( toolbar, "CSG Subtract (SHIFT + U)", "selection_csgsubtract.png", "CSGSubtract" ); + toolbar_append_button( toolbar, "CSG Merge (CTRL + U)", "selection_csgmerge.png", "CSGMerge" ); + toolbar_append_button( toolbar, "Make Hollow", "selection_makehollow.png", "CSGMakeHollow" ); + toolbar_append_button( toolbar, "Make Room", "selection_makeroom.png", "CSGMakeRoom" ); } -void Clipper_constructToolbar(ui::Toolbar toolbar) -{ +void ComponentModes_constructToolbar( ui::Toolbar toolbar ){ + toolbar_append_toggle_button( toolbar, "Select Vertices (V)", "modify_vertices.png", "DragVertices" ); + toolbar_append_toggle_button( toolbar, "Select Edges (E)", "modify_edges.png", "DragEdges" ); + toolbar_append_toggle_button( toolbar, "Select Faces (F)", "modify_faces.png", "DragFaces" ); +} - toolbar_append_toggle_button(toolbar, "Clipper (X)", "view_clipper.png", "ToggleClipper"); +void Clipper_constructToolbar( ui::Toolbar toolbar ){ + + toolbar_append_toggle_button( toolbar, "Clipper (X)", "view_clipper.png", "ToggleClipper" ); } -void XYWnd_constructToolbar(ui::Toolbar toolbar) -{ - toolbar_append_button(toolbar, "Change views", "view_change.png", "NextView"); +void XYWnd_constructToolbar( ui::Toolbar toolbar ){ + toolbar_append_button( toolbar, "Change views", "view_change.png", "NextView" ); } -void Manipulators_constructToolbar(ui::Toolbar toolbar) -{ - toolbar_append_toggle_button(toolbar, "Translate (W)", "select_mousetranslate.png", "MouseTranslate"); - toolbar_append_toggle_button(toolbar, "Rotate (R)", "select_mouserotate.png", "MouseRotate"); - toolbar_append_toggle_button(toolbar, "Scale", "select_mousescale.png", "MouseScale"); - toolbar_append_toggle_button(toolbar, "Resize (Q)", "select_mouseresize.png", "MouseDrag"); +void Manipulators_constructToolbar( ui::Toolbar toolbar ){ + toolbar_append_toggle_button( toolbar, "Translate (W)", "select_mousetranslate.png", "MouseTranslate" ); + toolbar_append_toggle_button( toolbar, "Rotate (R)", "select_mouserotate.png", "MouseRotate" ); + toolbar_append_toggle_button( toolbar, "Scale", "select_mousescale.png", "MouseScale" ); + toolbar_append_toggle_button( toolbar, "Resize (Q)", "select_mouseresize.png", "MouseDrag" ); - Clipper_constructToolbar(toolbar); + Clipper_constructToolbar( toolbar ); } -ui::Toolbar create_main_toolbar(MainFrame::EViewStyle style) -{ - auto toolbar = ui::Toolbar::from(gtk_toolbar_new()); - gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL); - gtk_toolbar_set_style(toolbar, GTK_TOOLBAR_ICONS); +ui::Toolbar create_main_toolbar( MainFrame::EViewStyle style ){ + auto toolbar = ui::Toolbar::from( gtk_toolbar_new() ); + gtk_orientable_set_orientation( GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL ); + gtk_toolbar_set_style( toolbar, GTK_TOOLBAR_ICONS ); - toolbar.show(); + toolbar.show(); - auto space = [&]() { - auto btn = ui::ToolItem::from(gtk_separator_tool_item_new()); - btn.show(); - toolbar.add(btn); - }; + auto space = [&]() { + auto btn = ui::ToolItem::from(gtk_separator_tool_item_new()); + btn.show(); + toolbar.add(btn); + }; - File_constructToolbar(toolbar); + File_constructToolbar( toolbar ); - space(); + space(); - UndoRedo_constructToolbar(toolbar); + UndoRedo_constructToolbar( toolbar ); - space(); + space(); - RotateFlip_constructToolbar(toolbar); + RotateFlip_constructToolbar( toolbar ); - space(); + space(); - Select_constructToolbar(toolbar); + Select_constructToolbar( toolbar ); - space(); + space(); - CSG_constructToolbar(toolbar); + CSG_constructToolbar( toolbar ); - space(); + space(); - ComponentModes_constructToolbar(toolbar); + ComponentModes_constructToolbar( toolbar ); - if (style == MainFrame::eRegular || style == MainFrame::eRegularLeft || style == MainFrame::eFloating) { - space(); + if ( style == MainFrame::eRegular || style == MainFrame::eRegularLeft || style == MainFrame::eFloating ) { + space(); - XYWnd_constructToolbar(toolbar); - } + XYWnd_constructToolbar( toolbar ); + } - space(); + space(); - CamWnd_constructToolbar(toolbar); + CamWnd_constructToolbar( toolbar ); - space(); + space(); - Manipulators_constructToolbar(toolbar); + Manipulators_constructToolbar( toolbar ); - if (g_Layout_enablePatchToolbar.m_value) { - space(); + if ( g_Layout_enablePatchToolbar.m_value ) { + space(); - Patch_constructToolbar(toolbar); - } + Patch_constructToolbar( toolbar ); + } - space(); + space(); - toolbar_append_toggle_button(toolbar, "Texture Lock (SHIFT +T)", "texture_lock.png", "TogTexLock"); + toolbar_append_toggle_button( toolbar, "Texture Lock (SHIFT +T)", "texture_lock.png", "TogTexLock" ); - space(); + space(); - /*auto g_view_entities_button =*/ toolbar_append_button(toolbar, "Entities (N)", "entities.png", - "ToggleEntityInspector"); - auto g_view_console_button = toolbar_append_button(toolbar, "Console (O)", "console.png", "ToggleConsole"); - auto g_view_textures_button = toolbar_append_button(toolbar, "Texture Browser (T)", "texture_browser.png", - "ToggleTextures"); - // TODO: call light inspector - //GtkButton* g_view_lightinspector_button = toolbar_append_button(toolbar, "Light Inspector", "lightinspector.png", "ToggleLightInspector"); + /*auto g_view_entities_button =*/ toolbar_append_button( toolbar, "Entities (N)", "entities.png", "ToggleEntityInspector" ); + auto g_view_console_button = toolbar_append_button( toolbar, "Console (O)", "console.png", "ToggleConsole" ); + auto g_view_textures_button = toolbar_append_button( toolbar, "Texture Browser (T)", "texture_browser.png", "ToggleTextures" ); + // TODO: call light inspector + //GtkButton* g_view_lightinspector_button = toolbar_append_button(toolbar, "Light Inspector", "lightinspector.png", "ToggleLightInspector"); - space(); - /*auto g_refresh_models_button =*/ toolbar_append_button(toolbar, "Refresh Models", "refresh_models.png", - "RefreshReferences"); + space(); + /*auto g_refresh_models_button =*/ toolbar_append_button( toolbar, "Refresh Models", "refresh_models.png", "RefreshReferences" ); - // disable the console and texture button in the regular layouts - if (style == MainFrame::eRegular || style == MainFrame::eRegularLeft) { - gtk_widget_set_sensitive(g_view_console_button, FALSE); - gtk_widget_set_sensitive(g_view_textures_button, FALSE); - } + // disable the console and texture button in the regular layouts + if ( style == MainFrame::eRegular || style == MainFrame::eRegularLeft ) { + gtk_widget_set_sensitive( g_view_console_button , FALSE ); + gtk_widget_set_sensitive( g_view_textures_button , FALSE ); + } - return toolbar; + return toolbar; } -ui::Widget create_main_statusbar(ui::Widget pStatusLabel[c_count_status]) -{ - auto table = ui::Table(1, c_count_status, FALSE); - table.show(); - - { - auto label = ui::Label("Label"); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_misc_set_padding(GTK_MISC(label), 4, 2); - label.show(); - table.attach(label, {0, 1, 0, 1}); - pStatusLabel[c_command_status] = ui::Widget(label); - } - - for (unsigned int i = 1; (int) i < c_count_status; ++i) { - auto frame = ui::Frame(); - frame.show(); - table.attach(frame, {i, i + 1, 0, 1}); - gtk_frame_set_shadow_type(frame, GTK_SHADOW_IN); - - auto label = ui::Label("Label"); - gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_END); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_misc_set_padding(GTK_MISC(label), 4, 2); - label.show(); - frame.add(label); - pStatusLabel[i] = ui::Widget(label); - } - - return ui::Widget(table); +ui::Widget create_main_statusbar( ui::Widget pStatusLabel[c_count_status] ){ + auto table = ui::Table( 1, c_count_status, FALSE ); + table.show(); + + { + auto label = ui::Label( "Label" ); + gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); + gtk_misc_set_padding( GTK_MISC( label ), 4, 2 ); + label.show(); + table.attach(label, {0, 1, 0, 1}); + pStatusLabel[c_command_status] = ui::Widget(label ); + } + + for (unsigned int i = 1; (int) i < c_count_status; ++i) + { + auto frame = ui::Frame(); + frame.show(); + table.attach(frame, {i, i + 1, 0, 1}); + gtk_frame_set_shadow_type( frame, GTK_SHADOW_IN ); + + auto label = ui::Label( "Label" ); + gtk_label_set_ellipsize( label, PANGO_ELLIPSIZE_END ); + gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); + gtk_misc_set_padding( GTK_MISC( label ), 4, 2 ); + label.show(); + frame.add(label); + pStatusLabel[i] = ui::Widget(label ); + } + + return ui::Widget(table ); } #if 0 - WidgetFocusPrinter g_mainframeWidgetFocusPrinter( "mainframe" ); +WidgetFocusPrinter g_mainframeWidgetFocusPrinter( "mainframe" ); class WindowFocusPrinter { @@ -2796,108 +2621,100 @@ WindowFocusPrinter g_mainframeFocusPrinter( "mainframe" ); #endif -class MainWindowActive { - static gboolean notify(ui::Window window, gpointer dummy, MainWindowActive *self) - { - if (g_wait.m_window && gtk_window_is_active(window) && !g_wait.m_window.visible()) { - g_wait.m_window.show(); - } +class MainWindowActive +{ +static gboolean notify( ui::Window window, gpointer dummy, MainWindowActive* self ){ + if ( g_wait.m_window && gtk_window_is_active( window ) && !g_wait.m_window.visible() ) { + g_wait.m_window.show(); + } - return FALSE; - } + return FALSE; +} public: - void connect(ui::Window toplevel_window) - { - toplevel_window.connect("notify::is-active", G_CALLBACK(notify), this); - } +void connect( ui::Window toplevel_window ){ + toplevel_window.connect( "notify::is-active", G_CALLBACK( notify ), this ); +} }; MainWindowActive g_MainWindowActive; -SignalHandlerId XYWindowDestroyed_connect(const SignalHandler &handler) -{ - return g_pParentWnd->GetXYWnd()->onDestroyed.connectFirst(handler); +SignalHandlerId XYWindowDestroyed_connect( const SignalHandler& handler ){ + return g_pParentWnd->GetXYWnd()->onDestroyed.connectFirst( handler ); } -void XYWindowDestroyed_disconnect(SignalHandlerId id) -{ - g_pParentWnd->GetXYWnd()->onDestroyed.disconnect(id); +void XYWindowDestroyed_disconnect( SignalHandlerId id ){ + g_pParentWnd->GetXYWnd()->onDestroyed.disconnect( id ); } -MouseEventHandlerId XYWindowMouseDown_connect(const MouseEventHandler &handler) -{ - return g_pParentWnd->GetXYWnd()->onMouseDown.connectFirst(handler); +MouseEventHandlerId XYWindowMouseDown_connect( const MouseEventHandler& handler ){ + return g_pParentWnd->GetXYWnd()->onMouseDown.connectFirst( handler ); } -void XYWindowMouseDown_disconnect(MouseEventHandlerId id) -{ - g_pParentWnd->GetXYWnd()->onMouseDown.disconnect(id); +void XYWindowMouseDown_disconnect( MouseEventHandlerId id ){ + g_pParentWnd->GetXYWnd()->onMouseDown.disconnect( id ); } // ============================================================================= // MainFrame class -MainFrame *g_pParentWnd = 0; +MainFrame* g_pParentWnd = 0; ui::Window MainFrame_getWindow() { - return g_pParentWnd ? g_pParentWnd->m_window : ui::Window{ui::null}; + return g_pParentWnd ? g_pParentWnd->m_window : ui::Window{ui::null}; } std::vector g_floating_windows; -MainFrame::MainFrame() : m_idleRedrawStatusText(RedrawStatusTextCaller(*this)) -{ - m_pXYWnd = 0; - m_pCamWnd = 0; - m_pZWnd = 0; - m_pYZWnd = 0; - m_pXZWnd = 0; - m_pActiveXY = 0; - - for (auto &n : m_pStatusLabel) { +MainFrame::MainFrame() : m_idleRedrawStatusText( RedrawStatusTextCaller( *this ) ){ + m_pXYWnd = 0; + m_pCamWnd = 0; + m_pZWnd = 0; + m_pYZWnd = 0; + m_pXZWnd = 0; + m_pActiveXY = 0; + + for (auto &n : m_pStatusLabel) { n = NULL; - } + } - m_bSleeping = false; + m_bSleeping = false; - Create(); + Create(); } -MainFrame::~MainFrame() -{ - SaveWindowInfo(); +MainFrame::~MainFrame(){ + SaveWindowInfo(); - m_window.hide(); + m_window.hide(); - Shutdown(); + Shutdown(); - for (std::vector::iterator i = g_floating_windows.begin(); i != g_floating_windows.end(); ++i) { - i->destroy(); - } + for ( std::vector::iterator i = g_floating_windows.begin(); i != g_floating_windows.end(); ++i ) + { + i->destroy(); + } - m_window.destroy(); + m_window.destroy(); } -void MainFrame::SetActiveXY(XYWnd *p) -{ - if (m_pActiveXY) { - m_pActiveXY->SetActive(false); - } +void MainFrame::SetActiveXY( XYWnd* p ){ + if ( m_pActiveXY ) { + m_pActiveXY->SetActive( false ); + } - m_pActiveXY = p; + m_pActiveXY = p; - if (m_pActiveXY) { - m_pActiveXY->SetActive(true); - } + if ( m_pActiveXY ) { + m_pActiveXY->SetActive( true ); + } } -void MainFrame::ReleaseContexts() -{ +void MainFrame::ReleaseContexts(){ #if 0 - if ( m_pXYWnd ) { + if ( m_pXYWnd ) { m_pXYWnd->DestroyContext(); } if ( m_pYZWnd ) { @@ -2918,10 +2735,9 @@ void MainFrame::ReleaseContexts() #endif } -void MainFrame::CreateContexts() -{ +void MainFrame::CreateContexts(){ #if 0 - if ( m_pCamWnd ) { + if ( m_pCamWnd ) { m_pCamWnd->CreateContext(); } if ( m_pXYWnd ) { @@ -2946,10 +2762,9 @@ void MainFrame::CreateContexts() //#define DBG_SLEEP #endif -void MainFrame::OnSleep() -{ +void MainFrame::OnSleep(){ #if 0 - m_bSleeping ^= 1; + m_bSleeping ^= 1; if ( m_bSleeping ) { // useful when trying to debug crashes in the sleep code globalOutputStream() << "Going into sleep mode..\n"; @@ -3001,38 +2816,35 @@ void MainFrame::OnSleep() } -ui::Window create_splash() -{ - auto window = ui::Window(ui::window_type::TOP); - gtk_window_set_decorated(window, false); - gtk_window_set_resizable(window, false); - gtk_window_set_modal(window, true); - gtk_window_set_default_size(window, -1, -1); - gtk_window_set_position(window, GTK_WIN_POS_CENTER); - gtk_container_set_border_width(window, 0); +ui::Window create_splash(){ + auto window = ui::Window( ui::window_type::TOP ); + gtk_window_set_decorated(window, false); + gtk_window_set_resizable(window, false); + gtk_window_set_modal(window, true); + gtk_window_set_default_size( window, -1, -1 ); + gtk_window_set_position( window, GTK_WIN_POS_CENTER ); + gtk_container_set_border_width(window, 0); - auto image = new_local_image("splash.png"); - image.show(); - window.add(image); + auto image = new_local_image( "splash.png" ); + image.show(); + window.add(image); - window.dimensions(-1, -1); - window.show(); + window.dimensions(-1, -1); + window.show(); - return window; + return window; } static ui::Window splash_screen{ui::null}; -void show_splash() -{ - splash_screen = create_splash(); +void show_splash(){ + splash_screen = create_splash(); - ui::process(); + ui::process(); } -void hide_splash() -{ - splash_screen.destroy(); +void hide_splash(){ + splash_screen.destroy(); } WindowPositionTracker g_posCamWnd; @@ -3040,379 +2852,377 @@ WindowPositionTracker g_posXYWnd; WindowPositionTracker g_posXZWnd; WindowPositionTracker g_posYZWnd; -static gint mainframe_delete(ui::Widget widget, GdkEvent *event, gpointer data) -{ - if (ConfirmModified("Exit Radiant")) { - gtk_main_quit(); - } +static gint mainframe_delete( ui::Widget widget, GdkEvent *event, gpointer data ){ + if ( ConfirmModified( "Exit Radiant" ) ) { + gtk_main_quit(); + } - return TRUE; + return TRUE; } -void MainFrame::Create() -{ - ui::Window window = ui::Window(ui::window_type::TOP); +void MainFrame::Create(){ + ui::Window window = ui::Window( ui::window_type::TOP ); - GlobalWindowObservers_connectTopLevel(window); + GlobalWindowObservers_connectTopLevel( window ); - gtk_window_set_transient_for(splash_screen, window); + gtk_window_set_transient_for( splash_screen, window ); #if !GDEF_OS_WINDOWS - { - GdkPixbuf *pixbuf = pixbuf_new_from_file_with_mask("bitmaps/icon.png"); - if (pixbuf != 0) { - gtk_window_set_icon(window, pixbuf); - g_object_unref(pixbuf); - } - } + { + GdkPixbuf* pixbuf = pixbuf_new_from_file_with_mask( "bitmaps/icon.png" ); + if ( pixbuf != 0 ) { + gtk_window_set_icon( window, pixbuf ); + g_object_unref( pixbuf ); + } + } #endif - gtk_widget_add_events(window, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK); - window.connect("delete_event", G_CALLBACK(mainframe_delete), this); + gtk_widget_add_events( window , GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK ); + window.connect( "delete_event", G_CALLBACK( mainframe_delete ), this ); - m_position_tracker.connect(window); + m_position_tracker.connect( window ); #if 0 - g_mainframeWidgetFocusPrinter.connect( window ); + g_mainframeWidgetFocusPrinter.connect( window ); g_mainframeFocusPrinter.connect( window ); #endif - g_MainWindowActive.connect(window); + g_MainWindowActive.connect( window ); - GetPlugInMgr().Init(window); + GetPlugInMgr().Init( window ); - auto vbox = ui::VBox(FALSE, 0); - window.add(vbox); - vbox.show(); + auto vbox = ui::VBox( FALSE, 0 ); + window.add(vbox); + vbox.show(); - global_accel_connect_window(window); + global_accel_connect_window( window ); - m_nCurrentStyle = (EViewStyle) g_Layout_viewStyle.m_value; + m_nCurrentStyle = (EViewStyle)g_Layout_viewStyle.m_value; - register_shortcuts(); + register_shortcuts(); - auto main_menu = create_main_menu(CurrentStyle()); - vbox.pack_start(main_menu, FALSE, FALSE, 0); + auto main_menu = create_main_menu( CurrentStyle() ); + vbox.pack_start( main_menu, FALSE, FALSE, 0 ); - auto main_toolbar = create_main_toolbar(CurrentStyle()); - vbox.pack_start(main_toolbar, FALSE, FALSE, 0); + auto main_toolbar = create_main_toolbar( CurrentStyle() ); + vbox.pack_start( main_toolbar, FALSE, FALSE, 0 ); - auto plugin_toolbar = create_plugin_toolbar(); - if (!g_Layout_enablePluginToolbar.m_value) { - plugin_toolbar.hide(); - } - vbox.pack_start(plugin_toolbar, FALSE, FALSE, 0); + auto plugin_toolbar = create_plugin_toolbar(); + if ( !g_Layout_enablePluginToolbar.m_value ) { + plugin_toolbar.hide(); + } + vbox.pack_start( plugin_toolbar, FALSE, FALSE, 0 ); - ui::Widget main_statusbar = create_main_statusbar(reinterpret_cast(m_pStatusLabel)); - vbox.pack_end(main_statusbar, FALSE, TRUE, 2); + ui::Widget main_statusbar = create_main_statusbar(reinterpret_cast(m_pStatusLabel)); + vbox.pack_end(main_statusbar, FALSE, TRUE, 2); - GroupDialog_constructWindow(window); - g_page_entity = GroupDialog_addPage("Entities", EntityInspector_constructWindow(GroupDialog_getWindow()), - RawStringExportCaller("Entities")); + GroupDialog_constructWindow( window ); + g_page_entity = GroupDialog_addPage( "Entities", EntityInspector_constructWindow( GroupDialog_getWindow() ), RawStringExportCaller( "Entities" ) ); - if (FloatingGroupDialog()) { - g_page_console = GroupDialog_addPage("Console", Console_constructWindow(GroupDialog_getWindow()), - RawStringExportCaller("Console")); - } + if ( FloatingGroupDialog() ) { + g_page_console = GroupDialog_addPage( "Console", Console_constructWindow( GroupDialog_getWindow() ), RawStringExportCaller( "Console" ) ); + } #if GDEF_OS_WINDOWS - if ( g_multimon_globals.m_bStartOnPrimMon ) { + if ( g_multimon_globals.m_bStartOnPrimMon ) { PositionWindowOnPrimaryScreen( g_layout_globals.m_position ); window_set_position( window, g_layout_globals.m_position ); } else #endif - if (g_layout_globals.nState & GDK_WINDOW_STATE_MAXIMIZED) { - gtk_window_maximize(window); - WindowPosition default_position(-1, -1, 640, 480); - window_set_position(window, default_position); - } else { - window_set_position(window, g_layout_globals.m_position); - } - - m_window = window; - - window.show(); - - if (CurrentStyle() == eRegular || CurrentStyle() == eRegularLeft) { - { - ui::Widget vsplit = ui::VPaned(ui::New); - m_vSplit = vsplit; - vbox.pack_start(vsplit, TRUE, TRUE, 0); - vsplit.show(); - - // console - ui::Widget console_window = Console_constructWindow(window); - gtk_paned_pack2(GTK_PANED(vsplit), console_window, FALSE, TRUE); - - { - ui::Widget hsplit = ui::HPaned(ui::New); - hsplit.show(); - m_hSplit = hsplit; - gtk_paned_add1(GTK_PANED(vsplit), hsplit); - - // xy - m_pXYWnd = new XYWnd(); - m_pXYWnd->SetViewType(XY); - ui::Widget xy_window = ui::Widget(create_framed_widget(m_pXYWnd->GetWidget())); - - { - ui::Widget vsplit2 = ui::VPaned(ui::New); - vsplit2.show(); - m_vSplit2 = vsplit2; - - if (CurrentStyle() == eRegular) { - gtk_paned_add1(GTK_PANED(hsplit), xy_window); - gtk_paned_add2(GTK_PANED(hsplit), vsplit2); - } else { - gtk_paned_add1(GTK_PANED(hsplit), vsplit2); - gtk_paned_add2(GTK_PANED(hsplit), xy_window); - } - - - // camera - m_pCamWnd = NewCamWnd(); - GlobalCamera_setCamWnd(*m_pCamWnd); - CamWnd_setParent(*m_pCamWnd, window); - auto camera_window = create_framed_widget(CamWnd_getWidget(*m_pCamWnd)); - - gtk_paned_add1(GTK_PANED(vsplit2), camera_window); - - // textures - auto texture_window = create_framed_widget(TextureBrowser_constructWindow(window)); - - gtk_paned_add2(GTK_PANED(vsplit2), texture_window); - } - } - } - - gtk_paned_set_position(GTK_PANED(m_vSplit), g_layout_globals.nXYHeight); - - if (CurrentStyle() == eRegular) { - gtk_paned_set_position(GTK_PANED(m_hSplit), g_layout_globals.nXYWidth); - } else { - gtk_paned_set_position(GTK_PANED(m_hSplit), g_layout_globals.nCamWidth); - } - - gtk_paned_set_position(GTK_PANED(m_vSplit2), g_layout_globals.nCamHeight); - } else if (CurrentStyle() == eFloating) { - { - ui::Window window = ui::Window(create_persistent_floating_window("Camera", m_window)); - global_accel_connect_window(window); - g_posCamWnd.connect(window); + if ( g_layout_globals.nState & GDK_WINDOW_STATE_MAXIMIZED ) { + gtk_window_maximize( window ); + WindowPosition default_position( -1, -1, 640, 480 ); + window_set_position( window, default_position ); + } + else + { + window_set_position( window, g_layout_globals.m_position ); + } + + m_window = window; + + window.show(); + + if ( CurrentStyle() == eRegular || CurrentStyle() == eRegularLeft ) { + { + ui::Widget vsplit = ui::VPaned(ui::New); + m_vSplit = vsplit; + vbox.pack_start( vsplit, TRUE, TRUE, 0 ); + vsplit.show(); + + // console + ui::Widget console_window = Console_constructWindow( window ); + gtk_paned_pack2( GTK_PANED( vsplit ), console_window, FALSE, TRUE ); + + { + ui::Widget hsplit = ui::HPaned(ui::New); + hsplit.show(); + m_hSplit = hsplit; + gtk_paned_add1( GTK_PANED( vsplit ), hsplit ); + + // xy + m_pXYWnd = new XYWnd(); + m_pXYWnd->SetViewType( XY ); + ui::Widget xy_window = ui::Widget(create_framed_widget( m_pXYWnd->GetWidget( ) )); + + { + ui::Widget vsplit2 = ui::VPaned(ui::New); + vsplit2.show(); + m_vSplit2 = vsplit2; + + if ( CurrentStyle() == eRegular ) { + gtk_paned_add1( GTK_PANED( hsplit ), xy_window ); + gtk_paned_add2( GTK_PANED( hsplit ), vsplit2 ); + } + else + { + gtk_paned_add1( GTK_PANED( hsplit ), vsplit2 ); + gtk_paned_add2( GTK_PANED( hsplit ), xy_window ); + } + + + // camera + m_pCamWnd = NewCamWnd(); + GlobalCamera_setCamWnd( *m_pCamWnd ); + CamWnd_setParent( *m_pCamWnd, window ); + auto camera_window = create_framed_widget( CamWnd_getWidget( *m_pCamWnd ) ); + + gtk_paned_add1( GTK_PANED( vsplit2 ), camera_window ); + + // textures + auto texture_window = create_framed_widget( TextureBrowser_constructWindow( window ) ); + + gtk_paned_add2( GTK_PANED( vsplit2 ), texture_window ); + } + } + } + + gtk_paned_set_position( GTK_PANED( m_vSplit ), g_layout_globals.nXYHeight ); - window.show(); + if ( CurrentStyle() == eRegular ) { + gtk_paned_set_position( GTK_PANED( m_hSplit ), g_layout_globals.nXYWidth ); + } + else + { + gtk_paned_set_position( GTK_PANED( m_hSplit ), g_layout_globals.nCamWidth ); + } + + gtk_paned_set_position( GTK_PANED( m_vSplit2 ), g_layout_globals.nCamHeight ); + } + else if ( CurrentStyle() == eFloating ) { + { + ui::Window window = ui::Window(create_persistent_floating_window( "Camera", m_window )); + global_accel_connect_window( window ); + g_posCamWnd.connect( window ); + + window.show(); + + m_pCamWnd = NewCamWnd(); + GlobalCamera_setCamWnd( *m_pCamWnd ); - m_pCamWnd = NewCamWnd(); - GlobalCamera_setCamWnd(*m_pCamWnd); + { + auto frame = create_framed_widget( CamWnd_getWidget( *m_pCamWnd ) ); + window.add(frame); + } + CamWnd_setParent( *m_pCamWnd, window ); - { - auto frame = create_framed_widget(CamWnd_getWidget(*m_pCamWnd)); - window.add(frame); - } - CamWnd_setParent(*m_pCamWnd, window); + g_floating_windows.push_back( window ); + } - g_floating_windows.push_back(window); - } - - { - ui::Window window = ui::Window(create_persistent_floating_window(ViewType_getTitle(XY), m_window)); - global_accel_connect_window(window); - g_posXYWnd.connect(window); + { + ui::Window window = ui::Window(create_persistent_floating_window( ViewType_getTitle( XY ), m_window )); + global_accel_connect_window( window ); + g_posXYWnd.connect( window ); - m_pXYWnd = new XYWnd(); - m_pXYWnd->m_parent = window; - m_pXYWnd->SetViewType(XY); + m_pXYWnd = new XYWnd(); + m_pXYWnd->m_parent = window; + m_pXYWnd->SetViewType( XY ); - { - auto frame = create_framed_widget(m_pXYWnd->GetWidget()); - window.add(frame); - } - XY_Top_Shown_Construct(window); + { + auto frame = create_framed_widget( m_pXYWnd->GetWidget() ); + window.add(frame); + } + XY_Top_Shown_Construct( window ); - g_floating_windows.push_back(window); - } + g_floating_windows.push_back( window ); + } - { - ui::Window window = ui::Window(create_persistent_floating_window(ViewType_getTitle(XZ), m_window)); - global_accel_connect_window(window); - g_posXZWnd.connect(window); + { + ui::Window window = ui::Window(create_persistent_floating_window( ViewType_getTitle( XZ ), m_window )); + global_accel_connect_window( window ); + g_posXZWnd.connect( window ); - m_pXZWnd = new XYWnd(); - m_pXZWnd->m_parent = window; - m_pXZWnd->SetViewType(XZ); + m_pXZWnd = new XYWnd(); + m_pXZWnd->m_parent = window; + m_pXZWnd->SetViewType( XZ ); - { - auto frame = create_framed_widget(m_pXZWnd->GetWidget()); - window.add(frame); - } + { + auto frame = create_framed_widget( m_pXZWnd->GetWidget() ); + window.add(frame); + } - XZ_Front_Shown_Construct(window); + XZ_Front_Shown_Construct( window ); - g_floating_windows.push_back(window); - } + g_floating_windows.push_back( window ); + } - { - ui::Window window = ui::Window(create_persistent_floating_window(ViewType_getTitle(YZ), m_window)); - global_accel_connect_window(window); - g_posYZWnd.connect(window); + { + ui::Window window = ui::Window(create_persistent_floating_window( ViewType_getTitle( YZ ), m_window )); + global_accel_connect_window( window ); + g_posYZWnd.connect( window ); - m_pYZWnd = new XYWnd(); - m_pYZWnd->m_parent = window; - m_pYZWnd->SetViewType(YZ); + m_pYZWnd = new XYWnd(); + m_pYZWnd->m_parent = window; + m_pYZWnd->SetViewType( YZ ); - { - auto frame = create_framed_widget(m_pYZWnd->GetWidget()); - window.add(frame); - } + { + auto frame = create_framed_widget( m_pYZWnd->GetWidget() ); + window.add(frame); + } - YZ_Side_Shown_Construct(window); + YZ_Side_Shown_Construct( window ); - g_floating_windows.push_back(window); - } + g_floating_windows.push_back( window ); + } - { - auto frame = create_framed_widget(TextureBrowser_constructWindow(GroupDialog_getWindow())); - g_page_textures = GroupDialog_addPage("Textures", frame, TextureBrowserExportTitleCaller()); - } + { + auto frame = create_framed_widget( TextureBrowser_constructWindow( GroupDialog_getWindow() ) ); + g_page_textures = GroupDialog_addPage( "Textures", frame, TextureBrowserExportTitleCaller() ); + } - GroupDialog_show(); - } else // 4 way - { - m_pCamWnd = NewCamWnd(); - GlobalCamera_setCamWnd(*m_pCamWnd); - CamWnd_setParent(*m_pCamWnd, window); + GroupDialog_show(); + } + else // 4 way + { + m_pCamWnd = NewCamWnd(); + GlobalCamera_setCamWnd( *m_pCamWnd ); + CamWnd_setParent( *m_pCamWnd, window ); - ui::Widget camera = CamWnd_getWidget(*m_pCamWnd); + ui::Widget camera = CamWnd_getWidget( *m_pCamWnd ); - m_pYZWnd = new XYWnd(); - m_pYZWnd->SetViewType(YZ); + m_pYZWnd = new XYWnd(); + m_pYZWnd->SetViewType( YZ ); - ui::Widget yz = m_pYZWnd->GetWidget(); + ui::Widget yz = m_pYZWnd->GetWidget(); - m_pXYWnd = new XYWnd(); - m_pXYWnd->SetViewType(XY); + m_pXYWnd = new XYWnd(); + m_pXYWnd->SetViewType( XY ); - ui::Widget xy = m_pXYWnd->GetWidget(); + ui::Widget xy = m_pXYWnd->GetWidget(); - m_pXZWnd = new XYWnd(); - m_pXZWnd->SetViewType(XZ); + m_pXZWnd = new XYWnd(); + m_pXZWnd->SetViewType( XZ ); - ui::Widget xz = m_pXZWnd->GetWidget(); + ui::Widget xz = m_pXZWnd->GetWidget(); - auto split = create_split_views(camera, yz, xy, xz); - vbox.pack_start(split, TRUE, TRUE, 0); + auto split = create_split_views( camera, yz, xy, xz ); + vbox.pack_start( split, TRUE, TRUE, 0 ); - { - auto frame = create_framed_widget(TextureBrowser_constructWindow(window)); - g_page_textures = GroupDialog_addPage("Textures", frame, TextureBrowserExportTitleCaller()); - } - } + { + auto frame = create_framed_widget( TextureBrowser_constructWindow( window ) ); + g_page_textures = GroupDialog_addPage( "Textures", frame, TextureBrowserExportTitleCaller() ); + } + } - EntityList_constructWindow(window); - PreferencesDialog_constructWindow(window); - FindTextureDialog_constructWindow(window); - SurfaceInspector_constructWindow(window); - PatchInspector_constructWindow(window); + EntityList_constructWindow( window ); + PreferencesDialog_constructWindow( window ); + FindTextureDialog_constructWindow( window ); + SurfaceInspector_constructWindow( window ); + PatchInspector_constructWindow( window ); - SetActiveXY(m_pXYWnd); + SetActiveXY( m_pXYWnd ); - AddGridChangeCallback(SetGridStatusCaller(*this)); - AddGridChangeCallback(ReferenceCaller(*this)); + AddGridChangeCallback( SetGridStatusCaller( *this ) ); + AddGridChangeCallback( ReferenceCaller( *this ) ); - g_defaultToolMode = DragMode; - g_defaultToolMode(); - SetStatusText(m_command_status, c_TranslateMode_status); + g_defaultToolMode = DragMode; + g_defaultToolMode(); + SetStatusText( m_command_status, c_TranslateMode_status ); - EverySecondTimer_enable(); + EverySecondTimer_enable(); - //GlobalShortcuts_reportUnregistered(); + //GlobalShortcuts_reportUnregistered(); } -void MainFrame::SaveWindowInfo() -{ - if (!FloatingGroupDialog()) { - g_layout_globals.nXYHeight = gtk_paned_get_position(GTK_PANED(m_vSplit)); +void MainFrame::SaveWindowInfo(){ + if ( !FloatingGroupDialog() ) { + g_layout_globals.nXYHeight = gtk_paned_get_position( GTK_PANED( m_vSplit ) ); - if (CurrentStyle() != eRegular) { - g_layout_globals.nCamWidth = gtk_paned_get_position(GTK_PANED(m_hSplit)); - } else { - g_layout_globals.nXYWidth = gtk_paned_get_position(GTK_PANED(m_hSplit)); - } + if ( CurrentStyle() != eRegular ) { + g_layout_globals.nCamWidth = gtk_paned_get_position( GTK_PANED( m_hSplit ) ); + } + else + { + g_layout_globals.nXYWidth = gtk_paned_get_position( GTK_PANED( m_hSplit ) ); + } - g_layout_globals.nCamHeight = gtk_paned_get_position(GTK_PANED(m_vSplit2)); - } + g_layout_globals.nCamHeight = gtk_paned_get_position( GTK_PANED( m_vSplit2 ) ); + } - g_layout_globals.m_position = m_position_tracker.getPosition(); + g_layout_globals.m_position = m_position_tracker.getPosition(); - g_layout_globals.nState = gdk_window_get_state(gtk_widget_get_window(m_window)); + g_layout_globals.nState = gdk_window_get_state( gtk_widget_get_window(m_window ) ); } -void MainFrame::Shutdown() -{ - EverySecondTimer_disable(); +void MainFrame::Shutdown(){ + EverySecondTimer_disable(); - EntityList_destroyWindow(); + EntityList_destroyWindow(); - delete m_pXYWnd; - m_pXYWnd = 0; - delete m_pYZWnd; - m_pYZWnd = 0; - delete m_pXZWnd; - m_pXZWnd = 0; + delete m_pXYWnd; + m_pXYWnd = 0; + delete m_pYZWnd; + m_pYZWnd = 0; + delete m_pXZWnd; + m_pXZWnd = 0; - TextureBrowser_destroyWindow(); + TextureBrowser_destroyWindow(); - DeleteCamWnd(m_pCamWnd); - m_pCamWnd = 0; + DeleteCamWnd( m_pCamWnd ); + m_pCamWnd = 0; - PreferencesDialog_destroyWindow(); - SurfaceInspector_destroyWindow(); - FindTextureDialog_destroyWindow(); - PatchInspector_destroyWindow(); + PreferencesDialog_destroyWindow(); + SurfaceInspector_destroyWindow(); + FindTextureDialog_destroyWindow(); + PatchInspector_destroyWindow(); - g_DbgDlg.destroyWindow(); + g_DbgDlg.destroyWindow(); - // destroying group-dialog last because it may contain texture-browser - GroupDialog_destroyWindow(); + // destroying group-dialog last because it may contain texture-browser + GroupDialog_destroyWindow(); } -void MainFrame::RedrawStatusText() -{ - ui::Label::from(m_pStatusLabel[c_command_status]).text(m_command_status.c_str()); - ui::Label::from(m_pStatusLabel[c_position_status]).text(m_position_status.c_str()); - ui::Label::from(m_pStatusLabel[c_brushcount_status]).text(m_brushcount_status.c_str()); - ui::Label::from(m_pStatusLabel[c_texture_status]).text(m_texture_status.c_str()); - ui::Label::from(m_pStatusLabel[c_grid_status]).text(m_grid_status.c_str()); +void MainFrame::RedrawStatusText(){ + ui::Label::from(m_pStatusLabel[c_command_status]).text(m_command_status.c_str()); + ui::Label::from(m_pStatusLabel[c_position_status]).text(m_position_status.c_str()); + ui::Label::from(m_pStatusLabel[c_brushcount_status]).text(m_brushcount_status.c_str()); + ui::Label::from(m_pStatusLabel[c_texture_status]).text(m_texture_status.c_str()); + ui::Label::from(m_pStatusLabel[c_grid_status]).text(m_grid_status.c_str()); } -void MainFrame::UpdateStatusText() -{ - m_idleRedrawStatusText.queueDraw(); +void MainFrame::UpdateStatusText(){ + m_idleRedrawStatusText.queueDraw(); } -void MainFrame::SetStatusText(CopiedString &status_text, const char *pText) -{ - status_text = pText; - UpdateStatusText(); +void MainFrame::SetStatusText( CopiedString& status_text, const char* pText ){ + status_text = pText; + UpdateStatusText(); } -void Sys_Status(const char *status) -{ - if (g_pParentWnd != 0) { - g_pParentWnd->SetStatusText(g_pParentWnd->m_command_status, status); - } +void Sys_Status( const char* status ){ + if ( g_pParentWnd != 0 ) { + g_pParentWnd->SetStatusText( g_pParentWnd->m_command_status, status ); + } } -int getRotateIncrement() -{ - return static_cast( g_si_globals.rotate ); +int getRotateIncrement(){ + return static_cast( g_si_globals.rotate ); } -int getFarClipDistance() -{ - return g_camwindow_globals.m_nCubicScale; +int getFarClipDistance(){ + return g_camwindow_globals.m_nCubicScale; } float ( *GridStatus_getGridSize )() = GetGridSize; @@ -3423,340 +3233,297 @@ int ( *GridStatus_getFarClipDistance )() = getFarClipDistance; bool ( *GridStatus_getTextureLockEnabled )(); -void MainFrame::SetGridStatus() -{ - StringOutputStream status(64); - const char *lock = (GridStatus_getTextureLockEnabled()) ? "ON" : "OFF"; - status << (GetSnapGridSize() > 0 ? "G:" : "g:") << GridStatus_getGridSize() - << " R:" << GridStatus_getRotateIncrement() - << " C:" << GridStatus_getFarClipDistance() - << " L:" << lock; - SetStatusText(m_grid_status, status.c_str()); +void MainFrame::SetGridStatus(){ + StringOutputStream status( 64 ); + const char* lock = ( GridStatus_getTextureLockEnabled() ) ? "ON" : "OFF"; + status << ( GetSnapGridSize() > 0 ? "G:" : "g:" ) << GridStatus_getGridSize() + << " R:" << GridStatus_getRotateIncrement() + << " C:" << GridStatus_getFarClipDistance() + << " L:" << lock; + SetStatusText( m_grid_status, status.c_str() ); } -void GridStatus_onTextureLockEnabledChanged() -{ - if (g_pParentWnd != 0) { - g_pParentWnd->SetGridStatus(); - } +void GridStatus_onTextureLockEnabledChanged(){ + if ( g_pParentWnd != 0 ) { + g_pParentWnd->SetGridStatus(); + } } -void GlobalGL_sharedContextCreated() -{ - GLFont *g_font = NULL; +void GlobalGL_sharedContextCreated(){ + GLFont *g_font = NULL; - // report OpenGL information - globalOutputStream() << "GL_VENDOR: " << reinterpret_cast( glGetString(GL_VENDOR)) << "\n"; - globalOutputStream() << "GL_RENDERER: " << reinterpret_cast( glGetString(GL_RENDERER)) << "\n"; - globalOutputStream() << "GL_VERSION: " << reinterpret_cast( glGetString(GL_VERSION)) << "\n"; - const auto extensions = reinterpret_cast( glGetString(GL_EXTENSIONS)); + // report OpenGL information + globalOutputStream() << "GL_VENDOR: " << reinterpret_cast( glGetString( GL_VENDOR ) ) << "\n"; + globalOutputStream() << "GL_RENDERER: " << reinterpret_cast( glGetString( GL_RENDERER ) ) << "\n"; + globalOutputStream() << "GL_VERSION: " << reinterpret_cast( glGetString( GL_VERSION ) ) << "\n"; + const auto extensions = reinterpret_cast( glGetString(GL_EXTENSIONS ) ); globalOutputStream() << "GL_EXTENSIONS: " << (extensions ? extensions : "") << "\n"; - QGL_sharedContextCreated(GlobalOpenGL()); + QGL_sharedContextCreated( GlobalOpenGL() ); - ShaderCache_extensionsInitialised(); + ShaderCache_extensionsInitialised(); - GlobalShaderCache().realise(); - Textures_Realise(); + GlobalShaderCache().realise(); + Textures_Realise(); #if GDEF_OS_WINDOWS - /* win32 is dodgy here, just use courier new then */ + /* win32 is dodgy here, just use courier new then */ g_font = glfont_create( "arial 9" ); #else - auto settings = gtk_settings_get_default(); - gchar *fontname; - g_object_get(settings, "gtk-font-name", &fontname, NULL); - g_font = glfont_create(fontname); + auto settings = gtk_settings_get_default(); + gchar *fontname; + g_object_get( settings, "gtk-font-name", &fontname, NULL ); + g_font = glfont_create( fontname ); #endif - GlobalOpenGL().m_font = g_font; + GlobalOpenGL().m_font = g_font; } -void GlobalGL_sharedContextDestroyed() -{ - Textures_Unrealise(); - GlobalShaderCache().unrealise(); +void GlobalGL_sharedContextDestroyed(){ + Textures_Unrealise(); + GlobalShaderCache().unrealise(); - QGL_sharedContextDestroyed(GlobalOpenGL()); + QGL_sharedContextDestroyed( GlobalOpenGL() ); } -void Layout_constructPreferences(PreferencesPage &page) -{ - { - const char *layouts[] = {"window1.png", "window2.png", "window3.png", "window4.png"}; - page.appendRadioIcons( - "Window Layout", - STRING_ARRAY_RANGE(layouts), - make_property(g_Layout_viewStyle) - ); - } - page.appendCheckBox( - "", "Detachable Menus", - make_property(g_Layout_enableDetachableMenus) - ); - if (!string_empty(g_pGameDescription->getKeyValue("no_patch"))) { - page.appendCheckBox( - "", "Patch Toolbar", - make_property(g_Layout_enablePatchToolbar) - ); - } - page.appendCheckBox( - "", "Plugin Toolbar", - make_property(g_Layout_enablePluginToolbar) - ); -} - -void Layout_constructPage(PreferenceGroup &group) -{ - PreferencesPage page(group.createPage("Layout", "Layout Preferences")); - Layout_constructPreferences(page); +void Layout_constructPreferences( PreferencesPage& page ){ + { + const char* layouts[] = { "window1.png", "window2.png", "window3.png", "window4.png" }; + page.appendRadioIcons( + "Window Layout", + STRING_ARRAY_RANGE( layouts ), + make_property( g_Layout_viewStyle ) + ); + } + page.appendCheckBox( + "", "Detachable Menus", + make_property( g_Layout_enableDetachableMenus ) + ); + if ( !string_empty( g_pGameDescription->getKeyValue( "no_patch" ) ) ) { + page.appendCheckBox( + "", "Patch Toolbar", + make_property( g_Layout_enablePatchToolbar ) + ); + } + page.appendCheckBox( + "", "Plugin Toolbar", + make_property( g_Layout_enablePluginToolbar ) + ); } -void Layout_registerPreferencesPage() -{ - PreferencesDialog_addInterfacePage(makeCallbackF(Layout_constructPage)); +void Layout_constructPage( PreferenceGroup& group ){ + PreferencesPage page( group.createPage( "Layout", "Layout Preferences" ) ); + Layout_constructPreferences( page ); +} + +void Layout_registerPreferencesPage(){ + PreferencesDialog_addInterfacePage( makeCallbackF(Layout_constructPage) ); } #include "preferencesystem.h" #include "stringio.h" -void MainFrame_Construct() -{ - GlobalCommands_insert("OpenManual", makeCallbackF(OpenHelpURL), Accelerator(GDK_KEY_F1)); - - GlobalCommands_insert("Sleep", makeCallbackF(thunk_OnSleep), - Accelerator('P', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); - GlobalCommands_insert("NewMap", makeCallbackF(NewMap)); - GlobalCommands_insert("OpenMap", makeCallbackF(OpenMap), Accelerator('O', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("ImportMap", makeCallbackF(ImportMap)); - GlobalCommands_insert("SaveMap", makeCallbackF(SaveMap), Accelerator('S', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("SaveMapAs", makeCallbackF(SaveMapAs)); - GlobalCommands_insert("ExportSelected", makeCallbackF(ExportMap)); - GlobalCommands_insert("SaveRegion", makeCallbackF(SaveRegion)); - GlobalCommands_insert("RefreshReferences", makeCallbackF(VFS_Refresh)); - GlobalCommands_insert("ProjectSettings", makeCallbackF(DoProjectSettings)); - GlobalCommands_insert("Exit", makeCallbackF(Exit)); - - GlobalCommands_insert("Undo", makeCallbackF(Undo), Accelerator('Z', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("Redo", makeCallbackF(Redo), Accelerator('Y', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("Copy", makeCallbackF(Copy), Accelerator('C', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("Paste", makeCallbackF(Paste), Accelerator('V', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("PasteToCamera", makeCallbackF(PasteToCamera), - Accelerator('V', (GdkModifierType) GDK_MOD1_MASK)); - GlobalCommands_insert("CloneSelection", makeCallbackF(Selection_Clone), Accelerator(GDK_KEY_space)); - GlobalCommands_insert("CloneSelectionAndMakeUnique", makeCallbackF(Selection_Clone_MakeUnique), - Accelerator(GDK_KEY_space, (GdkModifierType) GDK_SHIFT_MASK)); - GlobalCommands_insert("DeleteSelection", makeCallbackF(deleteSelection), Accelerator(GDK_KEY_BackSpace)); - GlobalCommands_insert("ParentSelection", makeCallbackF(Scene_parentSelected)); - GlobalCommands_insert("UnSelectSelection", makeCallbackF(Selection_Deselect), Accelerator(GDK_KEY_Escape)); - GlobalCommands_insert("InvertSelection", makeCallbackF(Select_Invert), Accelerator('I')); - GlobalCommands_insert("SelectInside", makeCallbackF(Select_Inside)); - GlobalCommands_insert("SelectTouching", makeCallbackF(Select_Touching)); - GlobalCommands_insert("ExpandSelectionToEntities", makeCallbackF(Scene_ExpandSelectionToEntities), - Accelerator('E', (GdkModifierType) (GDK_MOD1_MASK | GDK_CONTROL_MASK))); - GlobalCommands_insert("Preferences", makeCallbackF(PreferencesDialog_showDialog), Accelerator('P')); - - GlobalCommands_insert("ToggleConsole", makeCallbackF(Console_ToggleShow), Accelerator('O')); - GlobalCommands_insert("ToggleEntityInspector", makeCallbackF(EntityInspector_ToggleShow), Accelerator('N')); - GlobalCommands_insert("EntityList", makeCallbackF(EntityList_toggleShown), Accelerator('L')); - - GlobalCommands_insert("ShowHidden", makeCallbackF(Select_ShowAllHidden), - Accelerator('H', (GdkModifierType) GDK_SHIFT_MASK)); - GlobalCommands_insert("HideSelected", makeCallbackF(HideSelected), Accelerator('H')); - - GlobalToggles_insert("DragVertices", makeCallbackF(SelectVertexMode), - ToggleItem::AddCallbackCaller(g_vertexMode_button), Accelerator('V')); - GlobalToggles_insert("DragEdges", makeCallbackF(SelectEdgeMode), ToggleItem::AddCallbackCaller(g_edgeMode_button), - Accelerator('E')); - GlobalToggles_insert("DragFaces", makeCallbackF(SelectFaceMode), ToggleItem::AddCallbackCaller(g_faceMode_button), - Accelerator('F')); - - GlobalCommands_insert("MirrorSelectionX", makeCallbackF(Selection_Flipx)); - GlobalCommands_insert("RotateSelectionX", makeCallbackF(Selection_Rotatex)); - GlobalCommands_insert("MirrorSelectionY", makeCallbackF(Selection_Flipy)); - GlobalCommands_insert("RotateSelectionY", makeCallbackF(Selection_Rotatey)); - GlobalCommands_insert("MirrorSelectionZ", makeCallbackF(Selection_Flipz)); - GlobalCommands_insert("RotateSelectionZ", makeCallbackF(Selection_Rotatez)); - - GlobalCommands_insert("ArbitraryRotation", makeCallbackF(DoRotateDlg)); - GlobalCommands_insert("ArbitraryScale", makeCallbackF(DoScaleDlg)); - - GlobalCommands_insert("BuildMenuCustomize", makeCallbackF(DoBuildMenu)); - - GlobalCommands_insert("FindBrush", makeCallbackF(DoFind)); - - GlobalCommands_insert("MapInfo", makeCallbackF(DoMapInfo), Accelerator('M')); - - - GlobalToggles_insert("ToggleClipper", makeCallbackF(ClipperMode), ToggleItem::AddCallbackCaller(g_clipper_button), - Accelerator('X')); - - GlobalToggles_insert("MouseTranslate", makeCallbackF(TranslateMode), - ToggleItem::AddCallbackCaller(g_translatemode_button), Accelerator('W')); - GlobalToggles_insert("MouseRotate", makeCallbackF(RotateMode), ToggleItem::AddCallbackCaller(g_rotatemode_button), - Accelerator('R')); - GlobalToggles_insert("MouseScale", makeCallbackF(ScaleMode), ToggleItem::AddCallbackCaller(g_scalemode_button)); - GlobalToggles_insert("MouseDrag", makeCallbackF(DragMode), ToggleItem::AddCallbackCaller(g_dragmode_button), - Accelerator('Q')); - - GlobalCommands_insert("ColorSchemeOriginal", makeCallbackF(ColorScheme_Original)); - GlobalCommands_insert("ColorSchemeQER", makeCallbackF(ColorScheme_QER)); - GlobalCommands_insert("ColorSchemeBlackAndGreen", makeCallbackF(ColorScheme_Black)); - GlobalCommands_insert("ColorSchemeYdnar", makeCallbackF(ColorScheme_Ydnar)); - GlobalCommands_insert("ChooseTextureBackgroundColor", makeCallback(g_ColoursMenu.m_textureback)); - GlobalCommands_insert("ChooseGridBackgroundColor", makeCallback(g_ColoursMenu.m_xyback)); - GlobalCommands_insert("ChooseGridMajorColor", makeCallback(g_ColoursMenu.m_gridmajor)); - GlobalCommands_insert("ChooseGridMinorColor", makeCallback(g_ColoursMenu.m_gridminor)); - GlobalCommands_insert("ChooseSmallGridMajorColor", makeCallback(g_ColoursMenu.m_gridmajor_alt)); - GlobalCommands_insert("ChooseSmallGridMinorColor", makeCallback(g_ColoursMenu.m_gridminor_alt)); - GlobalCommands_insert("ChooseGridTextColor", makeCallback(g_ColoursMenu.m_gridtext)); - GlobalCommands_insert("ChooseGridBlockColor", makeCallback(g_ColoursMenu.m_gridblock)); - GlobalCommands_insert("ChooseBrushColor", makeCallback(g_ColoursMenu.m_brush)); - GlobalCommands_insert("ChooseCameraBackgroundColor", makeCallback(g_ColoursMenu.m_cameraback)); - GlobalCommands_insert("ChooseSelectedBrushColor", makeCallback(g_ColoursMenu.m_selectedbrush)); - GlobalCommands_insert("ChooseCameraSelectedBrushColor", makeCallback(g_ColoursMenu.m_selectedbrush3d)); - GlobalCommands_insert("ChooseClipperColor", makeCallback(g_ColoursMenu.m_clipper)); - GlobalCommands_insert("ChooseOrthoViewNameColor", makeCallback(g_ColoursMenu.m_viewname)); - - - GlobalCommands_insert("CSGSubtract", makeCallbackF(CSG_Subtract), - Accelerator('U', (GdkModifierType) GDK_SHIFT_MASK)); - GlobalCommands_insert("CSGMerge", makeCallbackF(CSG_Merge), Accelerator('U', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("CSGMakeHollow", makeCallbackF(CSG_MakeHollow)); - GlobalCommands_insert("CSGMakeRoom", makeCallbackF(CSG_MakeRoom)); - - Grid_registerCommands(); - - GlobalCommands_insert("SnapToGrid", makeCallbackF(Selection_SnapToGrid), - Accelerator('G', (GdkModifierType) GDK_CONTROL_MASK)); - - GlobalCommands_insert("SelectAllOfType", makeCallbackF(Select_AllOfType), - Accelerator('A', (GdkModifierType) GDK_SHIFT_MASK)); - - GlobalCommands_insert("TexRotateClock", makeCallbackF(Texdef_RotateClockwise), - Accelerator(GDK_KEY_Next, (GdkModifierType) GDK_SHIFT_MASK)); - GlobalCommands_insert("TexRotateCounter", makeCallbackF(Texdef_RotateAntiClockwise), - Accelerator(GDK_KEY_Prior, (GdkModifierType) GDK_SHIFT_MASK)); - GlobalCommands_insert("TexScaleUp", makeCallbackF(Texdef_ScaleUp), - Accelerator(GDK_KEY_Up, (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("TexScaleDown", makeCallbackF(Texdef_ScaleDown), - Accelerator(GDK_KEY_Down, (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("TexScaleLeft", makeCallbackF(Texdef_ScaleLeft), - Accelerator(GDK_KEY_Left, (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("TexScaleRight", makeCallbackF(Texdef_ScaleRight), - Accelerator(GDK_KEY_Right, (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("TexShiftUp", makeCallbackF(Texdef_ShiftUp), - Accelerator(GDK_KEY_Up, (GdkModifierType) GDK_SHIFT_MASK)); - GlobalCommands_insert("TexShiftDown", makeCallbackF(Texdef_ShiftDown), - Accelerator(GDK_KEY_Down, (GdkModifierType) GDK_SHIFT_MASK)); - GlobalCommands_insert("TexShiftLeft", makeCallbackF(Texdef_ShiftLeft), - Accelerator(GDK_KEY_Left, (GdkModifierType) GDK_SHIFT_MASK)); - GlobalCommands_insert("TexShiftRight", makeCallbackF(Texdef_ShiftRight), - Accelerator(GDK_KEY_Right, (GdkModifierType) GDK_SHIFT_MASK)); - - GlobalCommands_insert("MoveSelectionDOWN", makeCallbackF(Selection_MoveDown), Accelerator(GDK_KEY_KP_Subtract)); - GlobalCommands_insert("MoveSelectionUP", makeCallbackF(Selection_MoveUp), Accelerator(GDK_KEY_KP_Add)); - - GlobalCommands_insert("SelectNudgeLeft", makeCallbackF(Selection_NudgeLeft), - Accelerator(GDK_KEY_Left, (GdkModifierType) GDK_MOD1_MASK)); - GlobalCommands_insert("SelectNudgeRight", makeCallbackF(Selection_NudgeRight), - Accelerator(GDK_KEY_Right, (GdkModifierType) GDK_MOD1_MASK)); - GlobalCommands_insert("SelectNudgeUp", makeCallbackF(Selection_NudgeUp), - Accelerator(GDK_KEY_Up, (GdkModifierType) GDK_MOD1_MASK)); - GlobalCommands_insert("SelectNudgeDown", makeCallbackF(Selection_NudgeDown), - Accelerator(GDK_KEY_Down, (GdkModifierType) GDK_MOD1_MASK)); - - Patch_registerCommands(); - XYShow_registerCommands(); - - typedef FreeCaller ComponentModeSelectionChangedCaller; - GlobalSelectionSystem().addSelectionChangeCallback(ComponentModeSelectionChangedCaller()); - - GlobalPreferenceSystem().registerPreference("DetachableMenus", - make_property_string(g_Layout_enableDetachableMenus.m_latched)); - GlobalPreferenceSystem().registerPreference("PatchToolBar", - make_property_string(g_Layout_enablePatchToolbar.m_latched)); - GlobalPreferenceSystem().registerPreference("PluginToolBar", - make_property_string(g_Layout_enablePluginToolbar.m_latched)); - GlobalPreferenceSystem().registerPreference("QE4StyleWindows", make_property_string(g_Layout_viewStyle.m_latched)); - GlobalPreferenceSystem().registerPreference("XYHeight", make_property_string(g_layout_globals.nXYHeight)); - GlobalPreferenceSystem().registerPreference("XYWidth", make_property_string(g_layout_globals.nXYWidth)); - GlobalPreferenceSystem().registerPreference("CamWidth", make_property_string(g_layout_globals.nCamWidth)); - GlobalPreferenceSystem().registerPreference("CamHeight", make_property_string(g_layout_globals.nCamHeight)); - - GlobalPreferenceSystem().registerPreference("State", make_property_string(g_layout_globals.nState)); - GlobalPreferenceSystem().registerPreference("PositionX", make_property_string(g_layout_globals.m_position.x)); - GlobalPreferenceSystem().registerPreference("PositionY", make_property_string(g_layout_globals.m_position.y)); - GlobalPreferenceSystem().registerPreference("Width", make_property_string(g_layout_globals.m_position.w)); - GlobalPreferenceSystem().registerPreference("Height", make_property_string(g_layout_globals.m_position.h)); - - GlobalPreferenceSystem().registerPreference("CamWnd", make_property(g_posCamWnd)); - GlobalPreferenceSystem().registerPreference("XYWnd", make_property(g_posXYWnd)); - GlobalPreferenceSystem().registerPreference("YZWnd", make_property(g_posYZWnd)); - GlobalPreferenceSystem().registerPreference("XZWnd", make_property(g_posXZWnd)); - - { - const char *ENGINEPATH_ATTRIBUTE = +void MainFrame_Construct(){ + GlobalCommands_insert( "OpenManual", makeCallbackF(OpenHelpURL), Accelerator( GDK_KEY_F1 ) ); + + GlobalCommands_insert( "Sleep", makeCallbackF(thunk_OnSleep), Accelerator( 'P', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); + GlobalCommands_insert( "NewMap", makeCallbackF(NewMap) ); + GlobalCommands_insert( "OpenMap", makeCallbackF(OpenMap), Accelerator( 'O', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "ImportMap", makeCallbackF(ImportMap) ); + GlobalCommands_insert( "SaveMap", makeCallbackF(SaveMap), Accelerator( 'S', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "SaveMapAs", makeCallbackF(SaveMapAs) ); + GlobalCommands_insert( "ExportSelected", makeCallbackF(ExportMap) ); + GlobalCommands_insert( "SaveRegion", makeCallbackF(SaveRegion) ); + GlobalCommands_insert( "RefreshReferences", makeCallbackF(VFS_Refresh) ); + GlobalCommands_insert( "ProjectSettings", makeCallbackF(DoProjectSettings) ); + GlobalCommands_insert( "Exit", makeCallbackF(Exit) ); + + GlobalCommands_insert( "Undo", makeCallbackF(Undo), Accelerator( 'Z', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "Redo", makeCallbackF(Redo), Accelerator( 'Y', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "Copy", makeCallbackF(Copy), Accelerator( 'C', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "Paste", makeCallbackF(Paste), Accelerator( 'V', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "PasteToCamera", makeCallbackF(PasteToCamera), Accelerator( 'V', (GdkModifierType)GDK_MOD1_MASK ) ); + GlobalCommands_insert( "CloneSelection", makeCallbackF(Selection_Clone), Accelerator( GDK_KEY_space ) ); + GlobalCommands_insert( "CloneSelectionAndMakeUnique", makeCallbackF(Selection_Clone_MakeUnique), Accelerator( GDK_KEY_space, (GdkModifierType)GDK_SHIFT_MASK ) ); + GlobalCommands_insert( "DeleteSelection", makeCallbackF(deleteSelection), Accelerator( GDK_KEY_BackSpace ) ); + GlobalCommands_insert( "ParentSelection", makeCallbackF(Scene_parentSelected) ); + GlobalCommands_insert( "UnSelectSelection", makeCallbackF(Selection_Deselect), Accelerator( GDK_KEY_Escape ) ); + GlobalCommands_insert( "InvertSelection", makeCallbackF(Select_Invert), Accelerator( 'I' ) ); + GlobalCommands_insert( "SelectInside", makeCallbackF(Select_Inside) ); + GlobalCommands_insert( "SelectTouching", makeCallbackF(Select_Touching) ); + GlobalCommands_insert( "ExpandSelectionToEntities", makeCallbackF(Scene_ExpandSelectionToEntities), Accelerator( 'E', (GdkModifierType)( GDK_MOD1_MASK | GDK_CONTROL_MASK ) ) ); + GlobalCommands_insert( "Preferences", makeCallbackF(PreferencesDialog_showDialog), Accelerator( 'P' ) ); + + GlobalCommands_insert( "ToggleConsole", makeCallbackF(Console_ToggleShow), Accelerator( 'O' ) ); + GlobalCommands_insert( "ToggleEntityInspector", makeCallbackF(EntityInspector_ToggleShow), Accelerator( 'N' ) ); + GlobalCommands_insert( "EntityList", makeCallbackF(EntityList_toggleShown), Accelerator( 'L' ) ); + + GlobalCommands_insert( "ShowHidden", makeCallbackF(Select_ShowAllHidden), Accelerator( 'H', (GdkModifierType)GDK_SHIFT_MASK ) ); + GlobalCommands_insert( "HideSelected", makeCallbackF(HideSelected), Accelerator( 'H' ) ); + + GlobalToggles_insert( "DragVertices", makeCallbackF(SelectVertexMode), ToggleItem::AddCallbackCaller( g_vertexMode_button ), Accelerator( 'V' ) ); + GlobalToggles_insert( "DragEdges", makeCallbackF(SelectEdgeMode), ToggleItem::AddCallbackCaller( g_edgeMode_button ), Accelerator( 'E' ) ); + GlobalToggles_insert( "DragFaces", makeCallbackF(SelectFaceMode), ToggleItem::AddCallbackCaller( g_faceMode_button ), Accelerator( 'F' ) ); + + GlobalCommands_insert( "MirrorSelectionX", makeCallbackF(Selection_Flipx) ); + GlobalCommands_insert( "RotateSelectionX", makeCallbackF(Selection_Rotatex) ); + GlobalCommands_insert( "MirrorSelectionY", makeCallbackF(Selection_Flipy) ); + GlobalCommands_insert( "RotateSelectionY", makeCallbackF(Selection_Rotatey) ); + GlobalCommands_insert( "MirrorSelectionZ", makeCallbackF(Selection_Flipz) ); + GlobalCommands_insert( "RotateSelectionZ", makeCallbackF(Selection_Rotatez) ); + + GlobalCommands_insert( "ArbitraryRotation", makeCallbackF(DoRotateDlg) ); + GlobalCommands_insert( "ArbitraryScale", makeCallbackF(DoScaleDlg) ); + + GlobalCommands_insert( "BuildMenuCustomize", makeCallbackF(DoBuildMenu) ); + + GlobalCommands_insert( "FindBrush", makeCallbackF(DoFind) ); + + GlobalCommands_insert( "MapInfo", makeCallbackF(DoMapInfo), Accelerator( 'M' ) ); + + + GlobalToggles_insert( "ToggleClipper", makeCallbackF(ClipperMode), ToggleItem::AddCallbackCaller( g_clipper_button ), Accelerator( 'X' ) ); + + GlobalToggles_insert( "MouseTranslate", makeCallbackF(TranslateMode), ToggleItem::AddCallbackCaller( g_translatemode_button ), Accelerator( 'W' ) ); + GlobalToggles_insert( "MouseRotate", makeCallbackF(RotateMode), ToggleItem::AddCallbackCaller( g_rotatemode_button ), Accelerator( 'R' ) ); + GlobalToggles_insert( "MouseScale", makeCallbackF(ScaleMode), ToggleItem::AddCallbackCaller( g_scalemode_button ) ); + GlobalToggles_insert( "MouseDrag", makeCallbackF(DragMode), ToggleItem::AddCallbackCaller( g_dragmode_button ), Accelerator( 'Q' ) ); + + GlobalCommands_insert( "ColorSchemeOriginal", makeCallbackF(ColorScheme_Original) ); + GlobalCommands_insert( "ColorSchemeQER", makeCallbackF(ColorScheme_QER) ); + GlobalCommands_insert( "ColorSchemeBlackAndGreen", makeCallbackF(ColorScheme_Black) ); + GlobalCommands_insert( "ColorSchemeYdnar", makeCallbackF(ColorScheme_Ydnar) ); + GlobalCommands_insert( "ChooseTextureBackgroundColor", makeCallback( g_ColoursMenu.m_textureback ) ); + GlobalCommands_insert( "ChooseGridBackgroundColor", makeCallback( g_ColoursMenu.m_xyback ) ); + GlobalCommands_insert( "ChooseGridMajorColor", makeCallback( g_ColoursMenu.m_gridmajor ) ); + GlobalCommands_insert( "ChooseGridMinorColor", makeCallback( g_ColoursMenu.m_gridminor ) ); + GlobalCommands_insert( "ChooseSmallGridMajorColor", makeCallback( g_ColoursMenu.m_gridmajor_alt ) ); + GlobalCommands_insert( "ChooseSmallGridMinorColor", makeCallback( g_ColoursMenu.m_gridminor_alt ) ); + GlobalCommands_insert( "ChooseGridTextColor", makeCallback( g_ColoursMenu.m_gridtext ) ); + GlobalCommands_insert( "ChooseGridBlockColor", makeCallback( g_ColoursMenu.m_gridblock ) ); + GlobalCommands_insert( "ChooseBrushColor", makeCallback( g_ColoursMenu.m_brush ) ); + GlobalCommands_insert( "ChooseCameraBackgroundColor", makeCallback( g_ColoursMenu.m_cameraback ) ); + GlobalCommands_insert( "ChooseSelectedBrushColor", makeCallback( g_ColoursMenu.m_selectedbrush ) ); + GlobalCommands_insert( "ChooseCameraSelectedBrushColor", makeCallback( g_ColoursMenu.m_selectedbrush3d ) ); + GlobalCommands_insert( "ChooseClipperColor", makeCallback( g_ColoursMenu.m_clipper ) ); + GlobalCommands_insert( "ChooseOrthoViewNameColor", makeCallback( g_ColoursMenu.m_viewname ) ); + + + GlobalCommands_insert( "CSGSubtract", makeCallbackF(CSG_Subtract), Accelerator( 'U', (GdkModifierType)GDK_SHIFT_MASK ) ); + GlobalCommands_insert( "CSGMerge", makeCallbackF(CSG_Merge), Accelerator( 'U', (GdkModifierType) GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "CSGMakeHollow", makeCallbackF(CSG_MakeHollow) ); + GlobalCommands_insert( "CSGMakeRoom", makeCallbackF(CSG_MakeRoom) ); + + Grid_registerCommands(); + + GlobalCommands_insert( "SnapToGrid", makeCallbackF(Selection_SnapToGrid), Accelerator( 'G', (GdkModifierType)GDK_CONTROL_MASK ) ); + + GlobalCommands_insert( "SelectAllOfType", makeCallbackF(Select_AllOfType), Accelerator( 'A', (GdkModifierType)GDK_SHIFT_MASK ) ); + + GlobalCommands_insert( "TexRotateClock", makeCallbackF(Texdef_RotateClockwise), Accelerator( GDK_KEY_Next, (GdkModifierType)GDK_SHIFT_MASK ) ); + GlobalCommands_insert( "TexRotateCounter", makeCallbackF(Texdef_RotateAntiClockwise), Accelerator( GDK_KEY_Prior, (GdkModifierType)GDK_SHIFT_MASK ) ); + GlobalCommands_insert( "TexScaleUp", makeCallbackF(Texdef_ScaleUp), Accelerator( GDK_KEY_Up, (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "TexScaleDown", makeCallbackF(Texdef_ScaleDown), Accelerator( GDK_KEY_Down, (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "TexScaleLeft", makeCallbackF(Texdef_ScaleLeft), Accelerator( GDK_KEY_Left, (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "TexScaleRight", makeCallbackF(Texdef_ScaleRight), Accelerator( GDK_KEY_Right, (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "TexShiftUp", makeCallbackF(Texdef_ShiftUp), Accelerator( GDK_KEY_Up, (GdkModifierType)GDK_SHIFT_MASK ) ); + GlobalCommands_insert( "TexShiftDown", makeCallbackF(Texdef_ShiftDown), Accelerator( GDK_KEY_Down, (GdkModifierType)GDK_SHIFT_MASK ) ); + GlobalCommands_insert( "TexShiftLeft", makeCallbackF(Texdef_ShiftLeft), Accelerator( GDK_KEY_Left, (GdkModifierType)GDK_SHIFT_MASK ) ); + GlobalCommands_insert( "TexShiftRight", makeCallbackF(Texdef_ShiftRight), Accelerator( GDK_KEY_Right, (GdkModifierType)GDK_SHIFT_MASK ) ); + + GlobalCommands_insert( "MoveSelectionDOWN", makeCallbackF(Selection_MoveDown), Accelerator( GDK_KEY_KP_Subtract ) ); + GlobalCommands_insert( "MoveSelectionUP", makeCallbackF(Selection_MoveUp), Accelerator( GDK_KEY_KP_Add ) ); + + GlobalCommands_insert( "SelectNudgeLeft", makeCallbackF(Selection_NudgeLeft), Accelerator( GDK_KEY_Left, (GdkModifierType)GDK_MOD1_MASK ) ); + GlobalCommands_insert( "SelectNudgeRight", makeCallbackF(Selection_NudgeRight), Accelerator( GDK_KEY_Right, (GdkModifierType)GDK_MOD1_MASK ) ); + GlobalCommands_insert( "SelectNudgeUp", makeCallbackF(Selection_NudgeUp), Accelerator( GDK_KEY_Up, (GdkModifierType)GDK_MOD1_MASK ) ); + GlobalCommands_insert( "SelectNudgeDown", makeCallbackF(Selection_NudgeDown), Accelerator( GDK_KEY_Down, (GdkModifierType)GDK_MOD1_MASK ) ); + + Patch_registerCommands(); + XYShow_registerCommands(); + + typedef FreeCaller ComponentModeSelectionChangedCaller; + GlobalSelectionSystem().addSelectionChangeCallback( ComponentModeSelectionChangedCaller() ); + + GlobalPreferenceSystem().registerPreference( "DetachableMenus", make_property_string( g_Layout_enableDetachableMenus.m_latched ) ); + GlobalPreferenceSystem().registerPreference( "PatchToolBar", make_property_string( g_Layout_enablePatchToolbar.m_latched ) ); + GlobalPreferenceSystem().registerPreference( "PluginToolBar", make_property_string( g_Layout_enablePluginToolbar.m_latched ) ); + GlobalPreferenceSystem().registerPreference( "QE4StyleWindows", make_property_string( g_Layout_viewStyle.m_latched ) ); + GlobalPreferenceSystem().registerPreference( "XYHeight", make_property_string( g_layout_globals.nXYHeight ) ); + GlobalPreferenceSystem().registerPreference( "XYWidth", make_property_string( g_layout_globals.nXYWidth ) ); + GlobalPreferenceSystem().registerPreference( "CamWidth", make_property_string( g_layout_globals.nCamWidth ) ); + GlobalPreferenceSystem().registerPreference( "CamHeight", make_property_string( g_layout_globals.nCamHeight ) ); + + GlobalPreferenceSystem().registerPreference( "State", make_property_string( g_layout_globals.nState ) ); + GlobalPreferenceSystem().registerPreference( "PositionX", make_property_string( g_layout_globals.m_position.x ) ); + GlobalPreferenceSystem().registerPreference( "PositionY", make_property_string( g_layout_globals.m_position.y ) ); + GlobalPreferenceSystem().registerPreference( "Width", make_property_string( g_layout_globals.m_position.w ) ); + GlobalPreferenceSystem().registerPreference( "Height", make_property_string( g_layout_globals.m_position.h ) ); + + GlobalPreferenceSystem().registerPreference( "CamWnd", make_property(g_posCamWnd) ); + GlobalPreferenceSystem().registerPreference( "XYWnd", make_property(g_posXYWnd) ); + GlobalPreferenceSystem().registerPreference( "YZWnd", make_property(g_posYZWnd) ); + GlobalPreferenceSystem().registerPreference( "XZWnd", make_property(g_posXZWnd) ); + + { + const char* ENGINEPATH_ATTRIBUTE = #if GDEF_OS_WINDOWS - "enginepath_win32" + "enginepath_win32" #elif GDEF_OS_MACOS - "enginepath_macos" + "enginepath_macos" #elif GDEF_OS_LINUX || GDEF_OS_BSD - "enginepath_linux" + "enginepath_linux" #else #error "unknown platform" #endif - ; - StringOutputStream path(256); - path << DirectoryCleaned(g_pGameDescription->getRequiredKeyValue(ENGINEPATH_ATTRIBUTE)); - g_strEnginePath = path.c_str(); - } + ; + StringOutputStream path( 256 ); + path << DirectoryCleaned( g_pGameDescription->getRequiredKeyValue( ENGINEPATH_ATTRIBUTE ) ); + g_strEnginePath = path.c_str(); + } - GlobalPreferenceSystem().registerPreference("EnginePath", make_property_string(g_strEnginePath)); + GlobalPreferenceSystem().registerPreference( "EnginePath", make_property_string( g_strEnginePath ) ); - GlobalPreferenceSystem().registerPreference("DisableEnginePath", make_property_string(g_disableEnginePath)); - GlobalPreferenceSystem().registerPreference("DisableHomePath", make_property_string(g_disableHomePath)); + GlobalPreferenceSystem().registerPreference( "DisableEnginePath", make_property_string( g_disableEnginePath ) ); + GlobalPreferenceSystem().registerPreference( "DisableHomePath", make_property_string( g_disableHomePath ) ); - for (int i = 0; i < g_pakPathCount; i++) { - std::string label = "PakPath" + std::to_string(i); - GlobalPreferenceSystem().registerPreference(label.c_str(), make_property_string(g_strPakPath[i])); - } + for ( int i = 0; i < g_pakPathCount; i++ ) { + std::string label = "PakPath" + std::to_string( i ); + GlobalPreferenceSystem().registerPreference( label.c_str(), make_property_string( g_strPakPath[i] ) ); + } - g_Layout_viewStyle.useLatched(); - g_Layout_enableDetachableMenus.useLatched(); - g_Layout_enablePatchToolbar.useLatched(); - g_Layout_enablePluginToolbar.useLatched(); + g_Layout_viewStyle.useLatched(); + g_Layout_enableDetachableMenus.useLatched(); + g_Layout_enablePatchToolbar.useLatched(); + g_Layout_enablePluginToolbar.useLatched(); - Layout_registerPreferencesPage(); - Paths_registerPreferencesPage(); + Layout_registerPreferencesPage(); + Paths_registerPreferencesPage(); - g_brushCount.setCountChangedCallback(makeCallbackF(QE_brushCountChanged)); - g_entityCount.setCountChangedCallback(makeCallbackF(QE_entityCountChanged)); - GlobalEntityCreator().setCounter(&g_entityCount); + g_brushCount.setCountChangedCallback( makeCallbackF(QE_brushCountChanged) ); + g_entityCount.setCountChangedCallback( makeCallbackF(QE_entityCountChanged) ); + GlobalEntityCreator().setCounter( &g_entityCount ); - GLWidget_sharedContextCreated = GlobalGL_sharedContextCreated; - GLWidget_sharedContextDestroyed = GlobalGL_sharedContextDestroyed; + GLWidget_sharedContextCreated = GlobalGL_sharedContextCreated; + GLWidget_sharedContextDestroyed = GlobalGL_sharedContextDestroyed; - GlobalEntityClassManager().attach(g_WorldspawnColourEntityClassObserver); + GlobalEntityClassManager().attach( g_WorldspawnColourEntityClassObserver ); } -void MainFrame_Destroy() -{ - GlobalEntityClassManager().detach(g_WorldspawnColourEntityClassObserver); +void MainFrame_Destroy(){ + GlobalEntityClassManager().detach( g_WorldspawnColourEntityClassObserver ); - GlobalEntityCreator().setCounter(0); - g_entityCount.setCountChangedCallback(Callback()); - g_brushCount.setCountChangedCallback(Callback()); + GlobalEntityCreator().setCounter( 0 ); + g_entityCount.setCountChangedCallback( Callback() ); + g_brushCount.setCountChangedCallback( Callback() ); } -void GLWindow_Construct() -{ - GlobalPreferenceSystem().registerPreference("MouseButtons", make_property_string(g_glwindow_globals.m_nMouseType)); +void GLWindow_Construct(){ + GlobalPreferenceSystem().registerPreference( "MouseButtons", make_property_string( g_glwindow_globals.m_nMouseType ) ); } -void GLWindow_Destroy() -{ +void GLWindow_Destroy(){ } diff --git a/radiant/map.cpp b/radiant/map.cpp index 978d83da..6603279f 100644 --- a/radiant/map.cpp +++ b/radiant/map.cpp @@ -27,7 +27,7 @@ #include "imap.h" -MapModules &ReferenceAPI_getMapModules(); +MapModules& ReferenceAPI_getMapModules(); #include "iselection.h" #include "iundo.h" @@ -89,355 +89,328 @@ MapModules &ReferenceAPI_getMapModules(); bool g_writeMapComments = true; -class NameObserver { - UniqueNames &m_names; - CopiedString m_name; +class NameObserver +{ +UniqueNames& m_names; +CopiedString m_name; - void construct() - { - if (!empty()) { - //globalOutputStream() << "construct " << makeQuoted(c_str()) << "\n"; - m_names.insert(name_read(c_str())); - } - } +void construct(){ + if ( !empty() ) { + //globalOutputStream() << "construct " << makeQuoted(c_str()) << "\n"; + m_names.insert( name_read( c_str() ) ); + } +} - void destroy() - { - if (!empty()) { - //globalOutputStream() << "destroy " << makeQuoted(c_str()) << "\n"; - m_names.erase(name_read(c_str())); - } - } +void destroy(){ + if ( !empty() ) { + //globalOutputStream() << "destroy " << makeQuoted(c_str()) << "\n"; + m_names.erase( name_read( c_str() ) ); + } +} - NameObserver &operator=(const NameObserver &other); +NameObserver& operator=( const NameObserver& other ); public: - NameObserver(UniqueNames &names) : m_names(names) - { - construct(); - } - - NameObserver(const NameObserver &other) : m_names(other.m_names), m_name(other.m_name) - { - construct(); - } - - ~NameObserver() - { - destroy(); - } - - bool empty() const - { - return string_empty(c_str()); - } - - const char *c_str() const - { - return m_name.c_str(); - } - - void nameChanged(const char *name) - { - destroy(); - m_name = name; - construct(); - } - - typedef MemberCaller NameChangedCaller; +NameObserver( UniqueNames& names ) : m_names( names ){ + construct(); +} +NameObserver( const NameObserver& other ) : m_names( other.m_names ), m_name( other.m_name ){ + construct(); +} + +~NameObserver(){ + destroy(); +} + +bool empty() const { + return string_empty( c_str() ); +} + +const char* c_str() const { + return m_name.c_str(); +} + +void nameChanged( const char* name ){ + destroy(); + m_name = name; + construct(); +} + +typedef MemberCaller NameChangedCaller; }; -class BasicNamespace : public Namespace { - typedef std::map Names; - Names m_names; - UniqueNames m_uniqueNames; +class BasicNamespace : public Namespace +{ +typedef std::map Names; +Names m_names; +UniqueNames m_uniqueNames; public: - ~BasicNamespace() - { - ASSERT_MESSAGE(m_names.empty(), "namespace: names still registered at shutdown"); - } - - void attach(const NameCallback &setName, const NameCallbackCallback &attachObserver) - { - std::pair result = m_names.insert(Names::value_type(setName, m_uniqueNames)); - ASSERT_MESSAGE(result.second, "cannot attach name"); - attachObserver(NameObserver::NameChangedCaller((*result.first).second)); - //globalOutputStream() << "attach: " << reinterpret_cast(setName) << "\n"; - } - - void detach(const NameCallback &setName, const NameCallbackCallback &detachObserver) - { - Names::iterator i = m_names.find(setName); - ASSERT_MESSAGE(i != m_names.end(), "cannot detach name"); - //globalOutputStream() << "detach: " << reinterpret_cast(setName) << "\n"; - detachObserver(NameObserver::NameChangedCaller((*i).second)); - m_names.erase(i); - } - - void makeUnique(const char *name, const NameCallback &setName) const - { - char buffer[1024]; - name_write(buffer, m_uniqueNames.make_unique(name_read(name))); - setName(buffer); - } - - void mergeNames(const BasicNamespace &other) const - { - typedef std::list SetNameCallbacks; - typedef std::map NameGroups; - NameGroups groups; - - UniqueNames uniqueNames(other.m_uniqueNames); - - for (Names::const_iterator i = m_names.begin(); i != m_names.end(); ++i) { - groups[(*i).second.c_str()].push_back((*i).first); - } - - for (NameGroups::iterator i = groups.begin(); i != groups.end(); ++i) { - name_t uniqueName(uniqueNames.make_unique(name_read((*i).first.c_str()))); - uniqueNames.insert(uniqueName); - - char buffer[1024]; - name_write(buffer, uniqueName); - - //globalOutputStream() << "renaming " << makeQuoted((*i).first.c_str()) << " to " << makeQuoted(buffer) << "\n"; - - SetNameCallbacks &setNameCallbacks = (*i).second; - - for (SetNameCallbacks::const_iterator j = setNameCallbacks.begin(); j != setNameCallbacks.end(); ++j) { - (*j)(buffer); - } - } - } +~BasicNamespace(){ + ASSERT_MESSAGE( m_names.empty(), "namespace: names still registered at shutdown" ); +} + +void attach( const NameCallback& setName, const NameCallbackCallback& attachObserver ){ + std::pair result = m_names.insert( Names::value_type( setName, m_uniqueNames ) ); + ASSERT_MESSAGE( result.second, "cannot attach name" ); + attachObserver( NameObserver::NameChangedCaller( ( *result.first ).second ) ); + //globalOutputStream() << "attach: " << reinterpret_cast(setName) << "\n"; +} + +void detach( const NameCallback& setName, const NameCallbackCallback& detachObserver ){ + Names::iterator i = m_names.find( setName ); + ASSERT_MESSAGE( i != m_names.end(), "cannot detach name" ); + //globalOutputStream() << "detach: " << reinterpret_cast(setName) << "\n"; + detachObserver( NameObserver::NameChangedCaller( ( *i ).second ) ); + m_names.erase( i ); +} + +void makeUnique( const char* name, const NameCallback& setName ) const { + char buffer[1024]; + name_write( buffer, m_uniqueNames.make_unique( name_read( name ) ) ); + setName( buffer ); +} + +void mergeNames( const BasicNamespace& other ) const { + typedef std::list SetNameCallbacks; + typedef std::map NameGroups; + NameGroups groups; + + UniqueNames uniqueNames( other.m_uniqueNames ); + + for ( Names::const_iterator i = m_names.begin(); i != m_names.end(); ++i ) + { + groups[( *i ).second.c_str()].push_back( ( *i ).first ); + } + + for ( NameGroups::iterator i = groups.begin(); i != groups.end(); ++i ) + { + name_t uniqueName( uniqueNames.make_unique( name_read( ( *i ).first.c_str() ) ) ); + uniqueNames.insert( uniqueName ); + + char buffer[1024]; + name_write( buffer, uniqueName ); + + //globalOutputStream() << "renaming " << makeQuoted((*i).first.c_str()) << " to " << makeQuoted(buffer) << "\n"; + + SetNameCallbacks& setNameCallbacks = ( *i ).second; + + for ( SetNameCallbacks::const_iterator j = setNameCallbacks.begin(); j != setNameCallbacks.end(); ++j ) + { + ( *j )( buffer ); + } + } +} }; BasicNamespace g_defaultNamespace; BasicNamespace g_cloneNamespace; -class NamespaceAPI { - Namespace *m_namespace; +class NamespaceAPI +{ +Namespace* m_namespace; public: - typedef Namespace Type; +typedef Namespace Type; - STRING_CONSTANT(Name, "*"); +STRING_CONSTANT( Name, "*" ); - NamespaceAPI() - { - m_namespace = &g_defaultNamespace; - } +NamespaceAPI(){ + m_namespace = &g_defaultNamespace; +} - Namespace *getTable() - { - return m_namespace; - } +Namespace* getTable(){ + return m_namespace; +} }; typedef SingletonModule NamespaceModule; typedef Static StaticNamespaceModule; -StaticRegisterModule staticRegisterDefaultNamespace(StaticNamespaceModule::instance()); +StaticRegisterModule staticRegisterDefaultNamespace( StaticNamespaceModule::instance() ); -std::list g_cloned; +std::list g_cloned; -inline Namespaced *Node_getNamespaced(scene::Node &node) -{ - return NodeTypeCast::cast(node); +inline Namespaced* Node_getNamespaced( scene::Node& node ){ + return NodeTypeCast::cast( node ); } -void Node_gatherNamespaced(scene::Node &node) -{ - Namespaced *namespaced = Node_getNamespaced(node); - if (namespaced != 0) { - g_cloned.push_back(namespaced); - } +void Node_gatherNamespaced( scene::Node& node ){ + Namespaced* namespaced = Node_getNamespaced( node ); + if ( namespaced != 0 ) { + g_cloned.push_back( namespaced ); + } } -class GatherNamespaced : public scene::Traversable::Walker { +class GatherNamespaced : public scene::Traversable::Walker +{ public: - bool pre(scene::Node &node) const - { - Node_gatherNamespaced(node); - return true; - } +bool pre( scene::Node& node ) const { + Node_gatherNamespaced( node ); + return true; +} }; -void Map_gatherNamespaced(scene::Node &root) -{ - Node_traverseSubgraph(root, GatherNamespaced()); +void Map_gatherNamespaced( scene::Node& root ){ + Node_traverseSubgraph( root, GatherNamespaced() ); } -void Map_mergeClonedNames() -{ - for (std::list::const_iterator i = g_cloned.begin(); i != g_cloned.end(); ++i) { - (*i)->setNamespace(g_cloneNamespace); - } - g_cloneNamespace.mergeNames(g_defaultNamespace); - for (std::list::const_iterator i = g_cloned.begin(); i != g_cloned.end(); ++i) { - (*i)->setNamespace(g_defaultNamespace); - } +void Map_mergeClonedNames(){ + for ( std::list::const_iterator i = g_cloned.begin(); i != g_cloned.end(); ++i ) + { + ( *i )->setNamespace( g_cloneNamespace ); + } + g_cloneNamespace.mergeNames( g_defaultNamespace ); + for ( std::list::const_iterator i = g_cloned.begin(); i != g_cloned.end(); ++i ) + { + ( *i )->setNamespace( g_defaultNamespace ); + } - g_cloned.clear(); + g_cloned.clear(); } -class WorldNode { - scene::Node *m_node; +class WorldNode +{ +scene::Node* m_node; public: - WorldNode() - : m_node(0) - { - } - - void set(scene::Node *node) - { - if (m_node != 0) { - m_node->DecRef(); - } - m_node = node; - if (m_node != 0) { - m_node->IncRef(); - } - } - - scene::Node *get() const - { - return m_node; - } +WorldNode() + : m_node( 0 ){ +} + +void set( scene::Node* node ){ + if ( m_node != 0 ) { + m_node->DecRef(); + } + m_node = node; + if ( m_node != 0 ) { + m_node->IncRef(); + } +} + +scene::Node* get() const { + return m_node; +} }; class Map; +void Map_SetValid( Map& map, bool valid ); -void Map_SetValid(Map &map, bool valid); - -void Map_UpdateTitle(const Map &map); +void Map_UpdateTitle( const Map& map ); -void Map_SetWorldspawn(Map &map, scene::Node *node); +void Map_SetWorldspawn( Map& map, scene::Node* node ); -class Map : public ModuleObserver { +class Map : public ModuleObserver +{ public: - CopiedString m_name; - Resource *m_resource; - bool m_valid; +CopiedString m_name; +Resource* m_resource; +bool m_valid; - bool m_modified; +bool m_modified; - void ( *m_modified_changed )(const Map &); +void ( *m_modified_changed )( const Map& ); - Signal0 m_mapValidCallbacks; +Signal0 m_mapValidCallbacks; - WorldNode m_world_node; // "classname" "worldspawn" ! +WorldNode m_world_node; // "classname" "worldspawn" ! - Map() : m_resource(0), m_valid(false), m_modified_changed(Map_UpdateTitle) - { - } +Map() : m_resource( 0 ), m_valid( false ), m_modified_changed( Map_UpdateTitle ){ +} - void realise() - { - if (m_resource != 0) { - if (Map_Unnamed(*this)) { - g_map.m_resource->setNode(NewMapRoot("").get_pointer()); - MapFile *map = Node_getMapFile(*g_map.m_resource->getNode()); - if (map != 0) { - map->save(); - } - } else { - m_resource->load(); - } +void realise(){ + if ( m_resource != 0 ) { + if ( Map_Unnamed( *this ) ) { + g_map.m_resource->setNode( NewMapRoot( "" ).get_pointer() ); + MapFile* map = Node_getMapFile( *g_map.m_resource->getNode() ); + if ( map != 0 ) { + map->save(); + } + } + else + { + m_resource->load(); + } - GlobalSceneGraph().insert_root(*m_resource->getNode()); + GlobalSceneGraph().insert_root( *m_resource->getNode() ); - AutoSave_clear(); + AutoSave_clear(); - Map_SetValid(g_map, true); - } - } + Map_SetValid( g_map, true ); + } +} - void unrealise() - { - if (m_resource != 0) { - Map_SetValid(g_map, false); - Map_SetWorldspawn(g_map, 0); +void unrealise(){ + if ( m_resource != 0 ) { + Map_SetValid( g_map, false ); + Map_SetWorldspawn( g_map, 0 ); - GlobalUndoSystem().clear(); + GlobalUndoSystem().clear(); - GlobalSceneGraph().erase_root(); - } - } + GlobalSceneGraph().erase_root(); + } +} }; Map g_map; -Map *g_currentMap = 0; +Map* g_currentMap = 0; -void Map_addValidCallback(Map &map, const SignalHandler &handler) -{ - map.m_mapValidCallbacks.connectLast(handler); +void Map_addValidCallback( Map& map, const SignalHandler& handler ){ + map.m_mapValidCallbacks.connectLast( handler ); } -bool Map_Valid(const Map &map) -{ - return map.m_valid; +bool Map_Valid( const Map& map ){ + return map.m_valid; } -void Map_SetValid(Map &map, bool valid) -{ - map.m_valid = valid; - map.m_mapValidCallbacks(); +void Map_SetValid( Map& map, bool valid ){ + map.m_valid = valid; + map.m_mapValidCallbacks(); } -const char *Map_Name(const Map &map) -{ - return map.m_name.c_str(); +const char* Map_Name( const Map& map ){ + return map.m_name.c_str(); } -bool Map_Unnamed(const Map &map) -{ - return string_equal(Map_Name(map), "unnamed.map"); +bool Map_Unnamed( const Map& map ){ + return string_equal( Map_Name( map ), "unnamed.map" ); } -inline const MapFormat &MapFormat_forFile(const char *filename) -{ - const char *moduleName = findModuleName(GetFileTypeRegistry(), MapFormat::Name(), path_get_extension(filename)); - MapFormat *format = Radiant_getMapModules().findModule(moduleName); - ASSERT_MESSAGE(format != 0, "map format not found for file " << makeQuoted(filename)); - return *format; +inline const MapFormat& MapFormat_forFile( const char* filename ){ + const char* moduleName = findModuleName( GetFileTypeRegistry(), MapFormat::Name(), path_get_extension( filename ) ); + MapFormat* format = Radiant_getMapModules().findModule( moduleName ); + ASSERT_MESSAGE( format != 0, "map format not found for file " << makeQuoted( filename ) ); + return *format; } -const MapFormat &Map_getFormat(const Map &map) -{ - return MapFormat_forFile(Map_Name(map)); +const MapFormat& Map_getFormat( const Map& map ){ + return MapFormat_forFile( Map_Name( map ) ); } -bool Map_Modified(const Map &map) -{ - return map.m_modified; +bool Map_Modified( const Map& map ){ + return map.m_modified; } -void Map_SetModified(Map &map, bool modified) -{ - if (map.m_modified ^ modified) { - map.m_modified = modified; +void Map_SetModified( Map& map, bool modified ){ + if ( map.m_modified ^ modified ) { + map.m_modified = modified; - map.m_modified_changed(map); - } + map.m_modified_changed( map ); + } } -void Map_UpdateTitle(const Map &map) -{ - Sys_SetTitle(map.m_name.c_str(), Map_Modified(map)); +void Map_UpdateTitle( const Map& map ){ + Sys_SetTitle( map.m_name.c_str(), Map_Modified( map ) ); } -scene::Node *Map_GetWorldspawn(const Map &map) -{ - return map.m_world_node.get(); +scene::Node* Map_GetWorldspawn( const Map& map ){ + return map.m_world_node.get(); } -void Map_SetWorldspawn(Map &map, scene::Node *node) -{ - map.m_world_node.set(node); +void Map_SetWorldspawn( Map& map, scene::Node* node ){ + map.m_world_node.set( node ); } @@ -446,9 +419,9 @@ void Map_SetWorldspawn(Map &map, scene::Node *node) float g_MaxWorldCoord = 64 * 1024; float g_MinWorldCoord = -64 * 1024; -void AddRegionBrushes(void); +void AddRegionBrushes( void ); -void RemoveRegionBrushes(void); +void RemoveRegionBrushes( void ); /* @@ -457,68 +430,65 @@ void RemoveRegionBrushes(void); free all map elements, reinitialize the structures that depend on them ================ */ -void Map_Free() -{ - Pointfile_Clear(); +void Map_Free(){ + Pointfile_Clear(); - g_map.m_resource->detach(g_map); - GlobalReferenceCache().release(g_map.m_name.c_str()); - g_map.m_resource = 0; + g_map.m_resource->detach( g_map ); + GlobalReferenceCache().release( g_map.m_name.c_str() ); + g_map.m_resource = 0; - FlushReferences(); + FlushReferences(); - g_currentMap = 0; - Brush_unlatchPreferences(); + g_currentMap = 0; + Brush_unlatchPreferences(); } -class EntityFindByClassname : public scene::Graph::Walker { - const char *m_name; - Entity *&m_entity; +class EntityFindByClassname : public scene::Graph::Walker +{ +const char* m_name; +Entity*& m_entity; public: - EntityFindByClassname(const char *name, Entity *&entity) : m_name(name), m_entity(entity) - { - m_entity = 0; - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - if (m_entity == 0) { - Entity *entity = Node_getEntity(path.top()); - if (entity != 0 - && string_equal(m_name, entity->getKeyValue("classname"))) { - m_entity = entity; - } - } - return true; - } -}; +EntityFindByClassname( const char* name, Entity*& entity ) : m_name( name ), m_entity( entity ){ + m_entity = 0; +} -Entity *Scene_FindEntityByClass(const char *name) -{ - Entity *entity; - GlobalSceneGraph().traverse(EntityFindByClassname(name, entity)); - return entity; +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( m_entity == 0 ) { + Entity* entity = Node_getEntity( path.top() ); + if ( entity != 0 + && string_equal( m_name, entity->getKeyValue( "classname" ) ) ) { + m_entity = entity; + } + } + return true; } +}; -Entity *Scene_FindPlayerStart() -{ - typedef const char *StaticString; - StaticString strings[] = { - "info_player_start", - "info_player_deathmatch", - "team_CTF_redplayer", - "team_CTF_blueplayer", - "team_CTF_redspawn", - "team_CTF_bluespawn", - }; - typedef const StaticString *StaticStringIterator; - for (StaticStringIterator i = strings, end = strings + (sizeof(strings) / sizeof(StaticString)); i != end; ++i) { - Entity *entity = Scene_FindEntityByClass(*i); - if (entity != 0) { - return entity; - } - } - return 0; +Entity* Scene_FindEntityByClass( const char* name ){ + Entity* entity; + GlobalSceneGraph().traverse( EntityFindByClassname( name, entity ) ); + return entity; +} + +Entity *Scene_FindPlayerStart(){ + typedef const char* StaticString; + StaticString strings[] = { + "info_player_start", + "info_player_deathmatch", + "team_CTF_redplayer", + "team_CTF_blueplayer", + "team_CTF_redspawn", + "team_CTF_bluespawn", + }; + typedef const StaticString* StaticStringIterator; + for ( StaticStringIterator i = strings, end = strings + ( sizeof( strings ) / sizeof( StaticString ) ); i != end; ++i ) + { + Entity* entity = Scene_FindEntityByClass( *i ); + if ( entity != 0 ) { + return entity; + } + } + return 0; } // @@ -526,469 +496,453 @@ Entity *Scene_FindPlayerStart() // -void FocusViews(const Vector3 &point, float angle) -{ - CamWnd &camwnd = *g_pParentWnd->GetCamWnd(); - Camera_setOrigin(camwnd, point); - Vector3 angles(Camera_getAngles(camwnd)); - angles[CAMERA_PITCH] = 0; - angles[CAMERA_YAW] = angle; - Camera_setAngles(camwnd, angles); +void FocusViews( const Vector3& point, float angle ){ + CamWnd& camwnd = *g_pParentWnd->GetCamWnd(); + Camera_setOrigin( camwnd, point ); + Vector3 angles( Camera_getAngles( camwnd ) ); + angles[CAMERA_PITCH] = 0; + angles[CAMERA_YAW] = angle; + Camera_setAngles( camwnd, angles ); - XYWnd *xywnd = g_pParentWnd->GetXYWnd(); - xywnd->SetOrigin(point); + XYWnd* xywnd = g_pParentWnd->GetXYWnd(); + xywnd->SetOrigin( point ); } #include "stringio.h" -void Map_StartPosition() -{ - Entity *entity = Scene_FindPlayerStart(); +void Map_StartPosition(){ + Entity* entity = Scene_FindPlayerStart(); - if (entity) { - Vector3 origin; - string_parse_vector3(entity->getKeyValue("origin"), origin); - FocusViews(origin, string_read_float(entity->getKeyValue("angle"))); - } else { - FocusViews(g_vector3_identity, 0); - } + if ( entity ) { + Vector3 origin; + string_parse_vector3( entity->getKeyValue( "origin" ), origin ); + FocusViews( origin, string_read_float( entity->getKeyValue( "angle" ) ) ); + } + else + { + FocusViews( g_vector3_identity, 0 ); + } } -inline bool node_is_worldspawn(scene::Node &node) -{ - Entity *entity = Node_getEntity(node); - return entity != 0 && string_equal(entity->getKeyValue("classname"), "worldspawn"); +inline bool node_is_worldspawn( scene::Node& node ){ + Entity* entity = Node_getEntity( node ); + return entity != 0 && string_equal( entity->getKeyValue( "classname" ), "worldspawn" ); } // use first worldspawn -class entity_updateworldspawn : public scene::Traversable::Walker { +class entity_updateworldspawn : public scene::Traversable::Walker +{ public: - bool pre(scene::Node &node) const - { - if (node_is_worldspawn(node)) { - if (Map_GetWorldspawn(g_map) == 0) { - Map_SetWorldspawn(g_map, &node); - } - } - return false; - } +bool pre( scene::Node& node ) const { + if ( node_is_worldspawn( node ) ) { + if ( Map_GetWorldspawn( g_map ) == 0 ) { + Map_SetWorldspawn( g_map, &node ); + } + } + return false; +} }; -scene::Node *Map_FindWorldspawn(Map &map) -{ - Map_SetWorldspawn(map, 0); +scene::Node* Map_FindWorldspawn( Map& map ){ + Map_SetWorldspawn( map, 0 ); - Node_getTraversable(GlobalSceneGraph().root())->traverse(entity_updateworldspawn()); + Node_getTraversable( GlobalSceneGraph().root() )->traverse( entity_updateworldspawn() ); - return Map_GetWorldspawn(map); + return Map_GetWorldspawn( map ); } -class CollectAllWalker : public scene::Traversable::Walker { - scene::Node &m_root; - UnsortedNodeSet &m_nodes; +class CollectAllWalker : public scene::Traversable::Walker +{ +scene::Node& m_root; +UnsortedNodeSet& m_nodes; public: - CollectAllWalker(scene::Node &root, UnsortedNodeSet &nodes) : m_root(root), m_nodes(nodes) - { - } - - bool pre(scene::Node &node) const - { - m_nodes.insert(NodeSmartReference(node)); - Node_getTraversable(m_root)->erase(node); - return false; - } +CollectAllWalker( scene::Node& root, UnsortedNodeSet& nodes ) : m_root( root ), m_nodes( nodes ){ +} + +bool pre( scene::Node& node ) const { + m_nodes.insert( NodeSmartReference( node ) ); + Node_getTraversable( m_root )->erase( node ); + return false; +} }; -void Node_insertChildFirst(scene::Node &parent, scene::Node &child) -{ - UnsortedNodeSet nodes; - Node_getTraversable(parent)->traverse(CollectAllWalker(parent, nodes)); - Node_getTraversable(parent)->insert(child); +void Node_insertChildFirst( scene::Node& parent, scene::Node& child ){ + UnsortedNodeSet nodes; + Node_getTraversable( parent )->traverse( CollectAllWalker( parent, nodes ) ); + Node_getTraversable( parent )->insert( child ); - for (UnsortedNodeSet::iterator i = nodes.begin(); i != nodes.end(); ++i) { - Node_getTraversable(parent)->insert((*i)); - } + for ( UnsortedNodeSet::iterator i = nodes.begin(); i != nodes.end(); ++i ) + { + Node_getTraversable( parent )->insert( ( *i ) ); + } } -scene::Node &createWorldspawn() -{ - NodeSmartReference worldspawn( - GlobalEntityCreator().createEntity(GlobalEntityClassManager().findOrInsert("worldspawn", true))); - Node_insertChildFirst(GlobalSceneGraph().root(), worldspawn); - return worldspawn; +scene::Node& createWorldspawn(){ + NodeSmartReference worldspawn( GlobalEntityCreator().createEntity( GlobalEntityClassManager().findOrInsert( "worldspawn", true ) ) ); + Node_insertChildFirst( GlobalSceneGraph().root(), worldspawn ); + return worldspawn; } -void Map_UpdateWorldspawn(Map &map) -{ - if (Map_FindWorldspawn(map) == 0) { - Map_SetWorldspawn(map, &createWorldspawn()); - } +void Map_UpdateWorldspawn( Map& map ){ + if ( Map_FindWorldspawn( map ) == 0 ) { + Map_SetWorldspawn( map, &createWorldspawn() ); + } +} + +scene::Node& Map_FindOrInsertWorldspawn( Map& map ){ + Map_UpdateWorldspawn( map ); + return *Map_GetWorldspawn( map ); } -scene::Node &Map_FindOrInsertWorldspawn(Map &map) + +class MapMergeAll : public scene::Traversable::Walker { - Map_UpdateWorldspawn(map); - return *Map_GetWorldspawn(map); +mutable scene::Path m_path; +public: +MapMergeAll( const scene::Path& root ) + : m_path( root ){ } +bool pre( scene::Node& node ) const { + Node_getTraversable( m_path.top() )->insert( node ); + m_path.push( makeReference( node ) ); + selectPath( m_path, true ); + return false; +} -class MapMergeAll : public scene::Traversable::Walker { - mutable scene::Path m_path; +void post( scene::Node& node ) const { + m_path.pop(); +} +}; + +class MapMergeEntities : public scene::Traversable::Walker +{ +mutable scene::Path m_path; public: - MapMergeAll(const scene::Path &root) - : m_path(root) - { - } - - bool pre(scene::Node &node) const - { - Node_getTraversable(m_path.top())->insert(node); - m_path.push(makeReference(node)); - selectPath(m_path, true); - return false; - } - - void post(scene::Node &node) const - { - m_path.pop(); - } +MapMergeEntities( const scene::Path& root ) + : m_path( root ){ +} + +bool pre( scene::Node& node ) const { + if ( node_is_worldspawn( node ) ) { + scene::Node* world_node = Map_FindWorldspawn( g_map ); + if ( world_node == 0 ) { + Map_SetWorldspawn( g_map, &node ); + Node_getTraversable( m_path.top().get() )->insert( node ); + m_path.push( makeReference( node ) ); + Node_getTraversable( node )->traverse( SelectChildren( m_path ) ); + } + else + { + m_path.push( makeReference( *world_node ) ); + Node_getTraversable( node )->traverse( MapMergeAll( m_path ) ); + } + } + else + { + Node_getTraversable( m_path.top() )->insert( node ); + m_path.push( makeReference( node ) ); + if ( node_is_group( node ) ) { + Node_getTraversable( node )->traverse( SelectChildren( m_path ) ); + } + else + { + selectPath( m_path, true ); + } + } + return false; +} + +void post( scene::Node& node ) const { + m_path.pop(); +} }; -class MapMergeEntities : public scene::Traversable::Walker { - mutable scene::Path m_path; +class BasicContainer : public scene::Node::Symbiot +{ +class TypeCasts +{ +NodeTypeCastTable m_casts; public: - MapMergeEntities(const scene::Path &root) - : m_path(root) - { - } - - bool pre(scene::Node &node) const - { - if (node_is_worldspawn(node)) { - scene::Node *world_node = Map_FindWorldspawn(g_map); - if (world_node == 0) { - Map_SetWorldspawn(g_map, &node); - Node_getTraversable(m_path.top().get())->insert(node); - m_path.push(makeReference(node)); - Node_getTraversable(node)->traverse(SelectChildren(m_path)); - } else { - m_path.push(makeReference(*world_node)); - Node_getTraversable(node)->traverse(MapMergeAll(m_path)); - } - } else { - Node_getTraversable(m_path.top())->insert(node); - m_path.push(makeReference(node)); - if (node_is_group(node)) { - Node_getTraversable(node)->traverse(SelectChildren(m_path)); - } else { - selectPath(m_path, true); - } - } - return false; - } - - void post(scene::Node &node) const - { - m_path.pop(); - } +TypeCasts(){ + NodeContainedCast::install( m_casts ); +} + +NodeTypeCastTable& get(){ + return m_casts; +} }; -class BasicContainer : public scene::Node::Symbiot { - class TypeCasts { - NodeTypeCastTable m_casts; - public: - TypeCasts() - { - NodeContainedCast::install(m_casts); - } - - NodeTypeCastTable &get() - { - return m_casts; - } - }; - - scene::Node m_node; - TraversableNodeSet m_traverse; +scene::Node m_node; +TraversableNodeSet m_traverse; public: - typedef LazyStatic StaticTypeCasts; +typedef LazyStatic StaticTypeCasts; - scene::Traversable &get(NullType) - { - return m_traverse; - } +scene::Traversable& get( NullType){ + return m_traverse; +} - BasicContainer() : m_node(this, this, StaticTypeCasts::instance().get()) - { - } +BasicContainer() : m_node( this, this, StaticTypeCasts::instance().get() ){ +} - void release() - { - delete this; - } +void release(){ + delete this; +} - scene::Node &node() - { - return m_node; - } +scene::Node& node(){ + return m_node; +} }; /// Merges the map graph rooted at \p node into the global scene-graph. -void MergeMap(scene::Node &node) -{ - Node_getTraversable(node)->traverse(MapMergeEntities(scene::Path(makeReference(GlobalSceneGraph().root())))); +void MergeMap( scene::Node& node ){ + Node_getTraversable( node )->traverse( MapMergeEntities( scene::Path( makeReference( GlobalSceneGraph().root() ) ) ) ); } -void Map_ImportSelected(TextInputStream &in, const MapFormat &format) -{ - NodeSmartReference node((new BasicContainer)->node()); - format.readGraph(node, in, GlobalEntityCreator()); - Map_gatherNamespaced(node); - Map_mergeClonedNames(); - MergeMap(node); +void Map_ImportSelected( TextInputStream& in, const MapFormat& format ){ + NodeSmartReference node( ( new BasicContainer )->node() ); + format.readGraph( node, in, GlobalEntityCreator() ); + Map_gatherNamespaced( node ); + Map_mergeClonedNames(); + MergeMap( node ); } -inline scene::Cloneable *Node_getCloneable(scene::Node &node) -{ - return NodeTypeCast::cast(node); +inline scene::Cloneable* Node_getCloneable( scene::Node& node ){ + return NodeTypeCast::cast( node ); } -inline scene::Node &node_clone(scene::Node &node) -{ - scene::Cloneable *cloneable = Node_getCloneable(node); - if (cloneable != 0) { - return cloneable->clone(); - } +inline scene::Node& node_clone( scene::Node& node ){ + scene::Cloneable* cloneable = Node_getCloneable( node ); + if ( cloneable != 0 ) { + return cloneable->clone(); + } - return (new scene::NullNode)->node(); + return ( new scene::NullNode )->node(); } -class CloneAll : public scene::Traversable::Walker { - mutable scene::Path m_path; +class CloneAll : public scene::Traversable::Walker +{ +mutable scene::Path m_path; public: - CloneAll(scene::Node &root) - : m_path(makeReference(root)) - { - } - - bool pre(scene::Node &node) const - { - if (node.isRoot()) { - return false; - } - - m_path.push(makeReference(node_clone(node))); - m_path.top().get().IncRef(); - - return true; - } - - void post(scene::Node &node) const - { - if (node.isRoot()) { - return; - } - - Node_getTraversable(m_path.parent())->insert(m_path.top()); - - m_path.top().get().DecRef(); - m_path.pop(); - } +CloneAll( scene::Node& root ) + : m_path( makeReference( root ) ){ +} + +bool pre( scene::Node& node ) const { + if ( node.isRoot() ) { + return false; + } + + m_path.push( makeReference( node_clone( node ) ) ); + m_path.top().get().IncRef(); + + return true; +} + +void post( scene::Node& node ) const { + if ( node.isRoot() ) { + return; + } + + Node_getTraversable( m_path.parent() )->insert( m_path.top() ); + + m_path.top().get().DecRef(); + m_path.pop(); +} }; -scene::Node &Node_Clone(scene::Node &node) -{ - scene::Node &clone = node_clone(node); - scene::Traversable *traversable = Node_getTraversable(node); - if (traversable != 0) { - traversable->traverse(CloneAll(clone)); - } - return clone; +scene::Node& Node_Clone( scene::Node& node ){ + scene::Node& clone = node_clone( node ); + scene::Traversable* traversable = Node_getTraversable( node ); + if ( traversable != 0 ) { + traversable->traverse( CloneAll( clone ) ); + } + return clone; } typedef std::map EntityBreakdown; -class EntityBreakdownWalker : public scene::Graph::Walker { - EntityBreakdown &m_entitymap; +class EntityBreakdownWalker : public scene::Graph::Walker +{ +EntityBreakdown& m_entitymap; public: - EntityBreakdownWalker(EntityBreakdown &entitymap) - : m_entitymap(entitymap) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - Entity *entity = Node_getEntity(path.top()); - if (entity != 0) { - const EntityClass &eclass = entity->getEntityClass(); - if (m_entitymap.find(eclass.name()) == m_entitymap.end()) { - m_entitymap[eclass.name()] = 1; - } else { ++m_entitymap[eclass.name()]; } - } - return true; - } +EntityBreakdownWalker( EntityBreakdown& entitymap ) + : m_entitymap( entitymap ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + Entity* entity = Node_getEntity( path.top() ); + if ( entity != 0 ) { + const EntityClass& eclass = entity->getEntityClass(); + if ( m_entitymap.find( eclass.name() ) == m_entitymap.end() ) { + m_entitymap[eclass.name()] = 1; + } else + { + ++m_entitymap[eclass.name()]; + } + } + return true; +} }; -void Scene_EntityBreakdown(EntityBreakdown &entitymap) -{ - GlobalSceneGraph().traverse(EntityBreakdownWalker(entitymap)); +void Scene_EntityBreakdown( EntityBreakdown& entitymap ){ + GlobalSceneGraph().traverse( EntityBreakdownWalker( entitymap ) ); } -WindowPosition g_posMapInfoWnd(c_default_window_pos); +WindowPosition g_posMapInfoWnd( c_default_window_pos ); -void DoMapInfo() -{ - ModalDialog dialog; - ui::Entry brushes_entry{ui::null}; - ui::Entry entities_entry{ui::null}; - ui::ListStore EntityBreakdownWalker{ui::null}; +void DoMapInfo(){ + ModalDialog dialog; + ui::Entry brushes_entry{ui::null}; + ui::Entry entities_entry{ui::null}; + ui::ListStore EntityBreakdownWalker{ui::null}; - ui::Window window = MainFrame_getWindow().create_dialog_window("Map Info", G_CALLBACK(dialog_delete_callback), - &dialog); + ui::Window window = MainFrame_getWindow().create_dialog_window("Map Info", G_CALLBACK(dialog_delete_callback ), &dialog ); - window_set_position(window, g_posMapInfoWnd); + window_set_position( window, g_posMapInfoWnd ); - { - auto vbox = create_dialog_vbox(4, 4); - window.add(vbox); + { + auto vbox = create_dialog_vbox( 4, 4 ); + window.add(vbox); - { - auto hbox = create_dialog_hbox(4); - vbox.pack_start(hbox, FALSE, TRUE, 0); + { + auto hbox = create_dialog_hbox( 4 ); + vbox.pack_start( hbox, FALSE, TRUE, 0 ); - { - auto table = create_dialog_table(2, 2, 4, 4); - hbox.pack_start(table, TRUE, TRUE, 0); + { + auto table = create_dialog_table( 2, 2, 4, 4 ); + hbox.pack_start( table, TRUE, TRUE, 0 ); - { - auto entry = ui::Entry(ui::New); - entry.show(); + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE); + gtk_editable_set_editable( GTK_EDITABLE(entry), FALSE ); - brushes_entry = entry; - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + brushes_entry = entry; + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE); + gtk_editable_set_editable( GTK_EDITABLE(entry), FALSE ); - entities_entry = entry; - } - { - ui::Widget label = ui::Label("Total Brushes"); - label.show(); + entities_entry = entry; + } + { + ui::Widget label = ui::Label( "Total Brushes" ); + label.show(); table.attach(label, {0, 1, 0, 1}, {GTK_FILL, 0}); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - } - { - ui::Widget label = ui::Label("Total Entities"); - label.show(); + gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); + } + { + ui::Widget label = ui::Label( "Total Entities" ); + label.show(); table.attach(label, {0, 1, 1, 2}, {GTK_FILL, 0}); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - } - } - { - auto vbox2 = create_dialog_vbox(4); - hbox.pack_start(vbox2, FALSE, FALSE, 0); - - { - auto button = create_dialog_button("Close", G_CALLBACK(dialog_button_ok), &dialog); - vbox2.pack_start(button, FALSE, FALSE, 0); - } - } - } - { - ui::Widget label = ui::Label("Entity breakdown"); - label.show(); - vbox.pack_start(label, FALSE, TRUE, 0); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - } - { - auto scr = create_scrolled_window(ui::Policy::NEVER, ui::Policy::AUTOMATIC, 4); - vbox.pack_start(scr, TRUE, TRUE, 0); - - { - auto store = ui::ListStore::from(gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING)); - - auto view = ui::TreeView(ui::TreeModel::from(store._handle)); - gtk_tree_view_set_headers_clickable(view, TRUE); - - { - auto renderer = ui::CellRendererText(ui::New); - auto column = ui::TreeViewColumn("Entity", renderer, {{"text", 0}}); - gtk_tree_view_append_column(view, column); - gtk_tree_view_column_set_sort_column_id(column, 0); - } - - { - auto renderer = ui::CellRendererText(ui::New); - auto column = ui::TreeViewColumn("Count", renderer, {{"text", 1}}); - gtk_tree_view_append_column(view, column); - gtk_tree_view_column_set_sort_column_id(column, 1); - } - - view.show(); - - scr.add(view); - - EntityBreakdownWalker = store; - } - } - } - - // Initialize fields - - { - EntityBreakdown entitymap; - Scene_EntityBreakdown(entitymap); - - for (EntityBreakdown::iterator i = entitymap.begin(); i != entitymap.end(); ++i) { - char tmp[16]; - sprintf(tmp, "%u", Unsigned((*i).second)); - EntityBreakdownWalker.append(0, (*i).first.c_str(), 1, tmp); - } - } - - EntityBreakdownWalker.unref(); - - char tmp[16]; - sprintf(tmp, "%u", Unsigned(g_brushCount.get())); - brushes_entry.text(tmp); - sprintf(tmp, "%u", Unsigned(g_entityCount.get())); - entities_entry.text(tmp); - - modal_dialog_show(window, dialog); - - // save before exit - window_get_position(window, g_posMapInfoWnd); + gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); + } + } + { + auto vbox2 = create_dialog_vbox( 4 ); + hbox.pack_start( vbox2, FALSE, FALSE, 0 ); + + { + auto button = create_dialog_button( "Close", G_CALLBACK( dialog_button_ok ), &dialog ); + vbox2.pack_start( button, FALSE, FALSE, 0 ); + } + } + } + { + ui::Widget label = ui::Label( "Entity breakdown" ); + label.show(); + vbox.pack_start( label, FALSE, TRUE, 0 ); + gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 ); + } + { + auto scr = create_scrolled_window( ui::Policy::NEVER, ui::Policy::AUTOMATIC, 4 ); + vbox.pack_start( scr, TRUE, TRUE, 0 ); + + { + auto store = ui::ListStore::from(gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_STRING )); + + auto view = ui::TreeView(ui::TreeModel::from(store._handle)); + gtk_tree_view_set_headers_clickable(view, TRUE ); + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn( "Entity", renderer, {{"text", 0}} ); + gtk_tree_view_append_column(view, column ); + gtk_tree_view_column_set_sort_column_id( column, 0 ); + } + + { + auto renderer = ui::CellRendererText(ui::New); + auto column = ui::TreeViewColumn( "Count", renderer, {{"text", 1}} ); + gtk_tree_view_append_column(view, column ); + gtk_tree_view_column_set_sort_column_id( column, 1 ); + } + + view.show(); + + scr.add(view); + + EntityBreakdownWalker = store; + } + } + } + + // Initialize fields + + { + EntityBreakdown entitymap; + Scene_EntityBreakdown( entitymap ); + + for ( EntityBreakdown::iterator i = entitymap.begin(); i != entitymap.end(); ++i ) + { + char tmp[16]; + sprintf( tmp, "%u", Unsigned( ( *i ).second ) ); + EntityBreakdownWalker.append(0, (*i).first.c_str(), 1, tmp); + } + } + + EntityBreakdownWalker.unref(); + + char tmp[16]; + sprintf( tmp, "%u", Unsigned( g_brushCount.get() ) ); + brushes_entry.text(tmp); + sprintf( tmp, "%u", Unsigned( g_entityCount.get() ) ); + entities_entry.text(tmp); + + modal_dialog_show( window, dialog ); + + // save before exit + window_get_position( window, g_posMapInfoWnd ); window.destroy(); } -class ScopeTimer { - Timer m_timer; - const char *m_message; + +class ScopeTimer +{ +Timer m_timer; +const char* m_message; public: - ScopeTimer(const char *message) - : m_message(message) - { - m_timer.start(); - } - - ~ScopeTimer() - { - double elapsed_time = m_timer.elapsed_msec() / 1000.f; - globalOutputStream() << m_message << " timer: " << FloatFormat(elapsed_time, 5, 2) << " second(s) elapsed\n"; - } +ScopeTimer( const char* message ) + : m_message( message ){ + m_timer.start(); +} + +~ScopeTimer(){ + double elapsed_time = m_timer.elapsed_msec() / 1000.f; + globalOutputStream() << m_message << " timer: " << FloatFormat( elapsed_time, 5, 2 ) << " second(s) elapsed\n"; +} }; CopiedString g_strLastMapFolder = ""; @@ -999,311 +953,304 @@ CopiedString g_strLastMapFolder = ""; ================ */ -void Map_LoadFile(const char *filename) -{ - g_map.m_name = filename; +void Map_LoadFile( const char *filename ){ + g_map.m_name = filename; - // refresh VFS to apply new pak filtering based on mapname - // needed for daemon DPK VFS - VFS_Refresh(); + // refresh VFS to apply new pak filtering based on mapname + // needed for daemon DPK VFS + VFS_Refresh(); - globalOutputStream() << "Loading map from " << filename << "\n"; - ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Loading Map"); + globalOutputStream() << "Loading map from " << filename << "\n"; + ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Loading Map" ); - MRU_AddFile(filename); - g_strLastMapFolder = g_path_get_dirname(filename); + MRU_AddFile( filename ); + g_strLastMapFolder = g_path_get_dirname( filename ); - { - ScopeTimer timer("map load"); + { + ScopeTimer timer( "map load" ); - const MapFormat *format = NULL; - const char *moduleName = findModuleName(&GlobalFiletypes(), MapFormat::Name(), path_get_extension(filename)); - if (string_not_empty(moduleName)) { - format = ReferenceAPI_getMapModules().findModule(moduleName); - } + const MapFormat* format = NULL; + const char* moduleName = findModuleName( &GlobalFiletypes(), MapFormat::Name(), path_get_extension( filename ) ); + if ( string_not_empty( moduleName ) ) { + format = ReferenceAPI_getMapModules().findModule( moduleName ); + } - for (int i = 0; i < Brush_toggleFormatCount(); ++i) { - if (i) { - Map_Free(); - } - Brush_toggleFormat(i); - Map_UpdateTitle(g_map); + for ( int i = 0; i < Brush_toggleFormatCount(); ++i ) + { + if ( i ) { + Map_Free(); + } + Brush_toggleFormat( i ); + Map_UpdateTitle( g_map ); - g_map.m_resource = GlobalReferenceCache().capture(g_map.m_name.c_str()); - if (format) { - format->wrongFormat = false; - } - g_map.m_resource->attach(g_map); - if (format) { - if (!format->wrongFormat) { - break; - } - } - } + g_map.m_resource = GlobalReferenceCache().capture( g_map.m_name.c_str() ); + if ( format ) { + format->wrongFormat = false; + } + g_map.m_resource->attach( g_map ); + if ( format ) { + if ( !format->wrongFormat ) { + break; + } + } + } - Node_getTraversable(GlobalSceneGraph().root())->traverse(entity_updateworldspawn()); - } + Node_getTraversable( GlobalSceneGraph().root() )->traverse( entity_updateworldspawn() ); + } - globalOutputStream() << "--- LoadMapFile ---\n"; - globalOutputStream() << g_map.m_name.c_str() << "\n"; + globalOutputStream() << "--- LoadMapFile ---\n"; + globalOutputStream() << g_map.m_name.c_str() << "\n"; - globalOutputStream() << Unsigned(g_brushCount.get()) << " primitive\n"; - globalOutputStream() << Unsigned(g_entityCount.get()) << " entities\n"; + globalOutputStream() << Unsigned( g_brushCount.get() ) << " primitive\n"; + globalOutputStream() << Unsigned( g_entityCount.get() ) << " entities\n"; - //GlobalEntityCreator().printStatistics(); + //GlobalEntityCreator().printStatistics(); - // - // move the view to a start position - // - Map_StartPosition(); + // + // move the view to a start position + // + Map_StartPosition(); - g_currentMap = &g_map; + g_currentMap = &g_map; } -class Excluder { +class Excluder +{ public: - virtual bool excluded(scene::Node &node) const = 0; +virtual bool excluded( scene::Node& node ) const = 0; }; -class ExcludeWalker : public scene::Traversable::Walker { - const scene::Traversable::Walker &m_walker; - const Excluder *m_exclude; - mutable bool m_skip; +class ExcludeWalker : public scene::Traversable::Walker +{ +const scene::Traversable::Walker& m_walker; +const Excluder* m_exclude; +mutable bool m_skip; public: - ExcludeWalker(const scene::Traversable::Walker &walker, const Excluder &exclude) - : m_walker(walker), m_exclude(&exclude), m_skip(false) - { - } - - bool pre(scene::Node &node) const - { - if (m_exclude->excluded(node) || node.isRoot()) { - m_skip = true; - return false; - } else { - m_walker.pre(node); - } - return true; - } - - void post(scene::Node &node) const - { - if (m_skip) { - m_skip = false; - } else { - m_walker.post(node); - } - } +ExcludeWalker( const scene::Traversable::Walker& walker, const Excluder& exclude ) + : m_walker( walker ), m_exclude( &exclude ), m_skip( false ){ +} + +bool pre( scene::Node& node ) const { + if ( m_exclude->excluded( node ) || node.isRoot() ) { + m_skip = true; + return false; + } + else + { + m_walker.pre( node ); + } + return true; +} + +void post( scene::Node& node ) const { + if ( m_skip ) { + m_skip = false; + } + else + { + m_walker.post( node ); + } +} }; -class AnyInstanceSelected : public scene::Instantiable::Visitor { - bool &m_selected; +class AnyInstanceSelected : public scene::Instantiable::Visitor +{ +bool& m_selected; public: - AnyInstanceSelected(bool &selected) : m_selected(selected) - { - m_selected = false; - } - - void visit(scene::Instance &instance) const - { - Selectable *selectable = Instance_getSelectable(instance); - if (selectable != 0 - && selectable->isSelected()) { - m_selected = true; - } - } +AnyInstanceSelected( bool& selected ) : m_selected( selected ){ + m_selected = false; +} + +void visit( scene::Instance& instance ) const { + Selectable* selectable = Instance_getSelectable( instance ); + if ( selectable != 0 + && selectable->isSelected() ) { + m_selected = true; + } +} }; -bool Node_instanceSelected(scene::Node &node) -{ - scene::Instantiable *instantiable = Node_getInstantiable(node); - ASSERT_NOTNULL(instantiable); - bool selected; - instantiable->forEachInstance(AnyInstanceSelected(selected)); - return selected; +bool Node_instanceSelected( scene::Node& node ){ + scene::Instantiable* instantiable = Node_getInstantiable( node ); + ASSERT_NOTNULL( instantiable ); + bool selected; + instantiable->forEachInstance( AnyInstanceSelected( selected ) ); + return selected; } -class SelectedDescendantWalker : public scene::Traversable::Walker { - bool &m_selected; +class SelectedDescendantWalker : public scene::Traversable::Walker +{ +bool& m_selected; public: - SelectedDescendantWalker(bool &selected) : m_selected(selected) - { - m_selected = false; - } - - bool pre(scene::Node &node) const - { - if (node.isRoot()) { - return false; - } - - if (Node_instanceSelected(node)) { - m_selected = true; - } - - return true; - } +SelectedDescendantWalker( bool& selected ) : m_selected( selected ){ + m_selected = false; +} + +bool pre( scene::Node& node ) const { + if ( node.isRoot() ) { + return false; + } + + if ( Node_instanceSelected( node ) ) { + m_selected = true; + } + + return true; +} }; -bool Node_selectedDescendant(scene::Node &node) -{ - bool selected; - Node_traverseSubgraph(node, SelectedDescendantWalker(selected)); - return selected; +bool Node_selectedDescendant( scene::Node& node ){ + bool selected; + Node_traverseSubgraph( node, SelectedDescendantWalker( selected ) ); + return selected; } -class SelectionExcluder : public Excluder { +class SelectionExcluder : public Excluder +{ public: - bool excluded(scene::Node &node) const - { - return !Node_selectedDescendant(node); - } +bool excluded( scene::Node& node ) const { + return !Node_selectedDescendant( node ); +} }; -class IncludeSelectedWalker : public scene::Traversable::Walker { - const scene::Traversable::Walker &m_walker; - mutable std::size_t m_selected; - mutable bool m_skip; +class IncludeSelectedWalker : public scene::Traversable::Walker +{ +const scene::Traversable::Walker& m_walker; +mutable std::size_t m_selected; +mutable bool m_skip; - bool selectedParent() const - { - return m_selected != 0; - } +bool selectedParent() const { + return m_selected != 0; +} public: - IncludeSelectedWalker(const scene::Traversable::Walker &walker) - : m_walker(walker), m_selected(0), m_skip(false) - { - } - - bool pre(scene::Node &node) const - { - // include node if: - // node is not a 'root' AND ( node is selected OR any child of node is selected OR any parent of node is selected ) - if (!node.isRoot() && (Node_selectedDescendant(node) || selectedParent())) { - if (Node_instanceSelected(node)) { - ++m_selected; - } - m_walker.pre(node); - return true; - } else { - m_skip = true; - return false; - } - } - - void post(scene::Node &node) const - { - if (m_skip) { - m_skip = false; - } else { - if (Node_instanceSelected(node)) { - --m_selected; - } - m_walker.post(node); - } - } +IncludeSelectedWalker( const scene::Traversable::Walker& walker ) + : m_walker( walker ), m_selected( 0 ), m_skip( false ){ +} + +bool pre( scene::Node& node ) const { + // include node if: + // node is not a 'root' AND ( node is selected OR any child of node is selected OR any parent of node is selected ) + if ( !node.isRoot() && ( Node_selectedDescendant( node ) || selectedParent() ) ) { + if ( Node_instanceSelected( node ) ) { + ++m_selected; + } + m_walker.pre( node ); + return true; + } + else + { + m_skip = true; + return false; + } +} + +void post( scene::Node& node ) const { + if ( m_skip ) { + m_skip = false; + } + else + { + if ( Node_instanceSelected( node ) ) { + --m_selected; + } + m_walker.post( node ); + } +} }; -void Map_Traverse_Selected(scene::Node &root, const scene::Traversable::Walker &walker) -{ - scene::Traversable *traversable = Node_getTraversable(root); - if (traversable != 0) { +void Map_Traverse_Selected( scene::Node& root, const scene::Traversable::Walker& walker ){ + scene::Traversable* traversable = Node_getTraversable( root ); + if ( traversable != 0 ) { #if 0 - traversable->traverse( ExcludeWalker( walker, SelectionExcluder() ) ); + traversable->traverse( ExcludeWalker( walker, SelectionExcluder() ) ); #else - traversable->traverse(IncludeSelectedWalker(walker)); + traversable->traverse( IncludeSelectedWalker( walker ) ); #endif - } + } } -void Map_ExportSelected(TextOutputStream &out, const MapFormat &format) -{ - format.writeGraph(GlobalSceneGraph().root(), Map_Traverse_Selected, out, g_writeMapComments); +void Map_ExportSelected( TextOutputStream& out, const MapFormat& format ){ + format.writeGraph( GlobalSceneGraph().root(), Map_Traverse_Selected, out, g_writeMapComments ); } -void Map_Traverse(scene::Node &root, const scene::Traversable::Walker &walker) -{ - scene::Traversable *traversable = Node_getTraversable(root); - if (traversable != 0) { - traversable->traverse(walker); - } +void Map_Traverse( scene::Node& root, const scene::Traversable::Walker& walker ){ + scene::Traversable* traversable = Node_getTraversable( root ); + if ( traversable != 0 ) { + traversable->traverse( walker ); + } } -class RegionExcluder : public Excluder { +class RegionExcluder : public Excluder +{ public: - bool excluded(scene::Node &node) const - { - return node.excluded(); - } +bool excluded( scene::Node& node ) const { + return node.excluded(); +} }; -void Map_Traverse_Region(scene::Node &root, const scene::Traversable::Walker &walker) -{ - scene::Traversable *traversable = Node_getTraversable(root); - if (traversable != 0) { - traversable->traverse(ExcludeWalker(walker, RegionExcluder())); - } +void Map_Traverse_Region( scene::Node& root, const scene::Traversable::Walker& walker ){ + scene::Traversable* traversable = Node_getTraversable( root ); + if ( traversable != 0 ) { + traversable->traverse( ExcludeWalker( walker, RegionExcluder() ) ); + } } -bool Map_SaveRegion(const char *filename) -{ - AddRegionBrushes(); +bool Map_SaveRegion( const char *filename ){ + AddRegionBrushes(); - bool success = MapResource_saveFile(MapFormat_forFile(filename), GlobalSceneGraph().root(), Map_Traverse_Region, - filename); + bool success = MapResource_saveFile( MapFormat_forFile( filename ), GlobalSceneGraph().root(), Map_Traverse_Region, filename ); - RemoveRegionBrushes(); + RemoveRegionBrushes(); - return success; + return success; } -void Map_RenameAbsolute(const char *absolute) -{ - Resource *resource = GlobalReferenceCache().capture(absolute); - NodeSmartReference clone(NewMapRoot(path_make_relative(absolute, GlobalFileSystem().findRoot(absolute)))); - resource->setNode(clone.get_pointer()); +void Map_RenameAbsolute( const char* absolute ){ + Resource* resource = GlobalReferenceCache().capture( absolute ); + NodeSmartReference clone( NewMapRoot( path_make_relative( absolute, GlobalFileSystem().findRoot( absolute ) ) ) ); + resource->setNode( clone.get_pointer() ); - { - //ScopeTimer timer("clone subgraph"); - Node_getTraversable(GlobalSceneGraph().root())->traverse(CloneAll(clone)); - } + { + //ScopeTimer timer("clone subgraph"); + Node_getTraversable( GlobalSceneGraph().root() )->traverse( CloneAll( clone ) ); + } - g_map.m_resource->detach(g_map); - GlobalReferenceCache().release(g_map.m_name.c_str()); + g_map.m_resource->detach( g_map ); + GlobalReferenceCache().release( g_map.m_name.c_str() ); - g_map.m_resource = resource; + g_map.m_resource = resource; - g_map.m_name = absolute; - Map_UpdateTitle(g_map); + g_map.m_name = absolute; + Map_UpdateTitle( g_map ); - g_map.m_resource->attach(g_map); - // refresh VFS to apply new pak filtering based on mapname - // needed for daemon DPK VFS - VFS_Refresh(); + g_map.m_resource->attach( g_map ); + // refresh VFS to apply new pak filtering based on mapname + // needed for daemon DPK VFS + VFS_Refresh(); } -void Map_Rename(const char *filename) -{ - if (!string_equal(g_map.m_name.c_str(), filename)) { - ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Saving Map"); +void Map_Rename( const char* filename ){ + if ( !string_equal( g_map.m_name.c_str(), filename ) ) { + ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Saving Map" ); - Map_RenameAbsolute(filename); + Map_RenameAbsolute( filename ); - SceneChangeNotify(); - } else { - SaveReferences(); - } + SceneChangeNotify(); + } + else + { + SaveReferences(); + } } -bool Map_Save() -{ - Pointfile_Clear(); +bool Map_Save(){ + Pointfile_Clear(); - ScopeTimer timer("map save"); - SaveReferences(); - return true; // assume success.. + ScopeTimer timer( "map save" ); + SaveReferences(); + return true; // assume success.. } /* @@ -1312,55 +1259,54 @@ bool Map_Save() =========== */ -void Map_New() -{ - //globalOutputStream() << "Map_New\n"; +void Map_New(){ + //globalOutputStream() << "Map_New\n"; - g_map.m_name = "unnamed.map"; - Map_UpdateTitle(g_map); + g_map.m_name = "unnamed.map"; + Map_UpdateTitle( g_map ); - { - g_map.m_resource = GlobalReferenceCache().capture(g_map.m_name.c_str()); + { + g_map.m_resource = GlobalReferenceCache().capture( g_map.m_name.c_str() ); // ASSERT_MESSAGE(g_map.m_resource->getNode() == 0, "bleh"); - g_map.m_resource->attach(g_map); + g_map.m_resource->attach( g_map ); - SceneChangeNotify(); - } + SceneChangeNotify(); + } - FocusViews(g_vector3_identity, 0); + FocusViews( g_vector3_identity, 0 ); - g_currentMap = &g_map; + g_currentMap = &g_map; - // restart VFS to apply new pak filtering based on mapname - // needed for daemon DPK VFS - VFS_Restart(); + // restart VFS to apply new pak filtering based on mapname + // needed for daemon DPK VFS + VFS_Restart(); } -extern void ConstructRegionBrushes(scene::Node *brushes[6], const Vector3 ®ion_mins, const Vector3 ®ion_maxs); +extern void ConstructRegionBrushes( scene::Node * brushes[6], const Vector3 ®ion_mins, const Vector3 ®ion_maxs ); -void ConstructRegionStartpoint(scene::Node *startpoint, const Vector3 ®ion_mins, const Vector3 ®ion_maxs) -{ - /*! +void ConstructRegionStartpoint( scene::Node* startpoint, const Vector3& region_mins, const Vector3& region_maxs ){ + /*! \todo we need to make sure that the player start IS inside the region and bail out if it's not the compiler will refuse to compile a map with a player_start somewhere in empty space.. for now, let's just print an error */ - Vector3 vOrig(Camera_getOrigin(*g_pParentWnd->GetCamWnd())); + Vector3 vOrig( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ) ); - for (int i = 0; i < 3; i++) { - if (vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i]) { - globalErrorStream() << "Camera is NOT in the region, it's likely that the region won't compile correctly\n"; - break; - } - } + for ( int i = 0 ; i < 3 ; i++ ) + { + if ( vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i] ) { + globalErrorStream() << "Camera is NOT in the region, it's likely that the region won't compile correctly\n"; + break; + } + } - // write the info_playerstart - char sTmp[1024]; - sprintf(sTmp, "%d %d %d", (int) vOrig[0], (int) vOrig[1], (int) vOrig[2]); - Node_getEntity(*startpoint)->setKeyValue("origin", sTmp); - sprintf(sTmp, "%d", (int) Camera_getAngles(*g_pParentWnd->GetCamWnd())[CAMERA_YAW]); - Node_getEntity(*startpoint)->setKeyValue("angle", sTmp); + // write the info_playerstart + char sTmp[1024]; + sprintf( sTmp, "%d %d %d", (int)vOrig[0], (int)vOrig[1], (int)vOrig[2] ); + Node_getEntity( *startpoint )->setKeyValue( "origin", sTmp ); + sprintf( sTmp, "%d", (int)Camera_getAngles( *g_pParentWnd->GetCamWnd() )[CAMERA_YAW] ); + Node_getEntity( *startpoint )->setKeyValue( "angle", sTmp ); } /* @@ -1371,11 +1317,11 @@ void ConstructRegionStartpoint(scene::Node *startpoint, const Vector3 ®ion_mi =========================================================== */ bool region_active; -Vector3 region_mins(g_MinWorldCoord, g_MinWorldCoord, g_MinWorldCoord); -Vector3 region_maxs(g_MaxWorldCoord, g_MaxWorldCoord, g_MaxWorldCoord); +Vector3 region_mins( g_MinWorldCoord, g_MinWorldCoord, g_MinWorldCoord ); +Vector3 region_maxs( g_MaxWorldCoord, g_MaxWorldCoord, g_MaxWorldCoord ); -scene::Node *region_sides[6]; -scene::Node *region_startpoint = 0; +scene::Node* region_sides[6]; +scene::Node* region_startpoint = 0; /* =========== @@ -1386,116 +1332,106 @@ scene::Node *region_startpoint = 0; with the new implementation we should be able to append them in a temporary manner to the data we pass to the map module =========== */ -void AddRegionBrushes(void) -{ - int i; +void AddRegionBrushes( void ){ + int i; - for (i = 0; i < 6; i++) { - region_sides[i] = &GlobalBrushCreator().createBrush(); - Node_getTraversable(Map_FindOrInsertWorldspawn(g_map))->insert(NodeSmartReference(*region_sides[i])); - } + for ( i = 0; i < 6; i++ ) + { + region_sides[i] = &GlobalBrushCreator().createBrush(); + Node_getTraversable( Map_FindOrInsertWorldspawn( g_map ) )->insert( NodeSmartReference( *region_sides[i] ) ); + } - region_startpoint = &GlobalEntityCreator().createEntity( - GlobalEntityClassManager().findOrInsert("info_player_start", false)); + region_startpoint = &GlobalEntityCreator().createEntity( GlobalEntityClassManager().findOrInsert( "info_player_start", false ) ); - ConstructRegionBrushes(region_sides, region_mins, region_maxs); - ConstructRegionStartpoint(region_startpoint, region_mins, region_maxs); + ConstructRegionBrushes( region_sides, region_mins, region_maxs ); + ConstructRegionStartpoint( region_startpoint, region_mins, region_maxs ); - Node_getTraversable(GlobalSceneGraph().root())->insert(NodeSmartReference(*region_startpoint)); + Node_getTraversable( GlobalSceneGraph().root() )->insert( NodeSmartReference( *region_startpoint ) ); } -void RemoveRegionBrushes(void) -{ - for (std::size_t i = 0; i < 6; i++) { - Node_getTraversable(*Map_GetWorldspawn(g_map))->erase(*region_sides[i]); - } - Node_getTraversable(GlobalSceneGraph().root())->erase(*region_startpoint); +void RemoveRegionBrushes( void ){ + for ( std::size_t i = 0; i < 6; i++ ) + { + Node_getTraversable( *Map_GetWorldspawn( g_map ) )->erase( *region_sides[i] ); + } + Node_getTraversable( GlobalSceneGraph().root() )->erase( *region_startpoint ); } -inline void exclude_node(scene::Node &node, bool exclude) -{ - exclude - ? node.enable(scene::Node::eExcluded) - : node.disable(scene::Node::eExcluded); +inline void exclude_node( scene::Node& node, bool exclude ){ + exclude + ? node.enable( scene::Node::eExcluded ) + : node.disable( scene::Node::eExcluded ); } -class ExcludeAllWalker : public scene::Graph::Walker { - bool m_exclude; +class ExcludeAllWalker : public scene::Graph::Walker +{ +bool m_exclude; public: - ExcludeAllWalker(bool exclude) - : m_exclude(exclude) - { - } +ExcludeAllWalker( bool exclude ) + : m_exclude( exclude ){ +} - bool pre(const scene::Path &path, scene::Instance &instance) const - { - exclude_node(path.top(), m_exclude); +bool pre( const scene::Path& path, scene::Instance& instance ) const { + exclude_node( path.top(), m_exclude ); - return true; - } + return true; +} }; -void Scene_Exclude_All(bool exclude) -{ - GlobalSceneGraph().traverse(ExcludeAllWalker(exclude)); +void Scene_Exclude_All( bool exclude ){ + GlobalSceneGraph().traverse( ExcludeAllWalker( exclude ) ); } -bool Instance_isSelected(const scene::Instance &instance) -{ - const Selectable *selectable = Instance_getSelectable(instance); - return selectable != 0 && selectable->isSelected(); +bool Instance_isSelected( const scene::Instance& instance ){ + const Selectable* selectable = Instance_getSelectable( instance ); + return selectable != 0 && selectable->isSelected(); } -class ExcludeSelectedWalker : public scene::Graph::Walker { - bool m_exclude; +class ExcludeSelectedWalker : public scene::Graph::Walker +{ +bool m_exclude; public: - ExcludeSelectedWalker(bool exclude) - : m_exclude(exclude) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - exclude_node(path.top(), - (instance.isSelected() || instance.childSelected() || instance.parentSelected()) == m_exclude); - return true; - } +ExcludeSelectedWalker( bool exclude ) + : m_exclude( exclude ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + exclude_node( path.top(), ( instance.isSelected() || instance.childSelected() || instance.parentSelected() ) == m_exclude ); + return true; +} }; -void Scene_Exclude_Selected(bool exclude) -{ - GlobalSceneGraph().traverse(ExcludeSelectedWalker(exclude)); +void Scene_Exclude_Selected( bool exclude ){ + GlobalSceneGraph().traverse( ExcludeSelectedWalker( exclude ) ); } -class ExcludeRegionedWalker : public scene::Graph::Walker { - bool m_exclude; +class ExcludeRegionedWalker : public scene::Graph::Walker +{ +bool m_exclude; public: - ExcludeRegionedWalker(bool exclude) - : m_exclude(exclude) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - exclude_node( - path.top(), - !( - ( - aabb_intersects_aabb( - instance.worldAABB(), - aabb_for_minmax(region_mins, region_maxs) - ) != 0 - ) ^ m_exclude - ) - ); - - return true; - } +ExcludeRegionedWalker( bool exclude ) + : m_exclude( exclude ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + exclude_node( + path.top(), + !( + ( + aabb_intersects_aabb( + instance.worldAABB(), + aabb_for_minmax( region_mins, region_maxs ) + ) != 0 + ) ^ m_exclude + ) + ); + + return true; +} }; -void Scene_Exclude_Region(bool exclude) -{ - GlobalSceneGraph().traverse(ExcludeRegionedWalker(exclude)); +void Scene_Exclude_Region( bool exclude ){ + GlobalSceneGraph().traverse( ExcludeRegionedWalker( exclude ) ); } /* @@ -1505,25 +1441,23 @@ void Scene_Exclude_Region(bool exclude) Other filtering options may still be on =========== */ -void Map_RegionOff() -{ - region_active = false; +void Map_RegionOff(){ + region_active = false; - region_maxs[0] = g_MaxWorldCoord - 64; - region_mins[0] = g_MinWorldCoord + 64; - region_maxs[1] = g_MaxWorldCoord - 64; - region_mins[1] = g_MinWorldCoord + 64; - region_maxs[2] = g_MaxWorldCoord - 64; - region_mins[2] = g_MinWorldCoord + 64; + region_maxs[0] = g_MaxWorldCoord - 64; + region_mins[0] = g_MinWorldCoord + 64; + region_maxs[1] = g_MaxWorldCoord - 64; + region_mins[1] = g_MinWorldCoord + 64; + region_maxs[2] = g_MaxWorldCoord - 64; + region_mins[2] = g_MinWorldCoord + 64; - Scene_Exclude_All(false); + Scene_Exclude_All( false ); } -void Map_ApplyRegion(void) -{ - region_active = true; +void Map_ApplyRegion( void ){ + region_active = true; - Scene_Exclude_Region(false); + Scene_Exclude_Region( false ); } @@ -1532,19 +1466,18 @@ void Map_ApplyRegion(void) Map_RegionSelectedBrushes ======================== */ -void Map_RegionSelectedBrushes(void) -{ - Map_RegionOff(); +void Map_RegionSelectedBrushes( void ){ + Map_RegionOff(); - if (GlobalSelectionSystem().countSelected() != 0 - && GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive) { - region_active = true; - Select_GetBounds(region_mins, region_maxs); + if ( GlobalSelectionSystem().countSelected() != 0 + && GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive ) { + region_active = true; + Select_GetBounds( region_mins, region_maxs ); - Scene_Exclude_Selected(false); + Scene_Exclude_Selected( false ); - GlobalSelectionSystem().setSelectedAll(false); - } + GlobalSelectionSystem().setSelectedAll( false ); + } } @@ -1553,30 +1486,28 @@ void Map_RegionSelectedBrushes(void) Map_RegionXY =========== */ -void Map_RegionXY(float x_min, float y_min, float x_max, float y_max) -{ - Map_RegionOff(); +void Map_RegionXY( float x_min, float y_min, float x_max, float y_max ){ + Map_RegionOff(); - region_mins[0] = x_min; - region_maxs[0] = x_max; - region_mins[1] = y_min; - region_maxs[1] = y_max; - region_mins[2] = g_MinWorldCoord + 64; - region_maxs[2] = g_MaxWorldCoord - 64; + region_mins[0] = x_min; + region_maxs[0] = x_max; + region_mins[1] = y_min; + region_maxs[1] = y_max; + region_mins[2] = g_MinWorldCoord + 64; + region_maxs[2] = g_MaxWorldCoord - 64; - Map_ApplyRegion(); + Map_ApplyRegion(); } -void Map_RegionBounds(const AABB &bounds) -{ - Map_RegionOff(); +void Map_RegionBounds( const AABB& bounds ){ + Map_RegionOff(); - region_mins = vector3_subtracted(bounds.origin, bounds.extents); - region_maxs = vector3_added(bounds.origin, bounds.extents); + region_mins = vector3_subtracted( bounds.origin, bounds.extents ); + region_maxs = vector3_added( bounds.origin, bounds.extents ); - deleteSelection(); + deleteSelection(); - Map_ApplyRegion(); + Map_ApplyRegion(); } /* @@ -1584,12 +1515,11 @@ void Map_RegionBounds(const AABB &bounds) Map_RegionBrush =========== */ -void Map_RegionBrush(void) -{ - if (GlobalSelectionSystem().countSelected() != 0) { - scene::Instance &instance = GlobalSelectionSystem().ultimateSelected(); - Map_RegionBounds(instance.worldAABB()); - } +void Map_RegionBrush( void ){ + if ( GlobalSelectionSystem().countSelected() != 0 ) { + scene::Instance& instance = GlobalSelectionSystem().ultimateSelected(); + Map_RegionBounds( instance.worldAABB() ); + } } // @@ -1597,127 +1527,125 @@ void Map_RegionBrush(void) //Map_ImportFile //================ // -bool Map_ImportFile(const char *filename) -{ - ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Loading Map"); - - g_strLastMapFolder = g_path_get_dirname(filename); - - bool success = false; - - if (extension_equal(path_get_extension(filename), "bsp")) { - goto tryDecompile; - } - - { - const MapFormat *format = NULL; - const char *moduleName = findModuleName(&GlobalFiletypes(), MapFormat::Name(), path_get_extension(filename)); - if (string_not_empty(moduleName)) { - format = ReferenceAPI_getMapModules().findModule(moduleName); - } - - if (format) { - format->wrongFormat = false; - } - Resource *resource = GlobalReferenceCache().capture(filename); - resource->refresh(); // avoid loading old version if map has changed on disk since last import - if (!resource->load()) { - GlobalReferenceCache().release(filename); - goto tryDecompile; - } - if (format) { - if (format->wrongFormat) { - GlobalReferenceCache().release(filename); - goto tryDecompile; - } - } - NodeSmartReference clone(NewMapRoot("")); - Node_getTraversable(*resource->getNode())->traverse(CloneAll(clone)); - Map_gatherNamespaced(clone); - Map_mergeClonedNames(); - MergeMap(clone); - success = true; - GlobalReferenceCache().release(filename); - } - - SceneChangeNotify(); - - return success; - - tryDecompile: - - const char *type = GlobalRadiant().getGameDescriptionKeyValue("q3map2_type"); - int n = string_length(path_get_extension(filename)); - if (n && (extension_equal(path_get_extension(filename), "bsp") || - extension_equal(path_get_extension(filename), "map"))) { - StringBuffer output; - output.push_string(AppPath_get()); - output.push_string("q3map2."); - output.push_string(RADIANT_EXECUTABLE); - output.push_string(" -v -game "); - output.push_string((type && *type) ? type : "quake3"); - output.push_string(" -fs_basepath \""); - output.push_string(EnginePath_get()); - output.push_string("\" -fs_homepath \""); - output.push_string(g_qeglobals.m_userEnginePath.c_str()); - output.push_string("\""); - - // extra pakpaths - for (int i = 0; i < g_pakPathCount; i++) { - if (g_strcmp0(g_strPakPath[i].c_str(), "")) { - output.push_string(" -fs_pakpath \""); - output.push_string(g_strPakPath[i].c_str()); - output.push_string("\""); - } - } - - // extra switches - if (g_disableEnginePath) { - output.push_string(" -fs_nobasepath "); - } - - if (g_disableHomePath) { - output.push_string(" -fs_nohomepath "); - } - - output.push_string(" -fs_game "); - output.push_string(gamename_get()); - output.push_string(" -convert -format "); - output.push_string(Brush::m_type == eBrushTypeQuake3BP ? "map_bp" : "map"); - if (extension_equal(path_get_extension(filename), "map")) { - output.push_string(" -readmap "); - } - output.push_string(" \""); - output.push_string(filename); - output.push_string("\""); - - // run - Q_Exec(NULL, output.c_str(), NULL, false, true); - - // rebuild filename as "filenamewithoutext_converted.map" - output.clear(); - output.push_range(filename, filename + string_length(filename) - (n + 1)); - output.push_string("_converted.map"); - filename = output.c_str(); - - // open - Resource *resource = GlobalReferenceCache().capture(filename); - resource->refresh(); // avoid loading old version if map has changed on disk since last import - if (!resource->load()) { - GlobalReferenceCache().release(filename); - goto tryDecompile; - } - NodeSmartReference clone(NewMapRoot("")); - Node_getTraversable(*resource->getNode())->traverse(CloneAll(clone)); - Map_gatherNamespaced(clone); - Map_mergeClonedNames(); - MergeMap(clone); - success = true; - GlobalReferenceCache().release(filename); - } - - SceneChangeNotify(); - return success; +bool Map_ImportFile( const char* filename ){ + ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Loading Map" ); + + g_strLastMapFolder = g_path_get_dirname( filename ); + + bool success = false; + + if ( extension_equal( path_get_extension( filename ), "bsp" ) ) { + goto tryDecompile; + } + + { + const MapFormat* format = NULL; + const char* moduleName = findModuleName( &GlobalFiletypes(), MapFormat::Name(), path_get_extension( filename ) ); + if ( string_not_empty( moduleName ) ) { + format = ReferenceAPI_getMapModules().findModule( moduleName ); + } + + if ( format ) { + format->wrongFormat = false; + } + Resource* resource = GlobalReferenceCache().capture( filename ); + resource->refresh(); // avoid loading old version if map has changed on disk since last import + if ( !resource->load() ) { + GlobalReferenceCache().release( filename ); + goto tryDecompile; + } + if ( format ) { + if ( format->wrongFormat ) { + GlobalReferenceCache().release( filename ); + goto tryDecompile; + } + } + NodeSmartReference clone( NewMapRoot( "" ) ); + Node_getTraversable( *resource->getNode() )->traverse( CloneAll( clone ) ); + Map_gatherNamespaced( clone ); + Map_mergeClonedNames(); + MergeMap( clone ); + success = true; + GlobalReferenceCache().release( filename ); + } + + SceneChangeNotify(); + + return success; + +tryDecompile: + + const char *type = GlobalRadiant().getGameDescriptionKeyValue( "q3map2_type" ); + int n = string_length( path_get_extension( filename ) ); + if ( n && ( extension_equal( path_get_extension( filename ), "bsp" ) || extension_equal( path_get_extension( filename ), "map" ) ) ) { + StringBuffer output; + output.push_string( AppPath_get() ); + output.push_string( "q3map2." ); + output.push_string( RADIANT_EXECUTABLE ); + output.push_string( " -v -game " ); + output.push_string( ( type && *type ) ? type : "quake3" ); + output.push_string( " -fs_basepath \"" ); + output.push_string( EnginePath_get() ); + output.push_string( "\" -fs_homepath \"" ); + output.push_string( g_qeglobals.m_userEnginePath.c_str() ); + output.push_string( "\"" ); + + // extra pakpaths + for ( int i = 0; i < g_pakPathCount; i++ ) { + if ( g_strcmp0( g_strPakPath[i].c_str(), "") ) { + output.push_string( " -fs_pakpath \"" ); + output.push_string( g_strPakPath[i].c_str() ); + output.push_string( "\"" ); + } + } + + // extra switches + if ( g_disableEnginePath ) { + output.push_string( " -fs_nobasepath " ); + } + + if ( g_disableHomePath ) { + output.push_string( " -fs_nohomepath " ); + } + + output.push_string( " -fs_game " ); + output.push_string( gamename_get() ); + output.push_string( " -convert -format " ); + output.push_string( Brush::m_type == eBrushTypeQuake3BP ? "map_bp" : "map" ); + if ( extension_equal( path_get_extension( filename ), "map" ) ) { + output.push_string( " -readmap " ); + } + output.push_string( " \"" ); + output.push_string( filename ); + output.push_string( "\"" ); + + // run + Q_Exec( NULL, output.c_str(), NULL, false, true ); + + // rebuild filename as "filenamewithoutext_converted.map" + output.clear(); + output.push_range( filename, filename + string_length( filename ) - ( n + 1 ) ); + output.push_string( "_converted.map" ); + filename = output.c_str(); + + // open + Resource* resource = GlobalReferenceCache().capture( filename ); + resource->refresh(); // avoid loading old version if map has changed on disk since last import + if ( !resource->load() ) { + GlobalReferenceCache().release( filename ); + goto tryDecompile; + } + NodeSmartReference clone( NewMapRoot( "" ) ); + Node_getTraversable( *resource->getNode() )->traverse( CloneAll( clone ) ); + Map_gatherNamespaced( clone ); + Map_mergeClonedNames(); + MergeMap( clone ); + success = true; + GlobalReferenceCache().release( filename ); + } + + SceneChangeNotify(); + return success; } /* @@ -1725,16 +1653,15 @@ bool Map_ImportFile(const char *filename) Map_SaveFile =========== */ -bool Map_SaveFile(const char *filename) -{ - ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Saving Map"); - bool success = MapResource_saveFile(MapFormat_forFile(filename), GlobalSceneGraph().root(), Map_Traverse, filename); - if (success) { - // refresh VFS to apply new pak filtering based on mapname - // needed for daemon DPK VFS - VFS_Refresh(); - } - return success; +bool Map_SaveFile( const char* filename ){ + ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Saving Map" ); + bool success = MapResource_saveFile( MapFormat_forFile( filename ), GlobalSceneGraph().root(), Map_Traverse, filename ); + if ( success ) { + // refresh VFS to apply new pak filtering based on mapname + // needed for daemon DPK VFS + VFS_Refresh(); + } + return success; } // @@ -1744,622 +1671,575 @@ bool Map_SaveFile(const char *filename) // // Saves selected world brushes and whole entities with partial/full selections // -bool Map_SaveSelected(const char *filename) -{ - return MapResource_saveFile(MapFormat_forFile(filename), GlobalSceneGraph().root(), Map_Traverse_Selected, - filename); +bool Map_SaveSelected( const char* filename ){ + return MapResource_saveFile( MapFormat_forFile( filename ), GlobalSceneGraph().root(), Map_Traverse_Selected, filename ); } -class ParentSelectedBrushesToEntityWalker : public scene::Graph::Walker { - scene::Node &m_parent; -public: - ParentSelectedBrushesToEntityWalker(scene::Node &parent) : m_parent(parent) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - if (path.top().get_pointer() != &m_parent - && Node_isPrimitive(path.top())) { - Selectable *selectable = Instance_getSelectable(instance); - if (selectable != 0 - && selectable->isSelected() - && path.size() > 1) { - return false; - } - } - return true; - } - - void post(const scene::Path &path, scene::Instance &instance) const - { - if (path.top().get_pointer() != &m_parent - && Node_isPrimitive(path.top())) { - Selectable *selectable = Instance_getSelectable(instance); - if (selectable != 0 - && selectable->isSelected() - && path.size() > 1) { - scene::Node &parent = path.parent(); - if (&parent != &m_parent) { - NodeSmartReference node(path.top().get()); - Node_getTraversable(parent)->erase(node); - Node_getTraversable(m_parent)->insert(node); - } - } - } - } -}; - -void Scene_parentSelectedBrushesToEntity(scene::Graph &graph, scene::Node &parent) +class ParentSelectedBrushesToEntityWalker : public scene::Graph::Walker { - graph.traverse(ParentSelectedBrushesToEntityWalker(parent)); -} - -class CountSelectedBrushes : public scene::Graph::Walker { - std::size_t &m_count; - mutable std::size_t m_depth; +scene::Node& m_parent; public: - CountSelectedBrushes(std::size_t &count) : m_count(count), m_depth(0) - { - m_count = 0; - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - if (++m_depth != 1 && path.top().get().isRoot()) { - return false; - } - Selectable *selectable = Instance_getSelectable(instance); - if (selectable != 0 - && selectable->isSelected() - && Node_isPrimitive(path.top())) { - ++m_count; - } - return true; - } - - void post(const scene::Path &path, scene::Instance &instance) const - { - --m_depth; - } -}; - -std::size_t Scene_countSelectedBrushes(scene::Graph &graph) -{ - std::size_t count; - graph.traverse(CountSelectedBrushes(count)); - return count; +ParentSelectedBrushesToEntityWalker( scene::Node& parent ) : m_parent( parent ){ +} + +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get_pointer() != &m_parent + && Node_isPrimitive( path.top() ) ) { + Selectable* selectable = Instance_getSelectable( instance ); + if ( selectable != 0 + && selectable->isSelected() + && path.size() > 1 ) { + return false; + } + } + return true; +} + +void post( const scene::Path& path, scene::Instance& instance ) const { + if ( path.top().get_pointer() != &m_parent + && Node_isPrimitive( path.top() ) ) { + Selectable* selectable = Instance_getSelectable( instance ); + if ( selectable != 0 + && selectable->isSelected() + && path.size() > 1 ) { + scene::Node& parent = path.parent(); + if ( &parent != &m_parent ) { + NodeSmartReference node( path.top().get() ); + Node_getTraversable( parent )->erase( node ); + Node_getTraversable( m_parent )->insert( node ); + } + } + } } - -enum ENodeType { - eNodeUnknown, - eNodeMap, - eNodeEntity, - eNodePrimitive, }; -const char *nodetype_get_name(ENodeType type) -{ - if (type == eNodeMap) { - return "map"; - } - if (type == eNodeEntity) { - return "entity"; - } - if (type == eNodePrimitive) { - return "primitive"; - } - return "unknown"; -} - -ENodeType node_get_nodetype(scene::Node &node) -{ - if (Node_isEntity(node)) { - return eNodeEntity; - } - if (Node_isPrimitive(node)) { - return eNodePrimitive; - } - return eNodeUnknown; +void Scene_parentSelectedBrushesToEntity( scene::Graph& graph, scene::Node& parent ){ + graph.traverse( ParentSelectedBrushesToEntityWalker( parent ) ); } -bool contains_entity(scene::Node &node) +class CountSelectedBrushes : public scene::Graph::Walker { - return Node_getTraversable(node) != 0 && !Node_isBrush(node) && !Node_isPatch(node) && !Node_isEntity(node); +std::size_t& m_count; +mutable std::size_t m_depth; +public: +CountSelectedBrushes( std::size_t& count ) : m_count( count ), m_depth( 0 ){ + m_count = 0; } -bool contains_primitive(scene::Node &node) -{ - return Node_isEntity(node) && Node_getTraversable(node) != 0 && Node_getEntity(node)->isContainer(); +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( ++m_depth != 1 && path.top().get().isRoot() ) { + return false; + } + Selectable* selectable = Instance_getSelectable( instance ); + if ( selectable != 0 + && selectable->isSelected() + && Node_isPrimitive( path.top() ) ) { + ++m_count; + } + return true; } -ENodeType node_get_contains(scene::Node &node) -{ - if (contains_entity(node)) { - return eNodeEntity; - } - if (contains_primitive(node)) { - return eNodePrimitive; - } - return eNodeUnknown; +void post( const scene::Path& path, scene::Instance& instance ) const { + --m_depth; } +}; -void Path_parent(const scene::Path &parent, const scene::Path &child) -{ - ENodeType contains = node_get_contains(parent.top()); - ENodeType type = node_get_nodetype(child.top()); - - if (contains != eNodeUnknown && contains == type) { - NodeSmartReference node(child.top().get()); - Path_deleteTop(child); - Node_getTraversable(parent.top())->insert(node); - SceneChangeNotify(); - } else { - globalErrorStream() << "failed - " << nodetype_get_name(type) << " cannot be parented to " - << nodetype_get_name(contains) << " container.\n"; - } +std::size_t Scene_countSelectedBrushes( scene::Graph& graph ){ + std::size_t count; + graph.traverse( CountSelectedBrushes( count ) ); + return count; } -void Scene_parentSelected() +enum ENodeType { - UndoableCommand undo("parentSelected"); + eNodeUnknown, + eNodeMap, + eNodeEntity, + eNodePrimitive, +}; - if (GlobalSelectionSystem().countSelected() > 1) { - class ParentSelectedBrushesToEntityWalker : public SelectionSystem::Visitor { - const scene::Path &m_parent; - public: - ParentSelectedBrushesToEntityWalker(const scene::Path &parent) : m_parent(parent) - { - } +const char* nodetype_get_name( ENodeType type ){ + if ( type == eNodeMap ) { + return "map"; + } + if ( type == eNodeEntity ) { + return "entity"; + } + if ( type == eNodePrimitive ) { + return "primitive"; + } + return "unknown"; +} + +ENodeType node_get_nodetype( scene::Node& node ){ + if ( Node_isEntity( node ) ) { + return eNodeEntity; + } + if ( Node_isPrimitive( node ) ) { + return eNodePrimitive; + } + return eNodeUnknown; +} + +bool contains_entity( scene::Node& node ){ + return Node_getTraversable( node ) != 0 && !Node_isBrush( node ) && !Node_isPatch( node ) && !Node_isEntity( node ); +} + +bool contains_primitive( scene::Node& node ){ + return Node_isEntity( node ) && Node_getTraversable( node ) != 0 && Node_getEntity( node )->isContainer(); +} + +ENodeType node_get_contains( scene::Node& node ){ + if ( contains_entity( node ) ) { + return eNodeEntity; + } + if ( contains_primitive( node ) ) { + return eNodePrimitive; + } + return eNodeUnknown; +} + +void Path_parent( const scene::Path& parent, const scene::Path& child ){ + ENodeType contains = node_get_contains( parent.top() ); + ENodeType type = node_get_nodetype( child.top() ); + + if ( contains != eNodeUnknown && contains == type ) { + NodeSmartReference node( child.top().get() ); + Path_deleteTop( child ); + Node_getTraversable( parent.top() )->insert( node ); + SceneChangeNotify(); + } + else + { + globalErrorStream() << "failed - " << nodetype_get_name( type ) << " cannot be parented to " << nodetype_get_name( contains ) << " container.\n"; + } +} + +void Scene_parentSelected(){ + UndoableCommand undo( "parentSelected" ); + + if ( GlobalSelectionSystem().countSelected() > 1 ) { + class ParentSelectedBrushesToEntityWalker : public SelectionSystem::Visitor + { + const scene::Path& m_parent; +public: + ParentSelectedBrushesToEntityWalker( const scene::Path& parent ) : m_parent( parent ){ + } - void visit(scene::Instance &instance) const - { - if (&m_parent != &instance.path()) { - Path_parent(m_parent, instance.path()); - } - } - }; + void visit( scene::Instance& instance ) const { + if ( &m_parent != &instance.path() ) { + Path_parent( m_parent, instance.path() ); + } + } + }; - ParentSelectedBrushesToEntityWalker visitor(GlobalSelectionSystem().ultimateSelected().path()); - GlobalSelectionSystem().foreachSelected(visitor); - } else { - globalOutputStream() << "failed - did not find two selected nodes.\n"; - } + ParentSelectedBrushesToEntityWalker visitor( GlobalSelectionSystem().ultimateSelected().path() ); + GlobalSelectionSystem().foreachSelected( visitor ); + } + else + { + globalOutputStream() << "failed - did not find two selected nodes.\n"; + } } -void NewMap() -{ - if (ConfirmModified("New Map")) { - Map_RegionOff(); - Map_Free(); - Map_New(); - } +void NewMap(){ + if ( ConfirmModified( "New Map" ) ) { + Map_RegionOff(); + Map_Free(); + Map_New(); + } } CopiedString g_mapsPath; -const char *getMapsPath() -{ - return g_mapsPath.c_str(); +const char* getMapsPath(){ + return g_mapsPath.c_str(); } -const char *getLastMapFolderPath() -{ - if (g_strLastMapFolder.empty()) { - GlobalPreferenceSystem().registerPreference("LastMapFolder", make_property_string(g_strLastMapFolder)); - if (g_strLastMapFolder.empty()) { - StringOutputStream buffer(1024); - buffer << getMapsPath(); - if (!file_readable(buffer.c_str())) { - buffer.clear(); - buffer << g_qeglobals.m_userGamePath.c_str() << "/"; - } - g_strLastMapFolder = buffer.c_str(); - } - } - return g_strLastMapFolder.c_str(); -} - -const char *map_open(const char *title) -{ - return MainFrame_getWindow().file_dialog(TRUE, title, getLastMapFolderPath(), MapFormat::Name(), true, false, false); +const char* getLastMapFolderPath(){ + if (g_strLastMapFolder.empty()) { + GlobalPreferenceSystem().registerPreference( "LastMapFolder", make_property_string( g_strLastMapFolder ) ); + if (g_strLastMapFolder.empty()) { + StringOutputStream buffer( 1024 ); + buffer << getMapsPath(); + if ( !file_readable( buffer.c_str() ) ) { + buffer.clear(); + buffer << g_qeglobals.m_userGamePath.c_str() << "/"; + } + g_strLastMapFolder = buffer.c_str(); + } + } + return g_strLastMapFolder.c_str(); } -const char *map_import(const char *title) -{ - return MainFrame_getWindow().file_dialog(TRUE, title, getLastMapFolderPath(), MapFormat::Name(), false, true, false); +const char* map_open( const char* title ){ + return MainFrame_getWindow().file_dialog( TRUE, title, getLastMapFolderPath(), MapFormat::Name(), true, false, false ); } -const char *map_save(const char *title) -{ - return MainFrame_getWindow().file_dialog(FALSE, title, getLastMapFolderPath(), MapFormat::Name(), false, false, true); +const char* map_import( const char* title ){ + return MainFrame_getWindow().file_dialog( TRUE, title, getLastMapFolderPath(), MapFormat::Name(), false, true, false ); } -void OpenMap() -{ - if (!ConfirmModified("Open Map")) { - return; - } +const char* map_save( const char* title ){ + return MainFrame_getWindow().file_dialog( FALSE, title, getLastMapFolderPath(), MapFormat::Name(), false, false, true ); +} - const char *filename = map_open("Open Map"); +void OpenMap(){ + if ( !ConfirmModified( "Open Map" ) ) { + return; + } - if (filename != NULL) { - MRU_AddFile(filename); - Map_RegionOff(); - Map_Free(); - Map_LoadFile(filename); - } + const char* filename = map_open( "Open Map" ); + + if ( filename != NULL ) { + MRU_AddFile( filename ); + Map_RegionOff(); + Map_Free(); + Map_LoadFile( filename ); + } } -void ImportMap() -{ - const char *filename = map_import("Import Map"); +void ImportMap(){ + const char* filename = map_import( "Import Map" ); - if (filename != NULL) { - UndoableCommand undo("mapImport"); - Map_ImportFile(filename); - } + if ( filename != NULL ) { + UndoableCommand undo( "mapImport" ); + Map_ImportFile( filename ); + } } -bool Map_SaveAs() -{ - const char *filename = map_save("Save Map"); +bool Map_SaveAs(){ + const char* filename = map_save( "Save Map" ); - if (filename != NULL) { - g_strLastMapFolder = g_path_get_dirname(filename); - MRU_AddFile(filename); - Map_Rename(filename); - return Map_Save(); - } - return false; + if ( filename != NULL ) { + g_strLastMapFolder = g_path_get_dirname( filename ); + MRU_AddFile( filename ); + Map_Rename( filename ); + return Map_Save(); + } + return false; } -void SaveMapAs() -{ - Map_SaveAs(); +void SaveMapAs(){ + Map_SaveAs(); } -void SaveMap() -{ - if (Map_Unnamed(g_map)) { - SaveMapAs(); - } else if (Map_Modified(g_map)) { - Map_Save(); - } +void SaveMap(){ + if ( Map_Unnamed( g_map ) ) { + SaveMapAs(); + } + else if ( Map_Modified( g_map ) ) { + Map_Save(); + } } -void ExportMap() -{ - const char *filename = map_save("Export Selection"); +void ExportMap(){ + const char* filename = map_save( "Export Selection" ); - if (filename != NULL) { - g_strLastMapFolder = g_path_get_dirname(filename); - Map_SaveSelected(filename); - } + if ( filename != NULL ) { + g_strLastMapFolder = g_path_get_dirname( filename ); + Map_SaveSelected( filename ); + } } -void SaveRegion() -{ - const char *filename = map_save("Export Region"); +void SaveRegion(){ + const char* filename = map_save( "Export Region" ); - if (filename != NULL) { - g_strLastMapFolder = g_path_get_dirname(filename); - Map_SaveRegion(filename); - } + if ( filename != NULL ) { + g_strLastMapFolder = g_path_get_dirname( filename ); + Map_SaveRegion( filename ); + } } -void RegionOff() -{ - Map_RegionOff(); - SceneChangeNotify(); +void RegionOff(){ + Map_RegionOff(); + SceneChangeNotify(); } -void RegionXY() -{ - Map_RegionXY( - g_pParentWnd->GetXYWnd()->GetOrigin()[0] - - 0.5f * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale(), - g_pParentWnd->GetXYWnd()->GetOrigin()[1] - - 0.5f * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale(), - g_pParentWnd->GetXYWnd()->GetOrigin()[0] + - 0.5f * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale(), - g_pParentWnd->GetXYWnd()->GetOrigin()[1] + - 0.5f * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale() - ); - SceneChangeNotify(); -} - -void RegionBrush() -{ - Map_RegionBrush(); - SceneChangeNotify(); +void RegionXY(){ + Map_RegionXY( + g_pParentWnd->GetXYWnd()->GetOrigin()[0] - 0.5f * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale(), + g_pParentWnd->GetXYWnd()->GetOrigin()[1] - 0.5f * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale(), + g_pParentWnd->GetXYWnd()->GetOrigin()[0] + 0.5f * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale(), + g_pParentWnd->GetXYWnd()->GetOrigin()[1] + 0.5f * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale() + ); + SceneChangeNotify(); } -void RegionSelected() -{ - Map_RegionSelectedBrushes(); - SceneChangeNotify(); +void RegionBrush(){ + Map_RegionBrush(); + SceneChangeNotify(); +} + +void RegionSelected(){ + Map_RegionSelectedBrushes(); + SceneChangeNotify(); } -class BrushFindByIndexWalker : public scene::Traversable::Walker { - mutable std::size_t m_index; - scene::Path &m_path; + + + +class BrushFindByIndexWalker : public scene::Traversable::Walker +{ +mutable std::size_t m_index; +scene::Path& m_path; public: - BrushFindByIndexWalker(std::size_t index, scene::Path &path) - : m_index(index), m_path(path) - { - } - - bool pre(scene::Node &node) const - { - if (Node_isPrimitive(node) && m_index-- == 0) { - m_path.push(makeReference(node)); - } - return false; - } +BrushFindByIndexWalker( std::size_t index, scene::Path& path ) + : m_index( index ), m_path( path ){ +} + +bool pre( scene::Node& node ) const { + if ( Node_isPrimitive( node ) && m_index-- == 0 ) { + m_path.push( makeReference( node ) ); + } + return false; +} }; -class EntityFindByIndexWalker : public scene::Traversable::Walker { - mutable std::size_t m_index; - scene::Path &m_path; +class EntityFindByIndexWalker : public scene::Traversable::Walker +{ +mutable std::size_t m_index; +scene::Path& m_path; public: - EntityFindByIndexWalker(std::size_t index, scene::Path &path) - : m_index(index), m_path(path) - { - } - - bool pre(scene::Node &node) const - { - if (Node_isEntity(node) && m_index-- == 0) { - m_path.push(makeReference(node)); - } - return false; - } +EntityFindByIndexWalker( std::size_t index, scene::Path& path ) + : m_index( index ), m_path( path ){ +} + +bool pre( scene::Node& node ) const { + if ( Node_isEntity( node ) && m_index-- == 0 ) { + m_path.push( makeReference( node ) ); + } + return false; +} }; -void Scene_FindEntityBrush(std::size_t entity, std::size_t brush, scene::Path &path) -{ - path.push(makeReference(GlobalSceneGraph().root())); - { - Node_getTraversable(path.top())->traverse(EntityFindByIndexWalker(entity, path)); - } - if (path.size() == 2) { - scene::Traversable *traversable = Node_getTraversable(path.top()); - if (traversable != 0) { - traversable->traverse(BrushFindByIndexWalker(brush, path)); - } - } -} - -inline bool Node_hasChildren(scene::Node &node) -{ - scene::Traversable *traversable = Node_getTraversable(node); - return traversable != 0 && !traversable->empty(); +void Scene_FindEntityBrush( std::size_t entity, std::size_t brush, scene::Path& path ){ + path.push( makeReference( GlobalSceneGraph().root() ) ); + { + Node_getTraversable( path.top() )->traverse( EntityFindByIndexWalker( entity, path ) ); + } + if ( path.size() == 2 ) { + scene::Traversable* traversable = Node_getTraversable( path.top() ); + if ( traversable != 0 ) { + traversable->traverse( BrushFindByIndexWalker( brush, path ) ); + } + } +} + +inline bool Node_hasChildren( scene::Node& node ){ + scene::Traversable* traversable = Node_getTraversable( node ); + return traversable != 0 && !traversable->empty(); +} + +void SelectBrush( int entitynum, int brushnum ){ + scene::Path path; + Scene_FindEntityBrush( entitynum, brushnum, path ); + if ( path.size() == 3 || ( path.size() == 2 && !Node_hasChildren( path.top() ) ) ) { + scene::Instance* instance = GlobalSceneGraph().find( path ); + ASSERT_MESSAGE( instance != 0, "SelectBrush: path not found in scenegraph" ); + Selectable* selectable = Instance_getSelectable( *instance ); + ASSERT_MESSAGE( selectable != 0, "SelectBrush: path not selectable" ); + selectable->setSelected( true ); + g_pParentWnd->GetXYWnd()->PositionView( instance->worldAABB().origin ); + } } -void SelectBrush(int entitynum, int brushnum) + +class BrushFindIndexWalker : public scene::Graph::Walker { - scene::Path path; - Scene_FindEntityBrush(entitynum, brushnum, path); - if (path.size() == 3 || (path.size() == 2 && !Node_hasChildren(path.top()))) { - scene::Instance *instance = GlobalSceneGraph().find(path); - ASSERT_MESSAGE(instance != 0, "SelectBrush: path not found in scenegraph"); - Selectable *selectable = Instance_getSelectable(*instance); - ASSERT_MESSAGE(selectable != 0, "SelectBrush: path not selectable"); - selectable->setSelected(true); - g_pParentWnd->GetXYWnd()->PositionView(instance->worldAABB().origin); - } -} - - -class BrushFindIndexWalker : public scene::Graph::Walker { - mutable const scene::Node *m_node; - std::size_t &m_count; +mutable const scene::Node* m_node; +std::size_t& m_count; public: - BrushFindIndexWalker(const scene::Node &node, std::size_t &count) - : m_node(&node), m_count(count) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - if (Node_isPrimitive(path.top())) { - if (m_node == path.top().get_pointer()) { - m_node = 0; - } - if (m_node) { - ++m_count; - } - } - return true; - } -}; +BrushFindIndexWalker( const scene::Node& node, std::size_t& count ) + : m_node( &node ), m_count( count ){ +} -class EntityFindIndexWalker : public scene::Graph::Walker { - mutable const scene::Node *m_node; - std::size_t &m_count; -public: - EntityFindIndexWalker(const scene::Node &node, std::size_t &count) - : m_node(&node), m_count(count) - { - } - - bool pre(const scene::Path &path, scene::Instance &instance) const - { - if (Node_isEntity(path.top())) { - if (m_node == path.top().get_pointer()) { - m_node = 0; - } - if (m_node) { - ++m_count; - } - } - return true; - } +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( Node_isPrimitive( path.top() ) ) { + if ( m_node == path.top().get_pointer() ) { + m_node = 0; + } + if ( m_node ) { + ++m_count; + } + } + return true; +} }; -static void GetSelectionIndex(int *ent, int *brush) +class EntityFindIndexWalker : public scene::Graph::Walker { - std::size_t count_brush = 0; - std::size_t count_entity = 0; - if (GlobalSelectionSystem().countSelected() != 0) { - const scene::Path &path = GlobalSelectionSystem().ultimateSelected().path(); +mutable const scene::Node* m_node; +std::size_t& m_count; +public: +EntityFindIndexWalker( const scene::Node& node, std::size_t& count ) + : m_node( &node ), m_count( count ){ +} - GlobalSceneGraph().traverse(BrushFindIndexWalker(path.top(), count_brush)); - GlobalSceneGraph().traverse(EntityFindIndexWalker(path.parent(), count_entity)); - } - *brush = int(count_brush); - *ent = int(count_entity); +bool pre( const scene::Path& path, scene::Instance& instance ) const { + if ( Node_isEntity( path.top() ) ) { + if ( m_node == path.top().get_pointer() ) { + m_node = 0; + } + if ( m_node ) { + ++m_count; + } + } + return true; } +}; -void DoFind() -{ - ModalDialog dialog; - ui::Entry entity{ui::null}; - ui::Entry brush{ui::null}; - - ui::Window window = MainFrame_getWindow().create_dialog_window("Find Brush", G_CALLBACK(dialog_delete_callback), - &dialog); - - auto accel = ui::AccelGroup(ui::New); - window.add_accel_group(accel); - - { - auto vbox = create_dialog_vbox(4, 4); - window.add(vbox); - { - auto table = create_dialog_table(2, 2, 4, 4); - vbox.pack_start(table, TRUE, TRUE, 0); - { - ui::Widget label = ui::Label("Entity number"); - label.show(); +static void GetSelectionIndex( int *ent, int *brush ){ + std::size_t count_brush = 0; + std::size_t count_entity = 0; + if ( GlobalSelectionSystem().countSelected() != 0 ) { + const scene::Path& path = GlobalSelectionSystem().ultimateSelected().path(); + + GlobalSceneGraph().traverse( BrushFindIndexWalker( path.top(), count_brush ) ); + GlobalSceneGraph().traverse( EntityFindIndexWalker( path.parent(), count_entity ) ); + } + *brush = int(count_brush); + *ent = int(count_entity); +} + +void DoFind(){ + ModalDialog dialog; + ui::Entry entity{ui::null}; + ui::Entry brush{ui::null}; + + ui::Window window = MainFrame_getWindow().create_dialog_window("Find Brush", G_CALLBACK(dialog_delete_callback ), &dialog ); + + auto accel = ui::AccelGroup(ui::New); + window.add_accel_group( accel ); + + { + auto vbox = create_dialog_vbox( 4, 4 ); + window.add(vbox); + { + auto table = create_dialog_table( 2, 2, 4, 4 ); + vbox.pack_start( table, TRUE, TRUE, 0 ); + { + ui::Widget label = ui::Label( "Entity number" ); + label.show(); (table).attach(label, {0, 1, 0, 1}, {0, 0}); - } - { - ui::Widget label = ui::Label("Brush number"); - label.show(); + } + { + ui::Widget label = ui::Label( "Brush number" ); + label.show(); (table).attach(label, {0, 1, 1, 2}, {0, 0}); - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 0, 1}, {GTK_EXPAND | GTK_FILL, 0}); - gtk_widget_grab_focus(entry); - entity = entry; - } - { - auto entry = ui::Entry(ui::New); - entry.show(); + gtk_widget_grab_focus( entry ); + entity = entry; + } + { + auto entry = ui::Entry(ui::New); + entry.show(); table.attach(entry, {1, 2, 1, 2}, {GTK_EXPAND | GTK_FILL, 0}); - brush = entry; - } - } - { - auto hbox = create_dialog_hbox(4); - vbox.pack_start(hbox, TRUE, TRUE, 0); - { - auto button = create_dialog_button("Find", G_CALLBACK(dialog_button_ok), &dialog); - hbox.pack_start(button, FALSE, FALSE, 0); - widget_make_default(button); - gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Return, (GdkModifierType) 0, - (GtkAccelFlags) 0); - } - { - auto button = create_dialog_button("Close", G_CALLBACK(dialog_button_cancel), &dialog); - hbox.pack_start(button, FALSE, FALSE, 0); - gtk_widget_add_accelerator(button, "clicked", accel, GDK_KEY_Escape, (GdkModifierType) 0, - (GtkAccelFlags) 0); - } - } - } - - // Initialize dialog - char buf[16]; - int ent, br; - - GetSelectionIndex(&ent, &br); - sprintf(buf, "%i", ent); - entity.text(buf); - sprintf(buf, "%i", br); - brush.text(buf); - - if (modal_dialog_show(window, dialog) == eIDOK) { - const char *entstr = gtk_entry_get_text(entity); - const char *brushstr = gtk_entry_get_text(brush); - SelectBrush(atoi(entstr), atoi(brushstr)); - } + brush = entry; + } + } + { + auto hbox = create_dialog_hbox( 4 ); + vbox.pack_start( hbox, TRUE, TRUE, 0 ); + { + auto button = create_dialog_button( "Find", G_CALLBACK( dialog_button_ok ), &dialog ); + hbox.pack_start( button, FALSE, FALSE, 0 ); + widget_make_default( button ); + gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Return, (GdkModifierType)0, (GtkAccelFlags)0 ); + } + { + auto button = create_dialog_button( "Close", G_CALLBACK( dialog_button_cancel ), &dialog ); + hbox.pack_start( button, FALSE, FALSE, 0 ); + gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Escape, (GdkModifierType)0, (GtkAccelFlags)0 ); + } + } + } + + // Initialize dialog + char buf[16]; + int ent, br; + + GetSelectionIndex( &ent, &br ); + sprintf( buf, "%i", ent ); + entity.text(buf); + sprintf( buf, "%i", br ); + brush.text(buf); + + if ( modal_dialog_show( window, dialog ) == eIDOK ) { + const char *entstr = gtk_entry_get_text( entity ); + const char *brushstr = gtk_entry_get_text( brush ); + SelectBrush( atoi( entstr ), atoi( brushstr ) ); + } window.destroy(); } -void Map_constructPreferences(PreferencesPage &page) -{ - page.appendCheckBox("", "Load last map at startup", g_bLoadLastMap); - page.appendCheckBox("", "Add entity and brush number comments on map write", g_writeMapComments); +void Map_constructPreferences( PreferencesPage& page ){ + page.appendCheckBox( "", "Load last map at startup", g_bLoadLastMap ); + page.appendCheckBox( "", "Add entity and brush number comments on map write", g_writeMapComments ); } -class MapEntityClasses : public ModuleObserver { - std::size_t m_unrealised; +class MapEntityClasses : public ModuleObserver +{ +std::size_t m_unrealised; public: - MapEntityClasses() : m_unrealised(1) - { - } - - void realise() - { - if (--m_unrealised == 0) { - if (g_map.m_resource != 0) { - ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Loading Map"); - g_map.m_resource->realise(); - } - } - } - - void unrealise() - { - if (++m_unrealised == 1) { - if (g_map.m_resource != 0) { - g_map.m_resource->flush(); - g_map.m_resource->unrealise(); - } - } - } +MapEntityClasses() : m_unrealised( 1 ){ +} + +void realise(){ + if ( --m_unrealised == 0 ) { + if ( g_map.m_resource != 0 ) { + ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Loading Map" ); + g_map.m_resource->realise(); + } + } +} + +void unrealise(){ + if ( ++m_unrealised == 1 ) { + if ( g_map.m_resource != 0 ) { + g_map.m_resource->flush(); + g_map.m_resource->unrealise(); + } + } +} }; MapEntityClasses g_MapEntityClasses; -class MapModuleObserver : public ModuleObserver { - std::size_t m_unrealised; +class MapModuleObserver : public ModuleObserver +{ +std::size_t m_unrealised; public: - MapModuleObserver() : m_unrealised(1) - { - } - - void realise() - { - if (--m_unrealised == 0) { - ASSERT_MESSAGE(!string_empty(g_qeglobals.m_userGamePath.c_str()), - "maps_directory: user-game-path is empty"); - StringOutputStream buffer(256); - buffer << g_qeglobals.m_userGamePath.c_str() << "maps/"; - Q_mkdir(buffer.c_str()); - g_mapsPath = buffer.c_str(); - } - } - - void unrealise() - { - if (++m_unrealised == 1) { - g_mapsPath = ""; - } - } +MapModuleObserver() : m_unrealised( 1 ){ +} + +void realise(){ + if ( --m_unrealised == 0 ) { + ASSERT_MESSAGE( !string_empty( g_qeglobals.m_userGamePath.c_str() ), "maps_directory: user-game-path is empty" ); + StringOutputStream buffer( 256 ); + buffer << g_qeglobals.m_userGamePath.c_str() << "maps/"; + Q_mkdir( buffer.c_str() ); + g_mapsPath = buffer.c_str(); + } +} + +void unrealise(){ + if ( ++m_unrealised == 1 ) { + g_mapsPath = ""; + } +} }; MapModuleObserver g_MapModuleObserver; @@ -2367,27 +2247,24 @@ MapModuleObserver g_MapModuleObserver; CopiedString g_strLastMap; bool g_bLoadLastMap = false; -void Map_Construct() -{ - GlobalCommands_insert("RegionOff", makeCallbackF(RegionOff)); - GlobalCommands_insert("RegionSetXY", makeCallbackF(RegionXY)); - GlobalCommands_insert("RegionSetBrush", makeCallbackF(RegionBrush)); - GlobalCommands_insert("RegionSetSelection", makeCallbackF(RegionSelected), - Accelerator('R', (GdkModifierType) (GDK_SHIFT_MASK | GDK_CONTROL_MASK))); +void Map_Construct(){ + GlobalCommands_insert( "RegionOff", makeCallbackF(RegionOff) ); + GlobalCommands_insert( "RegionSetXY", makeCallbackF(RegionXY) ); + GlobalCommands_insert( "RegionSetBrush", makeCallbackF(RegionBrush) ); + GlobalCommands_insert( "RegionSetSelection", makeCallbackF(RegionSelected), Accelerator( 'R', (GdkModifierType)( GDK_SHIFT_MASK | GDK_CONTROL_MASK ) ) ); - GlobalPreferenceSystem().registerPreference("LastMap", make_property_string(g_strLastMap)); - GlobalPreferenceSystem().registerPreference("LoadLastMap", make_property_string(g_bLoadLastMap)); - GlobalPreferenceSystem().registerPreference("MapInfoDlg", make_property(g_posMapInfoWnd)); - GlobalPreferenceSystem().registerPreference("WriteMapComments", make_property_string(g_writeMapComments)); + GlobalPreferenceSystem().registerPreference( "LastMap", make_property_string( g_strLastMap ) ); + GlobalPreferenceSystem().registerPreference( "LoadLastMap", make_property_string( g_bLoadLastMap ) ); + GlobalPreferenceSystem().registerPreference( "MapInfoDlg", make_property( g_posMapInfoWnd ) ); + GlobalPreferenceSystem().registerPreference( "WriteMapComments", make_property_string( g_writeMapComments ) ); - PreferencesDialog_addSettingsPreferences(makeCallbackF(Map_constructPreferences)); + PreferencesDialog_addSettingsPreferences( makeCallbackF(Map_constructPreferences) ); - GlobalEntityClassManager().attach(g_MapEntityClasses); - Radiant_attachHomePathsObserver(g_MapModuleObserver); + GlobalEntityClassManager().attach( g_MapEntityClasses ); + Radiant_attachHomePathsObserver( g_MapModuleObserver ); } -void Map_Destroy() -{ - Radiant_detachHomePathsObserver(g_MapModuleObserver); - GlobalEntityClassManager().detach(g_MapEntityClasses); +void Map_Destroy(){ + Radiant_detachHomePathsObserver( g_MapModuleObserver ); + GlobalEntityClassManager().detach( g_MapEntityClasses ); } diff --git a/radiant/multimon.cpp b/radiant/multimon.cpp index 99d63204..9a4a4f22 100644 --- a/radiant/multimon.cpp +++ b/radiant/multimon.cpp @@ -29,17 +29,15 @@ multimon_globals_t g_multimon_globals; -LatchedValue g_Multimon_enableSysMenuPopups(false, "Floating windows sysmenu icons"); - -void MultiMonitor_constructPreferences(PreferencesPage &page) -{ - ui::CheckButton primary_monitor = page.appendCheckBox("Multi Monitor", "Start on Primary Monitor", - g_multimon_globals.m_bStartOnPrimMon); - ui::CheckButton popup = page.appendCheckBox( - "", "Disable system menu on popup windows", - make_property(g_Multimon_enableSysMenuPopups) - ); - Widget_connectToggleDependency(popup, primary_monitor); +LatchedValue g_Multimon_enableSysMenuPopups( false, "Floating windows sysmenu icons" ); + +void MultiMonitor_constructPreferences( PreferencesPage& page ){ + ui::CheckButton primary_monitor = page.appendCheckBox( "Multi Monitor", "Start on Primary Monitor", g_multimon_globals.m_bStartOnPrimMon ); + ui::CheckButton popup = page.appendCheckBox( + "", "Disable system menu on popup windows", + mkImportExportCallback( g_Multimon_enableSysMenuPopups ) + ); + Widget_connectToggleDependency( popup, primary_monitor ); } #include "preferencesystem.h" @@ -47,58 +45,54 @@ void MultiMonitor_constructPreferences(PreferencesPage &page) #include -namespace { - GdkRectangle primaryMonitor; +namespace +{ +GdkRectangle primaryMonitor; } -void PositionWindowOnPrimaryScreen(WindowPosition &position) -{ - if (position.w >= primaryMonitor.width - 12) { - position.w = primaryMonitor.width - 12; - } - if (position.h >= primaryMonitor.height - 24) { - position.h = primaryMonitor.height - 48; - } - if (position.x <= primaryMonitor.x || position.x + position.w >= (primaryMonitor.x + primaryMonitor.width) - 12) { - position.x = primaryMonitor.x + 6; - } - if (position.y <= primaryMonitor.y || position.y + position.h >= (primaryMonitor.y + primaryMonitor.height) - 48) { - position.y = primaryMonitor.y + 24; - } +void PositionWindowOnPrimaryScreen( WindowPosition& position ){ + if ( position.w >= primaryMonitor.width - 12 ) { + position.w = primaryMonitor.width - 12; + } + if ( position.h >= primaryMonitor.height - 24 ) { + position.h = primaryMonitor.height - 48; + } + if ( position.x <= primaryMonitor.x || position.x + position.w >= ( primaryMonitor.x + primaryMonitor.width ) - 12 ) { + position.x = primaryMonitor.x + 6; + } + if ( position.y <= primaryMonitor.y || position.y + position.h >= ( primaryMonitor.y + primaryMonitor.height ) - 48 ) { + position.y = primaryMonitor.y + 24; + } } -void MultiMon_Construct() -{ - // detect multiple monitors - - GdkScreen *screen = gdk_display_get_default_screen(gdk_display_get_default()); - gint m = gdk_screen_get_n_monitors(screen); - globalOutputStream() << "default screen has " << m << " monitors\n"; - for (int j = 0; j != m; ++j) { - GdkRectangle geom; - gdk_screen_get_monitor_geometry(screen, j, &geom); - globalOutputStream() << "monitor " << j << " geometry: " << geom.x << ", " << geom.y << ", " << geom.width - << ", " << geom.height << "\n"; - if (j == 0) { - // I am making the assumption that monitor 0 is always the primary monitor on win32. Tested on WinXP with gtk+-2.4. - primaryMonitor = geom; - } - } - - if (m > 1) { - g_multimon_globals.m_bStartOnPrimMon = true; - } - - GlobalPreferenceSystem().registerPreference("StartOnPrimMon", - make_property_string(g_multimon_globals.m_bStartOnPrimMon)); - GlobalPreferenceSystem().registerPreference("NoSysMenuPopups", - make_property_string(g_Multimon_enableSysMenuPopups.m_latched)); - - g_Multimon_enableSysMenuPopups.useLatched(); - - PreferencesDialog_addInterfacePreferences(makeCallbackF(MultiMonitor_constructPreferences)); +void MultiMon_Construct(){ + // detect multiple monitors + + GdkScreen* screen = gdk_display_get_default_screen( gdk_display_get_default() ); + gint m = gdk_screen_get_n_monitors( screen ); + globalOutputStream() << "default screen has " << m << " monitors\n"; + for ( int j = 0; j != m; ++j ) + { + GdkRectangle geom; + gdk_screen_get_monitor_geometry( screen, j, &geom ); + globalOutputStream() << "monitor " << j << " geometry: " << geom.x << ", " << geom.y << ", " << geom.width << ", " << geom.height << "\n"; + if ( j == 0 ) { + // I am making the assumption that monitor 0 is always the primary monitor on win32. Tested on WinXP with gtk+-2.4. + primaryMonitor = geom; + } + } + + if ( m > 1 ) { + g_multimon_globals.m_bStartOnPrimMon = true; + } + + GlobalPreferenceSystem().registerPreference( "StartOnPrimMon", make_property_string( g_multimon_globals.m_bStartOnPrimMon ) ); + GlobalPreferenceSystem().registerPreference( "NoSysMenuPopups", make_property_string( g_Multimon_enableSysMenuPopups.m_latched ) ); + + g_Multimon_enableSysMenuPopups.useLatched(); + + PreferencesDialog_addInterfacePreferences( makeCallbackF(MultiMonitor_constructPreferences) ); } -void MultiMon_Destroy() -{ +void MultiMon_Destroy(){ } diff --git a/radiant/qe3.cpp b/radiant/qe3.cpp index af0f8f93..b0737521 100644 --- a/radiant/qe3.cpp +++ b/radiant/qe3.cpp @@ -73,327 +73,314 @@ QEGlobals_t g_qeglobals; #endif -void QE_InitVFS() -{ - // VFS initialization ----------------------- - // we will call GlobalFileSystem().initDirectory, giving the directories to look in (for files in pk3's and for standalone files) - // we need to call in order, the mod ones first, then the base ones .. they will be searched in this order - // *nix systems have a dual filesystem in ~/.q3a, which is searched first .. so we need to add that too +void QE_InitVFS(){ + // VFS initialization ----------------------- + // we will call GlobalFileSystem().initDirectory, giving the directories to look in (for files in pk3's and for standalone files) + // we need to call in order, the mod ones first, then the base ones .. they will be searched in this order + // *nix systems have a dual filesystem in ~/.q3a, which is searched first .. so we need to add that too - const char *gamename = gamename_get(); - const char *basegame = basegame_get(); - const char *userRoot = g_qeglobals.m_userEnginePath.c_str(); - const char *globalRoot = EnginePath_get(); + const char* gamename = gamename_get(); + const char* basegame = basegame_get(); + const char* userRoot = g_qeglobals.m_userEnginePath.c_str(); + const char* globalRoot = EnginePath_get(); // editor builtin VFS - StringOutputStream editorGamePath(256); + StringOutputStream editorGamePath( 256 ); editorGamePath << GlobalRadiant().getAppPath() << DEFAULT_EDITORVFS_DIRNAME; - GlobalFileSystem().initDirectory(editorGamePath.c_str()); - - // if we have a mod dir - if (!string_equal(gamename, basegame)) { - // ~/./ - if (userRoot && !g_disableHomePath) { - StringOutputStream userGamePath(256); - userGamePath << userRoot << gamename << '/'; - GlobalFileSystem().initDirectory(userGamePath.c_str()); - } - - // / - if (!g_disableEnginePath) { - StringOutputStream globalGamePath(256); - globalGamePath << globalRoot << gamename << '/'; - GlobalFileSystem().initDirectory(globalGamePath.c_str()); - } - } - - // ~/./ - if (userRoot && !g_disableHomePath) { - StringOutputStream userBasePath(256); - userBasePath << userRoot << basegame << '/'; - GlobalFileSystem().initDirectory(userBasePath.c_str()); - } - - // / - if (!g_disableEnginePath) { - StringOutputStream globalBasePath(256); - globalBasePath << globalRoot << basegame << '/'; - GlobalFileSystem().initDirectory(globalBasePath.c_str()); - } - - // extra pakpaths - for (int i = 0; i < g_pakPathCount; i++) { - if (g_strcmp0(g_strPakPath[i].c_str(), "")) { - GlobalFileSystem().initDirectory(g_strPakPath[i].c_str()); - } - } + GlobalFileSystem().initDirectory( editorGamePath.c_str() ); + + // if we have a mod dir + if ( !string_equal( gamename, basegame ) ) { + // ~/./ + if ( userRoot && !g_disableHomePath ) { + StringOutputStream userGamePath( 256 ); + userGamePath << userRoot << gamename << '/'; + GlobalFileSystem().initDirectory( userGamePath.c_str() ); + } + + // / + if ( !g_disableEnginePath ) { + StringOutputStream globalGamePath( 256 ); + globalGamePath << globalRoot << gamename << '/'; + GlobalFileSystem().initDirectory( globalGamePath.c_str() ); + } + } + + // ~/./ + if ( userRoot && !g_disableHomePath ) { + StringOutputStream userBasePath( 256 ); + userBasePath << userRoot << basegame << '/'; + GlobalFileSystem().initDirectory( userBasePath.c_str() ); + } + + // / + if ( !g_disableEnginePath ) { + StringOutputStream globalBasePath( 256 ); + globalBasePath << globalRoot << basegame << '/'; + GlobalFileSystem().initDirectory( globalBasePath.c_str() ); + } + + // extra pakpaths + for ( int i = 0; i < g_pakPathCount; i++ ) { + if (g_strcmp0( g_strPakPath[i].c_str(), "")) { + GlobalFileSystem().initDirectory( g_strPakPath[i].c_str() ); + } + } } int g_numbrushes = 0; int g_numentities = 0; -void QE_UpdateStatusBar() -{ - char buffer[128]; - sprintf(buffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities); - g_pParentWnd->SetStatusText(g_pParentWnd->m_brushcount_status, buffer); +void QE_UpdateStatusBar(){ + char buffer[128]; + sprintf( buffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities ); + g_pParentWnd->SetStatusText( g_pParentWnd->m_brushcount_status, buffer ); } SimpleCounter g_brushCount; -void QE_brushCountChanged() -{ - g_numbrushes = int(g_brushCount.get()); - QE_UpdateStatusBar(); +void QE_brushCountChanged(){ + g_numbrushes = int(g_brushCount.get() ); + QE_UpdateStatusBar(); } SimpleCounter g_entityCount; -void QE_entityCountChanged() -{ - g_numentities = int(g_entityCount.get()); - QE_UpdateStatusBar(); +void QE_entityCountChanged(){ + g_numentities = int(g_entityCount.get() ); + QE_UpdateStatusBar(); } -bool ConfirmModified(const char *title) -{ - if (!Map_Modified(g_map)) { - return true; - } - - auto result = ui::alert(MainFrame_getWindow(), - "The current map has changed since it was last saved.\nDo you want to save the current map before continuing?", - title, ui::alert_type::YESNOCANCEL, ui::alert_icon::Question); - if (result == ui::alert_response::CANCEL) { - return false; - } - if (result == ui::alert_response::YES) { - if (Map_Unnamed(g_map)) { - return Map_SaveAs(); - } else { - return Map_Save(); - } - } - return true; +bool ConfirmModified( const char* title ){ + if ( !Map_Modified( g_map ) ) { + return true; + } + + auto result = ui::alert( MainFrame_getWindow(), "The current map has changed since it was last saved.\nDo you want to save the current map before continuing?", title, ui::alert_type::YESNOCANCEL, ui::alert_icon::Question ); + if ( result == ui::alert_response::CANCEL ) { + return false; + } + if ( result == ui::alert_response::YES ) { + if ( Map_Unnamed( g_map ) ) { + return Map_SaveAs(); + } + else + { + return Map_Save(); + } + } + return true; } -void bsp_init() -{ - build_set_variable("RadiantPath", AppPath_get()); - build_set_variable("ExecutableType", RADIANT_EXECUTABLE); - build_set_variable("EnginePath", EnginePath_get()); - build_set_variable("UserEnginePath", g_qeglobals.m_userEnginePath.c_str()); - build_set_variable("MonitorAddress", (g_WatchBSP_Enabled) ? "127.0.0.1:39000" : ""); - build_set_variable("GameName", gamename_get()); - - StringBuffer ExtraQ3map2Args; - // extra pakpaths - for (int i = 0; i < g_pakPathCount; i++) { - if (g_strcmp0(g_strPakPath[i].c_str(), "")) { - ExtraQ3map2Args.push_string(" -fs_pakpath \""); - ExtraQ3map2Args.push_string(g_strPakPath[i].c_str()); - ExtraQ3map2Args.push_string("\""); - } - } - - // extra switches - if (g_disableEnginePath) { - ExtraQ3map2Args.push_string(" -fs_nobasepath "); - } - - if (g_disableHomePath) { - ExtraQ3map2Args.push_string(" -fs_nohomepath "); - } - - build_set_variable("ExtraQ3map2Args", ExtraQ3map2Args.c_str()); - - const char *mapname = Map_Name(g_map); - StringOutputStream name(256); - name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".bsp"; - - build_set_variable("MapFile", mapname); - build_set_variable("BspFile", name.c_str()); +void bsp_init(){ + build_set_variable( "RadiantPath", AppPath_get() ); + build_set_variable( "ExecutableType", RADIANT_EXECUTABLE ); + build_set_variable( "EnginePath", EnginePath_get() ); + build_set_variable( "UserEnginePath", g_qeglobals.m_userEnginePath.c_str() ); + build_set_variable( "MonitorAddress", ( g_WatchBSP_Enabled ) ? "127.0.0.1:39000" : "" ); + build_set_variable( "GameName", gamename_get() ); + + StringBuffer ExtraQ3map2Args; + // extra pakpaths + for ( int i = 0; i < g_pakPathCount; i++ ) { + if ( g_strcmp0( g_strPakPath[i].c_str(), "") ) { + ExtraQ3map2Args.push_string( " -fs_pakpath \"" ); + ExtraQ3map2Args.push_string( g_strPakPath[i].c_str() ); + ExtraQ3map2Args.push_string( "\"" ); + } + } + + // extra switches + if ( g_disableEnginePath ) { + ExtraQ3map2Args.push_string( " -fs_nobasepath " ); + } + + if ( g_disableHomePath ) { + ExtraQ3map2Args.push_string( " -fs_nohomepath " ); + } + + build_set_variable( "ExtraQ3map2Args", ExtraQ3map2Args.c_str() ); + + const char* mapname = Map_Name( g_map ); + StringOutputStream name( 256 ); + name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".bsp"; + + build_set_variable( "MapFile", mapname ); + build_set_variable( "BspFile", name.c_str() ); } -void bsp_shutdown() -{ - build_clear_variables(); +void bsp_shutdown(){ + build_clear_variables(); } -class ArrayCommandListener : public CommandListener { - GPtrArray *m_array; +class ArrayCommandListener : public CommandListener +{ +GPtrArray* m_array; public: - ArrayCommandListener() - { - m_array = g_ptr_array_new(); - } - - ~ArrayCommandListener() - { - g_ptr_array_free(m_array, TRUE); - } - - void execute(const char *command) - { - g_ptr_array_add(m_array, g_strdup(command)); - } - - GPtrArray *array() const - { - return m_array; - } +ArrayCommandListener(){ + m_array = g_ptr_array_new(); +} + +~ArrayCommandListener(){ + g_ptr_array_free( m_array, TRUE ); +} + +void execute( const char* command ){ + g_ptr_array_add( m_array, g_strdup( command ) ); +} + +GPtrArray* array() const { + return m_array; +} }; -class BatchCommandListener : public CommandListener { - TextOutputStream &m_file; - std::size_t m_commandCount; - const char *m_outputRedirect; +class BatchCommandListener : public CommandListener +{ +TextOutputStream& m_file; +std::size_t m_commandCount; +const char* m_outputRedirect; public: - BatchCommandListener(TextOutputStream &file, const char *outputRedirect) : m_file(file), m_commandCount(0), - m_outputRedirect(outputRedirect) - { - } - - void execute(const char *command) - { - m_file << command; - if (m_commandCount == 0) { - m_file << " > "; - } else { - m_file << " >> "; - } - m_file << "\"" << m_outputRedirect << "\""; - m_file << "\n"; - ++m_commandCount; - } +BatchCommandListener( TextOutputStream& file, const char* outputRedirect ) : m_file( file ), m_commandCount( 0 ), m_outputRedirect( outputRedirect ){ +} + +void execute( const char* command ){ + m_file << command; + if ( m_commandCount == 0 ) { + m_file << " > "; + } + else + { + m_file << " >> "; + } + m_file << "\"" << m_outputRedirect << "\""; + m_file << "\n"; + ++m_commandCount; +} }; -bool Region_cameraValid() -{ - Vector3 vOrig(vector3_snapped(Camera_getOrigin(*g_pParentWnd->GetCamWnd()))); - - for (int i = 0; i < 3; i++) { - if (vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i]) { - return false; - } - } - return true; +bool Region_cameraValid(){ + Vector3 vOrig( vector3_snapped( Camera_getOrigin( *g_pParentWnd->GetCamWnd() ) ) ); + + for ( int i = 0 ; i < 3 ; i++ ) + { + if ( vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i] ) { + return false; + } + } + return true; } -void RunBSP(const char *name) -{ - // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503 - // make sure we don't attempt to region compile a map with the camera outside the region - if (region_active && !Region_cameraValid()) { - globalErrorStream() << "The camera must be in the region to start a region compile.\n"; - return; - } - - SaveMap(); - - if (Map_Unnamed(g_map)) { - globalOutputStream() << "build cancelled\n"; - return; - } - - if (g_SnapShots_Enabled && !Map_Unnamed(g_map) && Map_Modified(g_map)) { - Map_Snapshot(); - } - - if (region_active) { - const char *mapname = Map_Name(g_map); - StringOutputStream name(256); - name << StringRange(mapname, path_get_filename_base_end(mapname)) << ".reg"; - Map_SaveRegion(name.c_str()); - } - - Pointfile_Delete(); - - bsp_init(); - - if (g_WatchBSP_Enabled) { - ArrayCommandListener listener; - build_run(name, listener); - // grab the file name for engine running - const char *fullname = Map_Name(g_map); - StringOutputStream bspname(64); - bspname << StringRange(path_get_filename_start(fullname), path_get_filename_base_end(fullname)); - BuildMonitor_Run(listener.array(), bspname.c_str()); - } else { - char junkpath[PATH_MAX]; - strcpy(junkpath, SettingsPath_get()); - strcat(junkpath, "junk.txt"); - - char batpath[PATH_MAX]; +void RunBSP( const char* name ){ + // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503 + // make sure we don't attempt to region compile a map with the camera outside the region + if ( region_active && !Region_cameraValid() ) { + globalErrorStream() << "The camera must be in the region to start a region compile.\n"; + return; + } + + SaveMap(); + + if ( Map_Unnamed( g_map ) ) { + globalOutputStream() << "build cancelled\n"; + return; + } + + if ( g_SnapShots_Enabled && !Map_Unnamed( g_map ) && Map_Modified( g_map ) ) { + Map_Snapshot(); + } + + if ( region_active ) { + const char* mapname = Map_Name( g_map ); + StringOutputStream name( 256 ); + name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".reg"; + Map_SaveRegion( name.c_str() ); + } + + Pointfile_Delete(); + + bsp_init(); + + if ( g_WatchBSP_Enabled ) { + ArrayCommandListener listener; + build_run( name, listener ); + // grab the file name for engine running + const char* fullname = Map_Name( g_map ); + StringOutputStream bspname( 64 ); + bspname << StringRange( path_get_filename_start( fullname ), path_get_filename_base_end( fullname ) ); + BuildMonitor_Run( listener.array(), bspname.c_str() ); + } + else + { + char junkpath[PATH_MAX]; + strcpy( junkpath, SettingsPath_get() ); + strcat( junkpath, "junk.txt" ); + + char batpath[PATH_MAX]; #if GDEF_OS_POSIX - strcpy(batpath, SettingsPath_get()); - strcat(batpath, "qe3bsp.sh"); + strcpy( batpath, SettingsPath_get() ); + strcat( batpath, "qe3bsp.sh" ); #elif GDEF_OS_WINDOWS - strcpy( batpath, SettingsPath_get() ); - strcat( batpath, "qe3bsp.bat" ); + strcpy( batpath, SettingsPath_get() ); + strcat( batpath, "qe3bsp.bat" ); #else #error "unsupported platform" #endif - bool written = false; - { - TextFileOutputStream batchFile(batpath); - if (!batchFile.failed()) { + bool written = false; + { + TextFileOutputStream batchFile( batpath ); + if ( !batchFile.failed() ) { #if GDEF_OS_POSIX - batchFile << "#!/bin/sh \n\n"; + batchFile << "#!/bin/sh \n\n"; #endif - BatchCommandListener listener(batchFile, junkpath); - build_run(name, listener); - written = true; - } - } - if (written) { + BatchCommandListener listener( batchFile, junkpath ); + build_run( name, listener ); + written = true; + } + } + if ( written ) { #if GDEF_OS_POSIX - chmod(batpath, 0744); + chmod( batpath, 0744 ); #endif - globalOutputStream() << "Writing the compile script to '" << batpath << "'\n"; - globalOutputStream() << "The build output will be saved in '" << junkpath << "'\n"; - Q_Exec(batpath, NULL, NULL, true, false); - } - } + globalOutputStream() << "Writing the compile script to '" << batpath << "'\n"; + globalOutputStream() << "The build output will be saved in '" << junkpath << "'\n"; + Q_Exec( batpath, NULL, NULL, true, false ); + } + } - bsp_shutdown(); + bsp_shutdown(); } // ============================================================================= // Sys_ functions -void Sys_SetTitle(const char *text, bool modified) -{ - StringOutputStream title; - title << text; +void Sys_SetTitle( const char *text, bool modified ){ + StringOutputStream title; + title << text; - if (modified) { - title << " *"; - } + if ( modified ) { + title << " *"; + } - gtk_window_set_title(MainFrame_getWindow(), title.c_str()); + gtk_window_set_title(MainFrame_getWindow(), title.c_str() ); } bool g_bWaitCursor = false; -void Sys_BeginWait(void) -{ - ScreenUpdates_Disable("Processing...", "Please Wait"); - GdkCursor *cursor = gdk_cursor_new(GDK_WATCH); - gdk_window_set_cursor(gtk_widget_get_window(MainFrame_getWindow()), cursor); - gdk_cursor_unref(cursor); - g_bWaitCursor = true; +void Sys_BeginWait( void ){ + ScreenUpdates_Disable( "Processing...", "Please Wait" ); + GdkCursor *cursor = gdk_cursor_new( GDK_WATCH ); + gdk_window_set_cursor( gtk_widget_get_window(MainFrame_getWindow()), cursor ); + gdk_cursor_unref( cursor ); + g_bWaitCursor = true; } -void Sys_EndWait(void) -{ - ScreenUpdates_Enable(); - gdk_window_set_cursor(gtk_widget_get_window(MainFrame_getWindow()), 0); - g_bWaitCursor = false; +void Sys_EndWait( void ){ + ScreenUpdates_Enable(); + gdk_window_set_cursor(gtk_widget_get_window(MainFrame_getWindow()), 0 ); + g_bWaitCursor = false; } -void Sys_Beep(void) -{ - gdk_beep(); +void Sys_Beep( void ){ + gdk_beep(); } diff --git a/radiant/referencecache.cpp b/radiant/referencecache.cpp index 949eb55c..9ceeba1b 100644 --- a/radiant/referencecache.cpp +++ b/radiant/referencecache.cpp @@ -29,11 +29,11 @@ #include "iundo.h" #include "imap.h" -MapModules &ReferenceAPI_getMapModules(); +MapModules& ReferenceAPI_getMapModules(); #include "imodel.h" -ModelModules &ReferenceAPI_getModelModules(); +ModelModules& ReferenceAPI_getModelModules(); #include "ifilesystem.h" #include "iarchive.h" @@ -63,631 +63,604 @@ extern bool g_writeMapComments; bool References_Saved(); -void MapChanged() -{ - Map_SetModified(g_map, !References_Saved()); +void MapChanged(){ + Map_SetModified( g_map, !References_Saved() ); } -EntityCreator *g_entityCreator = 0; +EntityCreator* g_entityCreator = 0; + +bool MapResource_loadFile( const MapFormat& format, scene::Node& root, const char* filename ){ + globalOutputStream() << "Open file " << filename << " for read..."; + TextFileInputStream file( filename ); + if ( !file.failed() ) { + globalOutputStream() << "success\n"; + ScopeDisableScreenUpdates disableScreenUpdates( path_get_filename_start( filename ), "Loading Map" ); + ASSERT_NOTNULL( g_entityCreator ); + format.readGraph( root, file, *g_entityCreator ); + return true; + } + else + { + globalErrorStream() << "failure\n"; + return false; + } +} -bool MapResource_loadFile(const MapFormat &format, scene::Node &root, const char *filename) -{ - globalOutputStream() << "Open file " << filename << " for read..."; - TextFileInputStream file(filename); - if (!file.failed()) { - globalOutputStream() << "success\n"; - ScopeDisableScreenUpdates disableScreenUpdates(path_get_filename_start(filename), "Loading Map"); - ASSERT_NOTNULL(g_entityCreator); - format.readGraph(root, file, *g_entityCreator); - return true; - } else { - globalErrorStream() << "failure\n"; - return false; - } -} - -NodeSmartReference MapResource_load(const MapFormat &format, const char *path, const char *name) -{ - NodeSmartReference root(NewMapRoot(name)); +NodeSmartReference MapResource_load( const MapFormat& format, const char* path, const char* name ){ + NodeSmartReference root( NewMapRoot( name ) ); - StringOutputStream fullpath(256); - fullpath << path << name; + StringOutputStream fullpath( 256 ); + fullpath << path << name; - if (path_is_absolute(fullpath.c_str())) { - MapResource_loadFile(format, root, fullpath.c_str()); - } else { - globalErrorStream() << "map path is not fully qualified: " << makeQuoted(fullpath.c_str()) << "\n"; - } + if ( path_is_absolute( fullpath.c_str() ) ) { + MapResource_loadFile( format, root, fullpath.c_str() ); + } + else + { + globalErrorStream() << "map path is not fully qualified: " << makeQuoted( fullpath.c_str() ) << "\n"; + } - return root; + return root; } -bool MapResource_saveFile(const MapFormat &format, scene::Node &root, GraphTraversalFunc traverse, const char *filename) -{ - //ASSERT_MESSAGE(path_is_absolute(filename), "MapResource_saveFile: path is not absolute: " << makeQuoted(filename)); - globalOutputStream() << "Open file " << filename << " for write..."; - TextFileOutputStream file(filename); - if (!file.failed()) { - globalOutputStream() << "success\n"; - ScopeDisableScreenUpdates disableScreenUpdates(path_get_filename_start(filename), "Saving Map"); - format.writeGraph(root, traverse, file, g_writeMapComments); - return true; - } - - globalErrorStream() << "failure\n"; - return false; +bool MapResource_saveFile( const MapFormat& format, scene::Node& root, GraphTraversalFunc traverse, const char* filename ){ + //ASSERT_MESSAGE(path_is_absolute(filename), "MapResource_saveFile: path is not absolute: " << makeQuoted(filename)); + globalOutputStream() << "Open file " << filename << " for write..."; + TextFileOutputStream file( filename ); + if ( !file.failed() ) { + globalOutputStream() << "success\n"; + ScopeDisableScreenUpdates disableScreenUpdates( path_get_filename_start( filename ), "Saving Map" ); + format.writeGraph( root, traverse, file, g_writeMapComments ); + return true; + } + + globalErrorStream() << "failure\n"; + return false; } -bool file_saveBackup(const char *path) -{ - if (file_writeable(path)) { - StringOutputStream backup(256); - backup << StringRange(path, path_get_extension(path)) << "bak"; +bool file_saveBackup( const char* path ){ + if ( file_writeable( path ) ) { + StringOutputStream backup( 256 ); + backup << StringRange( path, path_get_extension( path ) ) << "bak"; - return (!file_exists(backup.c_str()) || file_remove(backup.c_str())) // remove backup - && file_move(path, backup.c_str()); // rename current to backup - } + return ( !file_exists( backup.c_str() ) || file_remove( backup.c_str() ) ) // remove backup + && file_move( path, backup.c_str() ); // rename current to backup + } - globalErrorStream() << "map path is not writeable: " << makeQuoted(path) << "\n"; - return false; + globalErrorStream() << "map path is not writeable: " << makeQuoted( path ) << "\n"; + return false; } -bool MapResource_save(const MapFormat &format, scene::Node &root, const char *path, const char *name) -{ - StringOutputStream fullpath(256); - fullpath << path << name; +bool MapResource_save( const MapFormat& format, scene::Node& root, const char* path, const char* name ){ + StringOutputStream fullpath( 256 ); + fullpath << path << name; - if (path_is_absolute(fullpath.c_str())) { - if (!file_exists(fullpath.c_str()) || file_saveBackup(fullpath.c_str())) { - return MapResource_saveFile(format, root, Map_Traverse, fullpath.c_str()); - } + if ( path_is_absolute( fullpath.c_str() ) ) { + if ( !file_exists( fullpath.c_str() ) || file_saveBackup( fullpath.c_str() ) ) { + return MapResource_saveFile( format, root, Map_Traverse, fullpath.c_str() ); + } - globalErrorStream() << "failed to save a backup map file: " << makeQuoted(fullpath.c_str()) << "\n"; - return false; - } + globalErrorStream() << "failed to save a backup map file: " << makeQuoted( fullpath.c_str() ) << "\n"; + return false; + } - globalErrorStream() << "map path is not fully qualified: " << makeQuoted(fullpath.c_str()) << "\n"; - return false; + globalErrorStream() << "map path is not fully qualified: " << makeQuoted( fullpath.c_str() ) << "\n"; + return false; } -namespace { - NodeSmartReference g_nullNode(NewNullNode()); - NodeSmartReference g_nullModel(g_nullNode); +namespace +{ +NodeSmartReference g_nullNode( NewNullNode() ); +NodeSmartReference g_nullModel( g_nullNode ); } -class NullModelLoader : public ModelLoader { +class NullModelLoader : public ModelLoader +{ public: - scene::Node &loadModel(ArchiveFile &file) - { - return g_nullModel; - } +scene::Node& loadModel( ArchiveFile& file ){ + return g_nullModel; +} }; -namespace { - NullModelLoader g_NullModelLoader; +namespace +{ +NullModelLoader g_NullModelLoader; } /// \brief Returns the model loader for the model \p type or 0 if the model \p type has no loader module -ModelLoader *ModelLoader_forType(const char *type) -{ - const char *moduleName = findModuleName(&GlobalFiletypes(), ModelLoader::Name(), type); - if (string_not_empty(moduleName)) { - ModelLoader *table = ReferenceAPI_getModelModules().findModule(moduleName); - if (table != 0) { - return table; - } else { - globalErrorStream() << "ERROR: Model type incorrectly registered: \"" << moduleName << "\"\n"; - return &g_NullModelLoader; - } - } - return 0; -} - -NodeSmartReference ModelResource_load(ModelLoader *loader, const char *name) -{ - ScopeDisableScreenUpdates disableScreenUpdates(path_get_filename_start(name), "Loading Model"); +ModelLoader* ModelLoader_forType( const char* type ){ + const char* moduleName = findModuleName( &GlobalFiletypes(), ModelLoader::Name(), type ); + if ( string_not_empty( moduleName ) ) { + ModelLoader* table = ReferenceAPI_getModelModules().findModule( moduleName ); + if ( table != 0 ) { + return table; + } + else + { + globalErrorStream() << "ERROR: Model type incorrectly registered: \"" << moduleName << "\"\n"; + return &g_NullModelLoader; + } + } + return 0; +} + +NodeSmartReference ModelResource_load( ModelLoader* loader, const char* name ){ + ScopeDisableScreenUpdates disableScreenUpdates( path_get_filename_start( name ), "Loading Model" ); - NodeSmartReference model(g_nullModel); + NodeSmartReference model( g_nullModel ); - { - ArchiveFile *file = GlobalFileSystem().openFile(name); + { + ArchiveFile* file = GlobalFileSystem().openFile( name ); - if (file != 0) { - globalOutputStream() << "Loaded Model: \"" << name << "\"\n"; - model = loader->loadModel(*file); - file->release(); - } else { - globalErrorStream() << "Model load failed: \"" << name << "\"\n"; - } - } + if ( file != 0 ) { + globalOutputStream() << "Loaded Model: \"" << name << "\"\n"; + model = loader->loadModel( *file ); + file->release(); + } + else + { + globalErrorStream() << "Model load failed: \"" << name << "\"\n"; + } + } - model.get().m_isRoot = true; + model.get().m_isRoot = true; - return model; + return model; } -inline hash_t path_hash(const char *path, hash_t previous = 0) -{ +inline hash_t path_hash( const char* path, hash_t previous = 0 ){ #if GDEF_OS_WINDOWS - return string_hash_nocase( path, previous ); + return string_hash_nocase( path, previous ); #else // UNIX - return string_hash(path, previous); + return string_hash( path, previous ); #endif } -struct PathEqual { - bool operator()(const CopiedString &path, const CopiedString &other) const - { - return path_equal(path.c_str(), other.c_str()); - } +struct PathEqual +{ + bool operator()( const CopiedString& path, const CopiedString& other ) const { + return path_equal( path.c_str(), other.c_str() ); + } }; -struct PathHash { - typedef hash_t hash_type; +struct PathHash +{ + typedef hash_t hash_type; - hash_type operator()(const CopiedString &path) const - { - return path_hash(path.c_str()); - } + hash_type operator()( const CopiedString& path ) const { + return path_hash( path.c_str() ); + } }; typedef std::pair ModelKey; -struct ModelKeyEqual { - bool operator()(const ModelKey &key, const ModelKey &other) const - { - return path_equal(key.first.c_str(), other.first.c_str()) && - path_equal(key.second.c_str(), other.second.c_str()); - } +struct ModelKeyEqual +{ + bool operator()( const ModelKey& key, const ModelKey& other ) const { + return path_equal( key.first.c_str(), other.first.c_str() ) && path_equal( key.second.c_str(), other.second.c_str() ); + } }; -struct ModelKeyHash { - typedef hash_t hash_type; +struct ModelKeyHash +{ + typedef hash_t hash_type; - hash_type operator()(const ModelKey &key) const - { - return hash_combine(path_hash(key.first.c_str()), path_hash(key.second.c_str())); - } + hash_type operator()( const ModelKey& key ) const { + return hash_combine( path_hash( key.first.c_str() ), path_hash( key.second.c_str() ) ); + } }; typedef HashTable ModelCache; ModelCache g_modelCache; bool g_modelCache_enabled = true; -ModelCache::iterator ModelCache_find(const char *path, const char *name) -{ - if (g_modelCache_enabled) { - return g_modelCache.find(ModelKey(path, name)); - } - return g_modelCache.end(); +ModelCache::iterator ModelCache_find( const char* path, const char* name ){ + if ( g_modelCache_enabled ) { + return g_modelCache.find( ModelKey( path, name ) ); + } + return g_modelCache.end(); } -ModelCache::iterator ModelCache_insert(const char *path, const char *name, scene::Node &node) -{ - if (g_modelCache_enabled) { - return g_modelCache.insert(ModelKey(path, name), NodeSmartReference(node)); - } - return g_modelCache.insert(ModelKey("", ""), g_nullModel); +ModelCache::iterator ModelCache_insert( const char* path, const char* name, scene::Node& node ){ + if ( g_modelCache_enabled ) { + return g_modelCache.insert( ModelKey( path, name ), NodeSmartReference( node ) ); + } + return g_modelCache.insert( ModelKey( "", "" ), g_nullModel ); } -void ModelCache_flush(const char *path, const char *name) -{ - ModelCache::iterator i = g_modelCache.find(ModelKey(path, name)); - if (i != g_modelCache.end()) { - //ASSERT_MESSAGE((*i).value.getCount() == 0, "resource flushed while still in use: " << (*i).key.first.c_str() << (*i).key.second.c_str()); - g_modelCache.erase(i); - } +void ModelCache_flush( const char* path, const char* name ){ + ModelCache::iterator i = g_modelCache.find( ModelKey( path, name ) ); + if ( i != g_modelCache.end() ) { + //ASSERT_MESSAGE((*i).value.getCount() == 0, "resource flushed while still in use: " << (*i).key.first.c_str() << (*i).key.second.c_str()); + g_modelCache.erase( i ); + } } -void ModelCache_clear() -{ - g_modelCache_enabled = false; - g_modelCache.clear(); - g_modelCache_enabled = true; +void ModelCache_clear(){ + g_modelCache_enabled = false; + g_modelCache.clear(); + g_modelCache_enabled = true; } -NodeSmartReference Model_load(ModelLoader *loader, const char *path, const char *name, const char *type) +NodeSmartReference Model_load( ModelLoader* loader, const char* path, const char* name, const char* type ){ + if ( loader != 0 ) { + return ModelResource_load( loader, name ); + } + else + { + const char* moduleName = findModuleName( &GlobalFiletypes(), MapFormat::Name(), type ); + if ( string_not_empty( moduleName ) ) { + const MapFormat* format = ReferenceAPI_getMapModules().findModule( moduleName ); + if ( format != 0 ) { + return MapResource_load( *format, path, name ); + } + else + { + globalErrorStream() << "ERROR: Map type incorrectly registered: \"" << moduleName << "\"\n"; + return g_nullModel; + } + } + else + { + if ( string_not_empty( type ) ) { + globalErrorStream() << "Model type not supported: \"" << name << "\"\n"; + } + return g_nullModel; + } + } +} + +namespace { - if (loader != 0) { - return ModelResource_load(loader, name); - } else { - const char *moduleName = findModuleName(&GlobalFiletypes(), MapFormat::Name(), type); - if (string_not_empty(moduleName)) { - const MapFormat *format = ReferenceAPI_getMapModules().findModule(moduleName); - if (format != 0) { - return MapResource_load(*format, path, name); - } else { - globalErrorStream() << "ERROR: Map type incorrectly registered: \"" << moduleName << "\"\n"; - return g_nullModel; - } - } else { - if (string_not_empty(type)) { - globalErrorStream() << "Model type not supported: \"" << name << "\"\n"; - } - return g_nullModel; - } - } -} - -namespace { - bool g_realised = false; +bool g_realised = false; // name may be absolute or relative - const char *rootPath(const char *name) - { - return GlobalFileSystem().findRoot( - path_is_absolute(name) - ? name - : GlobalFileSystem().findFile(name) - ); - } -} - -struct ModelResource : public Resource { - NodeSmartReference m_model; - const CopiedString m_originalName; - CopiedString m_path; - CopiedString m_name; - CopiedString m_type; - ModelLoader *m_loader; - ModuleObservers m_observers; - std::time_t m_modified; - std::size_t m_unrealised; - - ModelResource(const CopiedString &name) : - m_model(g_nullModel), - m_originalName(name), - m_type(path_get_extension(name.c_str())), - m_loader(0), - m_modified(0), - m_unrealised(1) - { - m_loader = ModelLoader_forType(m_type.c_str()); - - if (g_realised) { - realise(); - } - } - - ~ModelResource() - { - if (realised()) { - unrealise(); - } - ASSERT_MESSAGE(!realised(), "ModelResource::~ModelResource: resource reference still realised: " - << makeQuoted(m_name.c_str())); - } - - // NOT COPYABLE - ModelResource(const ModelResource &); - - // NOT ASSIGNABLE - ModelResource &operator=(const ModelResource &); - - void setModel(const NodeSmartReference &model) - { - m_model = model; - } - - void clearModel() - { - m_model = g_nullModel; - } - - void loadCached() - { - if (g_modelCache_enabled) { - // cache lookup - ModelCache::iterator i = ModelCache_find(m_path.c_str(), m_name.c_str()); - if (i == g_modelCache.end()) { - i = ModelCache_insert( - m_path.c_str(), - m_name.c_str(), - Model_load(m_loader, m_path.c_str(), m_name.c_str(), m_type.c_str()) - ); - } - - setModel((*i).value); - } else { - setModel(Model_load(m_loader, m_path.c_str(), m_name.c_str(), m_type.c_str())); - } - } - - void loadModel() - { - loadCached(); - connectMap(); - mapSave(); - } - - bool load() - { - ASSERT_MESSAGE(realised(), "resource not realised"); - if (m_model == g_nullModel) { - loadModel(); - } - - return m_model != g_nullModel; - } - - bool save() - { - if (!mapSaved()) { - const char *moduleName = findModuleName(GetFileTypeRegistry(), MapFormat::Name(), m_type.c_str()); - if (string_not_empty(moduleName)) { - const MapFormat *format = ReferenceAPI_getMapModules().findModule(moduleName); - if (format != 0 && MapResource_save(*format, m_model.get(), m_path.c_str(), m_name.c_str())) { - mapSave(); - return true; - } - } - } - return false; - } - - void flush() - { - if (realised()) { - ModelCache_flush(m_path.c_str(), m_name.c_str()); - } - } - - scene::Node *getNode() - { - //if(m_model != g_nullModel) - { - return m_model.get_pointer(); - } - //return 0; - } - - void setNode(scene::Node *node) - { - ModelCache::iterator i = ModelCache_find(m_path.c_str(), m_name.c_str()); - if (i != g_modelCache.end()) { - (*i).value = NodeSmartReference(*node); - } - setModel(NodeSmartReference(*node)); - - connectMap(); - } - - void attach(ModuleObserver &observer) - { - if (realised()) { - observer.realise(); - } - m_observers.attach(observer); - } - - void detach(ModuleObserver &observer) - { - if (realised()) { - observer.unrealise(); - } - m_observers.detach(observer); - } - - bool realised() - { - return m_unrealised == 0; - } - - void realise() - { - ASSERT_MESSAGE(m_unrealised != 0, "ModelResource::realise: already realised"); - if (--m_unrealised == 0) { - m_path = rootPath(m_originalName.c_str()); - m_name = path_make_relative(m_originalName.c_str(), m_path.c_str()); - - //globalOutputStream() << "ModelResource::realise: " << m_path.c_str() << m_name.c_str() << "\n"; - - m_observers.realise(); - } - } - - void unrealise() - { - if (++m_unrealised == 1) { - m_observers.unrealise(); - - //globalOutputStream() << "ModelResource::unrealise: " << m_path.c_str() << m_name.c_str() << "\n"; - clearModel(); - } - } - - bool isMap() const - { - return Node_getMapFile(m_model) != 0; - } - - void connectMap() - { - MapFile *map = Node_getMapFile(m_model); - if (map != 0) { - map->setChangedCallback(makeCallbackF(MapChanged)); - } - } - - std::time_t modified() const - { - StringOutputStream fullpath(256); - fullpath << m_path.c_str() << m_name.c_str(); - return file_modified(fullpath.c_str()); - } - - void mapSave() - { - m_modified = modified(); - MapFile *map = Node_getMapFile(m_model); - if (map != 0) { - map->save(); - } - } - - bool mapSaved() const - { - MapFile *map = Node_getMapFile(m_model); - if (map != 0) { - return m_modified == modified() && map->saved(); - } - return true; - } - - bool isModified() const - { - return ((!string_empty(m_path.c_str()) // had or has an absolute path - && m_modified != modified()) // AND disk timestamp changed - || !path_equal(rootPath(m_originalName.c_str()), m_path.c_str())); // OR absolute vfs-root changed - } - - void refresh() - { - if (isModified()) { - flush(); - unrealise(); - realise(); - } - } +const char* rootPath( const char* name ){ + return GlobalFileSystem().findRoot( + path_is_absolute( name ) + ? name + : GlobalFileSystem().findFile( name ) + ); +} +} + +struct ModelResource : public Resource +{ + NodeSmartReference m_model; + const CopiedString m_originalName; + CopiedString m_path; + CopiedString m_name; + CopiedString m_type; + ModelLoader* m_loader; + ModuleObservers m_observers; + std::time_t m_modified; + std::size_t m_unrealised; + + ModelResource( const CopiedString& name ) : + m_model( g_nullModel ), + m_originalName( name ), + m_type( path_get_extension( name.c_str() ) ), + m_loader( 0 ), + m_modified( 0 ), + m_unrealised( 1 ){ + m_loader = ModelLoader_forType( m_type.c_str() ); + + if ( g_realised ) { + realise(); + } + } + + ~ModelResource(){ + if ( realised() ) { + unrealise(); + } + ASSERT_MESSAGE( !realised(), "ModelResource::~ModelResource: resource reference still realised: " << makeQuoted( m_name.c_str() ) ); + } + + // NOT COPYABLE + ModelResource( const ModelResource& ); + + // NOT ASSIGNABLE + ModelResource& operator=( const ModelResource& ); + + void setModel( const NodeSmartReference& model ){ + m_model = model; + } + + void clearModel(){ + m_model = g_nullModel; + } + + void loadCached(){ + if ( g_modelCache_enabled ) { + // cache lookup + ModelCache::iterator i = ModelCache_find( m_path.c_str(), m_name.c_str() ); + if ( i == g_modelCache.end() ) { + i = ModelCache_insert( + m_path.c_str(), + m_name.c_str(), + Model_load( m_loader, m_path.c_str(), m_name.c_str(), m_type.c_str() ) + ); + } + + setModel( ( *i ).value ); + } + else + { + setModel( Model_load( m_loader, m_path.c_str(), m_name.c_str(), m_type.c_str() ) ); + } + } + + void loadModel(){ + loadCached(); + connectMap(); + mapSave(); + } + + bool load(){ + ASSERT_MESSAGE( realised(), "resource not realised" ); + if ( m_model == g_nullModel ) { + loadModel(); + } + + return m_model != g_nullModel; + } + + bool save(){ + if ( !mapSaved() ) { + const char* moduleName = findModuleName( GetFileTypeRegistry(), MapFormat::Name(), m_type.c_str() ); + if ( string_not_empty( moduleName ) ) { + const MapFormat* format = ReferenceAPI_getMapModules().findModule( moduleName ); + if ( format != 0 && MapResource_save( *format, m_model.get(), m_path.c_str(), m_name.c_str() ) ) { + mapSave(); + return true; + } + } + } + return false; + } + + void flush(){ + if ( realised() ) { + ModelCache_flush( m_path.c_str(), m_name.c_str() ); + } + } + + scene::Node* getNode(){ + //if(m_model != g_nullModel) + { + return m_model.get_pointer(); + } + //return 0; + } + + void setNode( scene::Node* node ){ + ModelCache::iterator i = ModelCache_find( m_path.c_str(), m_name.c_str() ); + if ( i != g_modelCache.end() ) { + ( *i ).value = NodeSmartReference( *node ); + } + setModel( NodeSmartReference( *node ) ); + + connectMap(); + } + + void attach( ModuleObserver& observer ){ + if ( realised() ) { + observer.realise(); + } + m_observers.attach( observer ); + } + + void detach( ModuleObserver& observer ){ + if ( realised() ) { + observer.unrealise(); + } + m_observers.detach( observer ); + } + + bool realised(){ + return m_unrealised == 0; + } + + void realise(){ + ASSERT_MESSAGE( m_unrealised != 0, "ModelResource::realise: already realised" ); + if ( --m_unrealised == 0 ) { + m_path = rootPath( m_originalName.c_str() ); + m_name = path_make_relative( m_originalName.c_str(), m_path.c_str() ); + + //globalOutputStream() << "ModelResource::realise: " << m_path.c_str() << m_name.c_str() << "\n"; + + m_observers.realise(); + } + } + + void unrealise(){ + if ( ++m_unrealised == 1 ) { + m_observers.unrealise(); + + //globalOutputStream() << "ModelResource::unrealise: " << m_path.c_str() << m_name.c_str() << "\n"; + clearModel(); + } + } + + bool isMap() const { + return Node_getMapFile( m_model ) != 0; + } + + void connectMap(){ + MapFile* map = Node_getMapFile( m_model ); + if ( map != 0 ) { + map->setChangedCallback( makeCallbackF(MapChanged) ); + } + } + + std::time_t modified() const { + StringOutputStream fullpath( 256 ); + fullpath << m_path.c_str() << m_name.c_str(); + return file_modified( fullpath.c_str() ); + } + + void mapSave(){ + m_modified = modified(); + MapFile* map = Node_getMapFile( m_model ); + if ( map != 0 ) { + map->save(); + } + } + + bool mapSaved() const { + MapFile* map = Node_getMapFile( m_model ); + if ( map != 0 ) { + return m_modified == modified() && map->saved(); + } + return true; + } + + bool isModified() const { + return ( ( !string_empty( m_path.c_str() ) // had or has an absolute path + && m_modified != modified() ) // AND disk timestamp changed + || !path_equal( rootPath( m_originalName.c_str() ), m_path.c_str() ) ); // OR absolute vfs-root changed + } + + void refresh(){ + if ( isModified() ) { + flush(); + unrealise(); + realise(); + } + } }; -class HashtableReferenceCache : public ReferenceCache, public ModuleObserver { - typedef HashedCache ModelReferences; - ModelReferences m_references; - std::size_t m_unrealised; - - class ModelReferencesSnapshot { - ModelReferences &m_references; - typedef std::list Iterators; - Iterators m_iterators; - public: - typedef Iterators::iterator iterator; - - ModelReferencesSnapshot(ModelReferences &references) : m_references(references) - { - for (ModelReferences::iterator i = m_references.begin(); i != m_references.end(); ++i) { - m_references.capture(i); - m_iterators.push_back(i); - } - } - - ~ModelReferencesSnapshot() - { - for (Iterators::iterator i = m_iterators.begin(); i != m_iterators.end(); ++i) { - m_references.release(*i); - } - } - - iterator begin() - { - return m_iterators.begin(); - } - - iterator end() - { - return m_iterators.end(); - } - }; +class HashtableReferenceCache : public ReferenceCache, public ModuleObserver +{ +typedef HashedCache ModelReferences; +ModelReferences m_references; +std::size_t m_unrealised; + +class ModelReferencesSnapshot +{ +ModelReferences& m_references; +typedef std::list Iterators; +Iterators m_iterators; +public: +typedef Iterators::iterator iterator; + +ModelReferencesSnapshot( ModelReferences& references ) : m_references( references ){ + for ( ModelReferences::iterator i = m_references.begin(); i != m_references.end(); ++i ) + { + m_references.capture( i ); + m_iterators.push_back( i ); + } +} + +~ModelReferencesSnapshot(){ + for ( Iterators::iterator i = m_iterators.begin(); i != m_iterators.end(); ++i ) + { + m_references.release( *i ); + } +} + +iterator begin(){ + return m_iterators.begin(); +} + +iterator end(){ + return m_iterators.end(); +} +}; public: - typedef ModelReferences::iterator iterator; - - HashtableReferenceCache() : m_unrealised(1) - { - } - - iterator begin() - { - return m_references.begin(); - } - - iterator end() - { - return m_references.end(); - } - - void clear() - { - m_references.clear(); - } - - Resource *capture(const char *path) - { - //globalOutputStream() << "capture: \"" << path << "\"\n"; - return m_references.capture(CopiedString(path)).get(); - } - - void release(const char *path) - { - m_references.release(CopiedString(path)); - //globalOutputStream() << "release: \"" << path << "\"\n"; - } - - void setEntityCreator(EntityCreator &entityCreator) - { - g_entityCreator = &entityCreator; - } - - bool realised() const - { - return m_unrealised == 0; - } - - void realise() - { - ASSERT_MESSAGE(m_unrealised != 0, "HashtableReferenceCache::realise: already realised"); - if (--m_unrealised == 0) { - g_realised = true; - - { - ModelReferencesSnapshot snapshot(m_references); - for (ModelReferencesSnapshot::iterator i = snapshot.begin(); i != snapshot.end(); ++i) { - ModelReferences::value_type &value = *(*i); - if (value.value.count() != 1) { - value.value.get()->realise(); - } - } - } - } - } - - void unrealise() - { - if (++m_unrealised == 1) { - g_realised = false; - - { - ModelReferencesSnapshot snapshot(m_references); - for (ModelReferencesSnapshot::iterator i = snapshot.begin(); i != snapshot.end(); ++i) { - ModelReferences::value_type &value = *(*i); - if (value.value.count() != 1) { - value.value.get()->unrealise(); - } - } - } - - ModelCache_clear(); - } - } - - void refresh() - { - ModelReferencesSnapshot snapshot(m_references); - for (ModelReferencesSnapshot::iterator i = snapshot.begin(); i != snapshot.end(); ++i) { - ModelResource *resource = (*(*i)).value.get(); - if (!resource->isMap()) { - resource->refresh(); - } - } - } +typedef ModelReferences::iterator iterator; + +HashtableReferenceCache() : m_unrealised( 1 ){ +} + +iterator begin(){ + return m_references.begin(); +} + +iterator end(){ + return m_references.end(); +} + +void clear(){ + m_references.clear(); +} + +Resource* capture( const char* path ){ + //globalOutputStream() << "capture: \"" << path << "\"\n"; + return m_references.capture( CopiedString( path ) ).get(); +} + +void release( const char* path ){ + m_references.release( CopiedString( path ) ); + //globalOutputStream() << "release: \"" << path << "\"\n"; +} + +void setEntityCreator( EntityCreator& entityCreator ){ + g_entityCreator = &entityCreator; +} + +bool realised() const { + return m_unrealised == 0; +} + +void realise(){ + ASSERT_MESSAGE( m_unrealised != 0, "HashtableReferenceCache::realise: already realised" ); + if ( --m_unrealised == 0 ) { + g_realised = true; + + { + ModelReferencesSnapshot snapshot( m_references ); + for ( ModelReferencesSnapshot::iterator i = snapshot.begin(); i != snapshot.end(); ++i ) + { + ModelReferences::value_type& value = *( *i ); + if ( value.value.count() != 1 ) { + value.value.get()->realise(); + } + } + } + } +} + +void unrealise(){ + if ( ++m_unrealised == 1 ) { + g_realised = false; + + { + ModelReferencesSnapshot snapshot( m_references ); + for ( ModelReferencesSnapshot::iterator i = snapshot.begin(); i != snapshot.end(); ++i ) + { + ModelReferences::value_type& value = *( *i ); + if ( value.value.count() != 1 ) { + value.value.get()->unrealise(); + } + } + } + + ModelCache_clear(); + } +} + +void refresh(){ + ModelReferencesSnapshot snapshot( m_references ); + for ( ModelReferencesSnapshot::iterator i = snapshot.begin(); i != snapshot.end(); ++i ) + { + ModelResource* resource = ( *( *i ) ).value.get(); + if ( !resource->isMap() ) { + resource->refresh(); + } + } +} }; -namespace { - HashtableReferenceCache g_referenceCache; +namespace +{ +HashtableReferenceCache g_referenceCache; } #if 0 @@ -695,49 +668,46 @@ class ResourceVisitor { public: virtual void visit( const char* name, const char* path, const - }; + }; #endif -void SaveReferences() -{ - ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Saving Map"); - for (HashtableReferenceCache::iterator i = g_referenceCache.begin(); i != g_referenceCache.end(); ++i) { - (*i).value->save(); - } - MapChanged(); +void SaveReferences(){ + ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Saving Map" ); + for ( HashtableReferenceCache::iterator i = g_referenceCache.begin(); i != g_referenceCache.end(); ++i ) + { + ( *i ).value->save(); + } + MapChanged(); } -bool References_Saved() -{ - for (HashtableReferenceCache::iterator i = g_referenceCache.begin(); i != g_referenceCache.end(); ++i) { - scene::Node *node = (*i).value->getNode(); - if (node != 0) { - MapFile *map = Node_getMapFile(*node); - if (map != 0 && !map->saved()) { - return false; - } - } - } - return true; -} - -void RefreshReferences() -{ - ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Refreshing Models"); - g_referenceCache.refresh(); +bool References_Saved(){ + for ( HashtableReferenceCache::iterator i = g_referenceCache.begin(); i != g_referenceCache.end(); ++i ) + { + scene::Node* node = ( *i ).value->getNode(); + if ( node != 0 ) { + MapFile* map = Node_getMapFile( *node ); + if ( map != 0 && !map->saved() ) { + return false; + } + } + } + return true; } +void RefreshReferences(){ + ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Refreshing Models" ); + g_referenceCache.refresh(); +} -void FlushReferences() -{ - ModelCache_clear(); - g_referenceCache.clear(); +void FlushReferences(){ + ModelCache_clear(); + + g_referenceCache.clear(); } -ReferenceCache &GetReferenceCache() -{ - return g_referenceCache; +ReferenceCache& GetReferenceCache(){ + return g_referenceCache; } @@ -746,68 +716,63 @@ ReferenceCache &GetReferenceCache() #include "modulesystem/moduleregistry.h" class ReferenceDependencies : - public GlobalRadiantModuleRef, - public GlobalFileSystemModuleRef, - public GlobalFiletypesModuleRef { - ModelModulesRef m_model_modules; - MapModulesRef m_map_modules; + public GlobalRadiantModuleRef, + public GlobalFileSystemModuleRef, + public GlobalFiletypesModuleRef +{ +ModelModulesRef m_model_modules; +MapModulesRef m_map_modules; public: - ReferenceDependencies() : - m_model_modules(GlobalRadiant().getRequiredGameDescriptionKeyValue("modeltypes")), - m_map_modules(GlobalRadiant().getRequiredGameDescriptionKeyValue("maptypes")) - { - } - - ModelModules &getModelModules() - { - return m_model_modules.get(); - } - - MapModules &getMapModules() - { - return m_map_modules.get(); - } +ReferenceDependencies() : + m_model_modules( GlobalRadiant().getRequiredGameDescriptionKeyValue( "modeltypes" ) ), + m_map_modules( GlobalRadiant().getRequiredGameDescriptionKeyValue( "maptypes" ) ) +{ +} + +ModelModules& getModelModules(){ + return m_model_modules.get(); +} + +MapModules& getMapModules(){ + return m_map_modules.get(); +} }; -class ReferenceAPI : public TypeSystemRef { - ReferenceCache *m_reference; +class ReferenceAPI : public TypeSystemRef +{ +ReferenceCache* m_reference; public: - typedef ReferenceCache Type; +typedef ReferenceCache Type; - STRING_CONSTANT(Name, "*"); +STRING_CONSTANT( Name, "*" ); - ReferenceAPI() - { - g_nullModel = NewNullModel(); +ReferenceAPI(){ + g_nullModel = NewNullModel(); - GlobalFileSystem().attach(g_referenceCache); + GlobalFileSystem().attach( g_referenceCache ); - m_reference = &GetReferenceCache(); - } + m_reference = &GetReferenceCache(); +} - ~ReferenceAPI() - { - GlobalFileSystem().detach(g_referenceCache); +~ReferenceAPI(){ + GlobalFileSystem().detach( g_referenceCache ); - g_nullModel = g_nullNode; - } + g_nullModel = g_nullNode; +} - ReferenceCache *getTable() - { - return m_reference; - } +ReferenceCache* getTable(){ + return m_reference; +} }; typedef SingletonModule ReferenceModule; typedef Static StaticReferenceModule; -StaticRegisterModule staticRegisterReference(StaticReferenceModule::instance()); +StaticRegisterModule staticRegisterReference( StaticReferenceModule::instance() ); -ModelModules &ReferenceAPI_getModelModules() -{ - return StaticReferenceModule::instance().getDependencies().getModelModules(); +ModelModules& ReferenceAPI_getModelModules(){ + return StaticReferenceModule::instance().getDependencies().getModelModules(); } -MapModules &ReferenceAPI_getMapModules() -{ - return StaticReferenceModule::instance().getDependencies().getMapModules(); +MapModules& ReferenceAPI_getMapModules(){ + return StaticReferenceModule::instance().getDependencies().getMapModules( ); } diff --git a/radiant/renderstate.cpp b/radiant/renderstate.cpp index 1da08b71..fa4fa1a3 100644 --- a/radiant/renderstate.cpp +++ b/radiant/renderstate.cpp @@ -56,24 +56,21 @@ #define DEBUG_RENDER 0 -inline void debug_string(const char *string) -{ +inline void debug_string( const char* string ){ #if (DEBUG_RENDER) - globalOutputStream() << string << "\n"; + globalOutputStream() << string << "\n"; #endif } -inline void debug_int(const char *comment, int i) -{ +inline void debug_int( const char* comment, int i ){ #if (DEBUG_RENDER) - globalOutputStream() << comment << " " << i << "\n"; + globalOutputStream() << comment << " " << i << "\n"; #endif } -inline void debug_colour(const char *comment) -{ -#if (DEBUG_RENDER) - Vector4 v; +inline void debug_colour( const char* comment ){ +#if ( DEBUG_RENDER ) + Vector4 v; glGetFloatv( GL_CURRENT_COLOR, reinterpret_cast( &v ) ); globalOutputStream() << comment << " colour: " << v[0] << " " @@ -98,298 +95,277 @@ std::size_t g_count_states; std::size_t g_count_transforms; Timer g_timer; -inline void count_prim() -{ - ++g_count_prims; +inline void count_prim(){ + ++g_count_prims; } -inline void count_state() -{ - ++g_count_states; +inline void count_state(){ + ++g_count_states; } -inline void count_transform() -{ - ++g_count_transforms; +inline void count_transform(){ + ++g_count_transforms; } -void Renderer_ResetStats() -{ - g_count_prims = 0; - g_count_states = 0; - g_count_transforms = 0; - g_timer.start(); +void Renderer_ResetStats(){ + g_count_prims = 0; + g_count_states = 0; + g_count_transforms = 0; + g_timer.start(); } -const char *Renderer_GetStats() -{ - g_renderer_stats.clear(); - g_renderer_stats << "prims: " << Unsigned(g_count_prims) - << " | states: " << Unsigned(g_count_states) - << " | transforms: " << Unsigned(g_count_transforms) - << " | msec: " << g_timer.elapsed_msec(); - return g_renderer_stats.c_str(); +const char* Renderer_GetStats(){ + g_renderer_stats.clear(); + g_renderer_stats << "prims: " << Unsigned( g_count_prims ) + << " | states: " << Unsigned( g_count_states ) + << " | transforms: " << Unsigned( g_count_transforms ) + << " | msec: " << g_timer.elapsed_msec(); + return g_renderer_stats.c_str(); } -void printShaderLog(GLhandleARB object) -{ - GLint log_length = 0; - glGetObjectParameterivARB(object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_length); +void printShaderLog( GLhandleARB object ){ + GLint log_length = 0; + glGetObjectParameterivARB( object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_length ); - Array log(log_length); - glGetInfoLogARB(object, log_length, &log_length, log.data()); + Array log( log_length ); + glGetInfoLogARB( object, log_length, &log_length, log.data() ); - globalErrorStream() << StringRange(log.begin(), log.begin() + log_length) << "\n"; + globalErrorStream() << StringRange( log.begin(), log.begin() + log_length ) << "\n"; } -void createShader(GLhandleARB program, const char *filename, GLenum type) -{ - GLhandleARB shader = glCreateShaderObjectARB(type); - GlobalOpenGL_debugAssertNoErrors(); - - // load shader - { - std::size_t size = file_size(filename); - FileInputStream file(filename); - ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename)); - Array buffer(size); - size = file.read(reinterpret_cast( buffer.data()), size); +void createShader( GLhandleARB program, const char* filename, GLenum type ){ + GLhandleARB shader = glCreateShaderObjectARB( type ); + GlobalOpenGL_debugAssertNoErrors(); - const GLcharARB *string = buffer.data(); - GLint length = GLint(size); - glShaderSourceARB(shader, 1, &string, &length); - } + // load shader + { + std::size_t size = file_size( filename ); + FileInputStream file( filename ); + ASSERT_MESSAGE( !file.failed(), "failed to open " << makeQuoted( filename ) ); + Array buffer( size ); + size = file.read( reinterpret_cast( buffer.data() ), size ); + + const GLcharARB* string = buffer.data(); + GLint length = GLint( size ); + glShaderSourceARB( shader, 1, &string, &length ); + } - // compile shader - { - glCompileShaderARB(shader); + // compile shader + { + glCompileShaderARB( shader ); - GLint compiled = 0; - glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); + GLint compiled = 0; + glGetObjectParameterivARB( shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled ); - if (!compiled) { - printShaderLog(shader); - } + if ( !compiled ) { + printShaderLog( shader ); + } - ASSERT_MESSAGE(compiled, "shader compile failed: " << makeQuoted(filename)); - } + ASSERT_MESSAGE( compiled, "shader compile failed: " << makeQuoted( filename ) ); + } - // attach shader - glAttachObjectARB(program, shader); + // attach shader + glAttachObjectARB( program, shader ); - glDeleteObjectARB(shader); + glDeleteObjectARB( shader ); - GlobalOpenGL_debugAssertNoErrors(); + GlobalOpenGL_debugAssertNoErrors(); } -void GLSLProgram_link(GLhandleARB program) -{ - glLinkProgramARB(program); +void GLSLProgram_link( GLhandleARB program ){ + glLinkProgramARB( program ); - GLint linked = false; - glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linked); + GLint linked = false; + glGetObjectParameterivARB( program, GL_OBJECT_LINK_STATUS_ARB, &linked ); - if (!linked) { - printShaderLog(program); - } + if ( !linked ) { + printShaderLog( program ); + } - ASSERT_MESSAGE(linked, "program link failed"); + ASSERT_MESSAGE( linked, "program link failed" ); } -void GLSLProgram_validate(GLhandleARB program) -{ - glValidateProgramARB(program); +void GLSLProgram_validate( GLhandleARB program ){ + glValidateProgramARB( program ); - GLint validated = false; - glGetObjectParameterivARB(program, GL_OBJECT_VALIDATE_STATUS_ARB, &validated); + GLint validated = false; + glGetObjectParameterivARB( program, GL_OBJECT_VALIDATE_STATUS_ARB, &validated ); - if (!validated) { - printShaderLog(program); - } + if ( !validated ) { + printShaderLog( program ); + } - ASSERT_MESSAGE(validated, "program validation failed"); + ASSERT_MESSAGE( validated, "program validation failed" ); } bool g_bumpGLSLPass_enabled = false; bool g_depthfillPass_enabled = false; -class GLSLBumpProgram : public GLProgram { +class GLSLBumpProgram : public GLProgram +{ public: - GLhandleARB m_program; - qtexture_t *m_light_attenuation_xy; - qtexture_t *m_light_attenuation_z; - GLint u_view_origin; - GLint u_light_origin; - GLint u_light_color; - GLint u_bump_scale; - GLint u_specular_exponent; - - GLSLBumpProgram() : m_program(0), m_light_attenuation_xy(0), m_light_attenuation_z(0) - { - } - - void create() - { - // create program - m_program = glCreateProgramObjectARB(); - - // create shader - { - StringOutputStream filename(256); - filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glsl"; - createShader(m_program, filename.c_str(), GL_VERTEX_SHADER_ARB); - filename.clear(); - filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glsl"; - createShader(m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB); - } - - GLSLProgram_link(m_program); - GLSLProgram_validate(m_program); - - glUseProgramObjectARB(m_program); - - glBindAttribLocationARB(m_program, c_attr_TexCoord0, "attr_TexCoord0"); - glBindAttribLocationARB(m_program, c_attr_Tangent, "attr_Tangent"); - glBindAttribLocationARB(m_program, c_attr_Binormal, "attr_Binormal"); - - glUniform1iARB(glGetUniformLocationARB(m_program, "u_diffusemap"), 0); - glUniform1iARB(glGetUniformLocationARB(m_program, "u_bumpmap"), 1); - glUniform1iARB(glGetUniformLocationARB(m_program, "u_specularmap"), 2); - glUniform1iARB(glGetUniformLocationARB(m_program, "u_attenuationmap_xy"), 3); - glUniform1iARB(glGetUniformLocationARB(m_program, "u_attenuationmap_z"), 4); - - u_view_origin = glGetUniformLocationARB(m_program, "u_view_origin"); - u_light_origin = glGetUniformLocationARB(m_program, "u_light_origin"); - u_light_color = glGetUniformLocationARB(m_program, "u_light_color"); - u_bump_scale = glGetUniformLocationARB(m_program, "u_bump_scale"); - u_specular_exponent = glGetUniformLocationARB(m_program, "u_specular_exponent"); - - glUseProgramObjectARB(0); - - GlobalOpenGL_debugAssertNoErrors(); - } - - void destroy() - { - glDeleteObjectARB(m_program); - m_program = 0; - } - - void enable() - { - glUseProgramObjectARB(m_program); - - glEnableVertexAttribArrayARB(c_attr_TexCoord0); - glEnableVertexAttribArrayARB(c_attr_Tangent); - glEnableVertexAttribArrayARB(c_attr_Binormal); - - GlobalOpenGL_debugAssertNoErrors(); - - debug_string("enable bump"); - g_bumpGLSLPass_enabled = true; - } - - void disable() - { - glUseProgramObjectARB(0); - - glDisableVertexAttribArrayARB(c_attr_TexCoord0); - glDisableVertexAttribArrayARB(c_attr_Tangent); - glDisableVertexAttribArrayARB(c_attr_Binormal); - - GlobalOpenGL_debugAssertNoErrors(); - - debug_string("disable bump"); - g_bumpGLSLPass_enabled = false; - } - - void setParameters(const Vector3 &viewer, const Matrix4 &localToWorld, const Vector3 &origin, const Vector3 &colour, - const Matrix4 &world2light) - { - Matrix4 world2local(localToWorld); - matrix4_affine_invert(world2local); - - Vector3 localLight(origin); - matrix4_transform_point(world2local, localLight); - - Vector3 localViewer(viewer); - matrix4_transform_point(world2local, localViewer); - - Matrix4 local2light(world2light); - matrix4_multiply_by_matrix4(local2light, localToWorld); // local->world->light - - glUniform3fARB(u_view_origin, localViewer.x(), localViewer.y(), localViewer.z()); - glUniform3fARB(u_light_origin, localLight.x(), localLight.y(), localLight.z()); - glUniform3fARB(u_light_color, colour.x(), colour.y(), colour.z()); - glUniform1fARB(u_bump_scale, 1.0); - glUniform1fARB(u_specular_exponent, 32.0); +GLhandleARB m_program; +qtexture_t* m_light_attenuation_xy; +qtexture_t* m_light_attenuation_z; +GLint u_view_origin; +GLint u_light_origin; +GLint u_light_color; +GLint u_bump_scale; +GLint u_specular_exponent; + +GLSLBumpProgram() : m_program( 0 ), m_light_attenuation_xy( 0 ), m_light_attenuation_z( 0 ){ +} + +void create(){ + // create program + m_program = glCreateProgramObjectARB(); + + // create shader + { + StringOutputStream filename( 256 ); + filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glsl"; + createShader( m_program, filename.c_str(), GL_VERTEX_SHADER_ARB ); + filename.clear(); + filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glsl"; + createShader( m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB ); + } + + GLSLProgram_link( m_program ); + GLSLProgram_validate( m_program ); - glActiveTexture(GL_TEXTURE3); - glClientActiveTexture(GL_TEXTURE3); + glUseProgramObjectARB( m_program ); - glMatrixMode(GL_TEXTURE); - glLoadMatrixf(reinterpret_cast( &local2light )); - glMatrixMode(GL_MODELVIEW); + glBindAttribLocationARB( m_program, c_attr_TexCoord0, "attr_TexCoord0" ); + glBindAttribLocationARB( m_program, c_attr_Tangent, "attr_Tangent" ); + glBindAttribLocationARB( m_program, c_attr_Binormal, "attr_Binormal" ); + + glUniform1iARB( glGetUniformLocationARB( m_program, "u_diffusemap" ), 0 ); + glUniform1iARB( glGetUniformLocationARB( m_program, "u_bumpmap" ), 1 ); + glUniform1iARB( glGetUniformLocationARB( m_program, "u_specularmap" ), 2 ); + glUniform1iARB( glGetUniformLocationARB( m_program, "u_attenuationmap_xy" ), 3 ); + glUniform1iARB( glGetUniformLocationARB( m_program, "u_attenuationmap_z" ), 4 ); + + u_view_origin = glGetUniformLocationARB( m_program, "u_view_origin" ); + u_light_origin = glGetUniformLocationARB( m_program, "u_light_origin" ); + u_light_color = glGetUniformLocationARB( m_program, "u_light_color" ); + u_bump_scale = glGetUniformLocationARB( m_program, "u_bump_scale" ); + u_specular_exponent = glGetUniformLocationARB( m_program, "u_specular_exponent" ); + + glUseProgramObjectARB( 0 ); + + GlobalOpenGL_debugAssertNoErrors(); +} + +void destroy(){ + glDeleteObjectARB( m_program ); + m_program = 0; +} + +void enable(){ + glUseProgramObjectARB( m_program ); + + glEnableVertexAttribArrayARB( c_attr_TexCoord0 ); + glEnableVertexAttribArrayARB( c_attr_Tangent ); + glEnableVertexAttribArrayARB( c_attr_Binormal ); + + GlobalOpenGL_debugAssertNoErrors(); + + debug_string( "enable bump" ); + g_bumpGLSLPass_enabled = true; +} + +void disable(){ + glUseProgramObjectARB( 0 ); + + glDisableVertexAttribArrayARB( c_attr_TexCoord0 ); + glDisableVertexAttribArrayARB( c_attr_Tangent ); + glDisableVertexAttribArrayARB( c_attr_Binormal ); + + GlobalOpenGL_debugAssertNoErrors(); + + debug_string( "disable bump" ); + g_bumpGLSLPass_enabled = false; +} + +void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){ + Matrix4 world2local( localToWorld ); + matrix4_affine_invert( world2local ); + + Vector3 localLight( origin ); + matrix4_transform_point( world2local, localLight ); + + Vector3 localViewer( viewer ); + matrix4_transform_point( world2local, localViewer ); + + Matrix4 local2light( world2light ); + matrix4_multiply_by_matrix4( local2light, localToWorld ); // local->world->light + + glUniform3fARB( u_view_origin, localViewer.x(), localViewer.y(), localViewer.z() ); + glUniform3fARB( u_light_origin, localLight.x(), localLight.y(), localLight.z() ); + glUniform3fARB( u_light_color, colour.x(), colour.y(), colour.z() ); + glUniform1fARB( u_bump_scale, 1.0 ); + glUniform1fARB( u_specular_exponent, 32.0 ); + + glActiveTexture( GL_TEXTURE3 ); + glClientActiveTexture( GL_TEXTURE3 ); + + glMatrixMode( GL_TEXTURE ); + glLoadMatrixf( reinterpret_cast( &local2light ) ); + glMatrixMode( GL_MODELVIEW ); - GlobalOpenGL_debugAssertNoErrors(); - } + GlobalOpenGL_debugAssertNoErrors(); +} }; GLSLBumpProgram g_bumpGLSL; -class GLSLDepthFillProgram : public GLProgram { +class GLSLDepthFillProgram : public GLProgram +{ public: - GLhandleARB m_program; - - void create() - { - // create program - m_program = glCreateProgramObjectARB(); - - // create shader - { - StringOutputStream filename(256); - filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glsl"; - createShader(m_program, filename.c_str(), GL_VERTEX_SHADER_ARB); - filename.clear(); - filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glsl"; - createShader(m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB); - } - - GLSLProgram_link(m_program); - GLSLProgram_validate(m_program); - - GlobalOpenGL_debugAssertNoErrors(); - } - - void destroy() - { - glDeleteObjectARB(m_program); - m_program = 0; - } - - void enable() - { - glUseProgramObjectARB(m_program); - GlobalOpenGL_debugAssertNoErrors(); - debug_string("enable depthfill"); - g_depthfillPass_enabled = true; - } - - void disable() - { - glUseProgramObjectARB(0); - GlobalOpenGL_debugAssertNoErrors(); - debug_string("disable depthfill"); - g_depthfillPass_enabled = false; - } - - void setParameters(const Vector3 &viewer, const Matrix4 &localToWorld, const Vector3 &origin, const Vector3 &colour, - const Matrix4 &world2light) - { - } +GLhandleARB m_program; + +void create(){ + // create program + m_program = glCreateProgramObjectARB(); + + // create shader + { + StringOutputStream filename( 256 ); + filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glsl"; + createShader( m_program, filename.c_str(), GL_VERTEX_SHADER_ARB ); + filename.clear(); + filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glsl"; + createShader( m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB ); + } + + GLSLProgram_link( m_program ); + GLSLProgram_validate( m_program ); + + GlobalOpenGL_debugAssertNoErrors(); +} + +void destroy(){ + glDeleteObjectARB( m_program ); + m_program = 0; +} + +void enable(){ + glUseProgramObjectARB( m_program ); + GlobalOpenGL_debugAssertNoErrors(); + debug_string( "enable depthfill" ); + g_depthfillPass_enabled = true; +} + +void disable(){ + glUseProgramObjectARB( 0 ); + GlobalOpenGL_debugAssertNoErrors(); + debug_string( "disable depthfill" ); + g_depthfillPass_enabled = false; +} +void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){ +} }; GLSLDepthFillProgram g_depthFillGLSL; @@ -397,194 +373,182 @@ GLSLDepthFillProgram g_depthFillGLSL; // ARB path -void createProgram(const char *filename, GLenum type) -{ - std::size_t size = file_size(filename); - FileInputStream file(filename); - ASSERT_MESSAGE(!file.failed(), "failed to open " << makeQuoted(filename)); - Array buffer(size); - size = file.read(reinterpret_cast( buffer.data()), size); +void createProgram( const char* filename, GLenum type ){ + std::size_t size = file_size( filename ); + FileInputStream file( filename ); + ASSERT_MESSAGE( !file.failed(), "failed to open " << makeQuoted( filename ) ); + Array buffer( size ); + size = file.read( reinterpret_cast( buffer.data() ), size ); - glProgramStringARB(type, GL_PROGRAM_FORMAT_ASCII_ARB, GLsizei(size), buffer.data()); + glProgramStringARB( type, GL_PROGRAM_FORMAT_ASCII_ARB, GLsizei( size ), buffer.data() ); - if (GL_INVALID_OPERATION == glGetError()) { - GLint errPos; - glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos); - const GLubyte *errString = glGetString(GL_PROGRAM_ERROR_STRING_ARB); + if ( GL_INVALID_OPERATION == glGetError() ) { + GLint errPos; + glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos ); + const GLubyte* errString = glGetString( GL_PROGRAM_ERROR_STRING_ARB ); - globalErrorStream() << reinterpret_cast( filename ) << ":" << errPos << "\n" - << reinterpret_cast( errString ); + globalErrorStream() << reinterpret_cast( filename ) << ":" << errPos << "\n" << reinterpret_cast( errString ); - ERROR_MESSAGE("error in gl program"); - } + ERROR_MESSAGE( "error in gl program" ); + } } -class ARBBumpProgram : public GLProgram { +class ARBBumpProgram : public GLProgram +{ public: - GLuint m_vertex_program; - GLuint m_fragment_program; +GLuint m_vertex_program; +GLuint m_fragment_program; - void create() - { - glEnable(GL_VERTEX_PROGRAM_ARB); - glEnable(GL_FRAGMENT_PROGRAM_ARB); +void create(){ + glEnable( GL_VERTEX_PROGRAM_ARB ); + glEnable( GL_FRAGMENT_PROGRAM_ARB ); - { - glGenProgramsARB(1, &m_vertex_program); - glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program); - StringOutputStream filename(256); - filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glp"; - createProgram(filename.c_str(), GL_VERTEX_PROGRAM_ARB); + { + glGenProgramsARB( 1, &m_vertex_program ); + glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program ); + StringOutputStream filename( 256 ); + filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glp"; + createProgram( filename.c_str(), GL_VERTEX_PROGRAM_ARB ); - glGenProgramsARB(1, &m_fragment_program); - glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program); - filename.clear(); - filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glp"; - createProgram(filename.c_str(), GL_FRAGMENT_PROGRAM_ARB); - } + glGenProgramsARB( 1, &m_fragment_program ); + glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program ); + filename.clear(); + filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glp"; + createProgram( filename.c_str(), GL_FRAGMENT_PROGRAM_ARB ); + } - glDisable(GL_VERTEX_PROGRAM_ARB); - glDisable(GL_FRAGMENT_PROGRAM_ARB); + glDisable( GL_VERTEX_PROGRAM_ARB ); + glDisable( GL_FRAGMENT_PROGRAM_ARB ); - GlobalOpenGL_debugAssertNoErrors(); - } + GlobalOpenGL_debugAssertNoErrors(); +} - void destroy() - { - glDeleteProgramsARB(1, &m_vertex_program); - glDeleteProgramsARB(1, &m_fragment_program); - GlobalOpenGL_debugAssertNoErrors(); - } +void destroy(){ + glDeleteProgramsARB( 1, &m_vertex_program ); + glDeleteProgramsARB( 1, &m_fragment_program ); + GlobalOpenGL_debugAssertNoErrors(); +} - void enable() - { - glEnable(GL_VERTEX_PROGRAM_ARB); - glEnable(GL_FRAGMENT_PROGRAM_ARB); - glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program); - glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program); +void enable(){ + glEnable( GL_VERTEX_PROGRAM_ARB ); + glEnable( GL_FRAGMENT_PROGRAM_ARB ); + glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program ); + glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program ); - glEnableVertexAttribArrayARB(8); - glEnableVertexAttribArrayARB(9); - glEnableVertexAttribArrayARB(10); - glEnableVertexAttribArrayARB(11); + glEnableVertexAttribArrayARB( 8 ); + glEnableVertexAttribArrayARB( 9 ); + glEnableVertexAttribArrayARB( 10 ); + glEnableVertexAttribArrayARB( 11 ); - GlobalOpenGL_debugAssertNoErrors(); - } + GlobalOpenGL_debugAssertNoErrors(); +} - void disable() - { - glDisable(GL_VERTEX_PROGRAM_ARB); - glDisable(GL_FRAGMENT_PROGRAM_ARB); +void disable(){ + glDisable( GL_VERTEX_PROGRAM_ARB ); + glDisable( GL_FRAGMENT_PROGRAM_ARB ); - glDisableVertexAttribArrayARB(8); - glDisableVertexAttribArrayARB(9); - glDisableVertexAttribArrayARB(10); - glDisableVertexAttribArrayARB(11); + glDisableVertexAttribArrayARB( 8 ); + glDisableVertexAttribArrayARB( 9 ); + glDisableVertexAttribArrayARB( 10 ); + glDisableVertexAttribArrayARB( 11 ); - GlobalOpenGL_debugAssertNoErrors(); - } + GlobalOpenGL_debugAssertNoErrors(); +} - void setParameters(const Vector3 &viewer, const Matrix4 &localToWorld, const Vector3 &origin, const Vector3 &colour, - const Matrix4 &world2light) - { - Matrix4 world2local(localToWorld); - matrix4_affine_invert(world2local); +void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){ + Matrix4 world2local( localToWorld ); + matrix4_affine_invert( world2local ); - Vector3 localLight(origin); - matrix4_transform_point(world2local, localLight); + Vector3 localLight( origin ); + matrix4_transform_point( world2local, localLight ); - Vector3 localViewer(viewer); - matrix4_transform_point(world2local, localViewer); + Vector3 localViewer( viewer ); + matrix4_transform_point( world2local, localViewer ); - Matrix4 local2light(world2light); - matrix4_multiply_by_matrix4(local2light, localToWorld); // local->world->light + Matrix4 local2light( world2light ); + matrix4_multiply_by_matrix4( local2light, localToWorld ); // local->world->light - // view origin - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 4, localViewer.x(), localViewer.y(), localViewer.z(), 0); + // view origin + glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 4, localViewer.x(), localViewer.y(), localViewer.z(), 0 ); - // light origin - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, localLight.x(), localLight.y(), localLight.z(), 1); + // light origin + glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 2, localLight.x(), localLight.y(), localLight.z(), 1 ); - // light colour - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 3, colour.x(), colour.y(), colour.z(), 0); + // light colour + glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 3, colour.x(), colour.y(), colour.z(), 0 ); - // bump scale - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 1, 1, 0, 0, 0); + // bump scale + glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 1, 1, 0, 0, 0 ); - // specular exponent - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 5, 32, 0, 0, 0); + // specular exponent + glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 5, 32, 0, 0, 0 ); - glActiveTexture(GL_TEXTURE3); - glClientActiveTexture(GL_TEXTURE3); + glActiveTexture( GL_TEXTURE3 ); + glClientActiveTexture( GL_TEXTURE3 ); - glMatrixMode(GL_TEXTURE); - glLoadMatrixf(reinterpret_cast( &local2light )); - glMatrixMode(GL_MODELVIEW); + glMatrixMode( GL_TEXTURE ); + glLoadMatrixf( reinterpret_cast( &local2light ) ); + glMatrixMode( GL_MODELVIEW ); - GlobalOpenGL_debugAssertNoErrors(); - } + GlobalOpenGL_debugAssertNoErrors(); +} }; -class ARBDepthFillProgram : public GLProgram { +class ARBDepthFillProgram : public GLProgram +{ public: - GLuint m_vertex_program; - GLuint m_fragment_program; - - void create() - { - glEnable(GL_VERTEX_PROGRAM_ARB); - glEnable(GL_FRAGMENT_PROGRAM_ARB); - - { - glGenProgramsARB(1, &m_vertex_program); - glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program); - StringOutputStream filename(256); - filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glp"; - createProgram(filename.c_str(), GL_VERTEX_PROGRAM_ARB); - - glGenProgramsARB(1, &m_fragment_program); - glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program); - filename.clear(); - filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glp"; - createProgram(filename.c_str(), GL_FRAGMENT_PROGRAM_ARB); - } - - glDisable(GL_VERTEX_PROGRAM_ARB); - glDisable(GL_FRAGMENT_PROGRAM_ARB); - - GlobalOpenGL_debugAssertNoErrors(); - } - - void destroy() - { - glDeleteProgramsARB(1, &m_vertex_program); - glDeleteProgramsARB(1, &m_fragment_program); - GlobalOpenGL_debugAssertNoErrors(); - } - - void enable() - { - glEnable(GL_VERTEX_PROGRAM_ARB); - glEnable(GL_FRAGMENT_PROGRAM_ARB); - glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_vertex_program); - glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_fragment_program); - - GlobalOpenGL_debugAssertNoErrors(); - } - - void disable() - { - glDisable(GL_VERTEX_PROGRAM_ARB); - glDisable(GL_FRAGMENT_PROGRAM_ARB); - - GlobalOpenGL_debugAssertNoErrors(); - } - - void setParameters(const Vector3 &viewer, const Matrix4 &localToWorld, const Vector3 &origin, const Vector3 &colour, - const Matrix4 &world2light) - { - } +GLuint m_vertex_program; +GLuint m_fragment_program; + +void create(){ + glEnable( GL_VERTEX_PROGRAM_ARB ); + glEnable( GL_FRAGMENT_PROGRAM_ARB ); + + { + glGenProgramsARB( 1, &m_vertex_program ); + glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program ); + StringOutputStream filename( 256 ); + filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glp"; + createProgram( filename.c_str(), GL_VERTEX_PROGRAM_ARB ); + + glGenProgramsARB( 1, &m_fragment_program ); + glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program ); + filename.clear(); + filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glp"; + createProgram( filename.c_str(), GL_FRAGMENT_PROGRAM_ARB ); + } + + glDisable( GL_VERTEX_PROGRAM_ARB ); + glDisable( GL_FRAGMENT_PROGRAM_ARB ); + + GlobalOpenGL_debugAssertNoErrors(); +} + +void destroy(){ + glDeleteProgramsARB( 1, &m_vertex_program ); + glDeleteProgramsARB( 1, &m_fragment_program ); + GlobalOpenGL_debugAssertNoErrors(); +} + +void enable(){ + glEnable( GL_VERTEX_PROGRAM_ARB ); + glEnable( GL_FRAGMENT_PROGRAM_ARB ); + glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program ); + glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program ); + + GlobalOpenGL_debugAssertNoErrors(); +} + +void disable(){ + glDisable( GL_VERTEX_PROGRAM_ARB ); + glDisable( GL_FRAGMENT_PROGRAM_ARB ); + + GlobalOpenGL_debugAssertNoErrors(); +} + +void setParameters( const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light ){ +} }; ARBBumpProgram g_bumpARB; @@ -592,7 +556,7 @@ ARBDepthFillProgram g_depthFillARB; #if 0 - // NV20 path (unfinished) +// NV20 path (unfinished) void createProgram( GLint program, const char* filename, GLenum type ){ std::size_t size = file_size( filename ); @@ -808,213 +772,205 @@ bool g_normalArray_enabled = false; bool g_texcoordArray_enabled = false; bool g_colorArray_enabled = false; -inline bool OpenGLState_less(const OpenGLState &self, const OpenGLState &other) -{ - //! Sort by sort-order override. - if (self.m_sort != other.m_sort) { - return self.m_sort < other.m_sort; - } - //! Sort by texture handle. - if (self.m_texture != other.m_texture) { - return self.m_texture < other.m_texture; - } - if (self.m_texture1 != other.m_texture1) { - return self.m_texture1 < other.m_texture1; - } - if (self.m_texture2 != other.m_texture2) { - return self.m_texture2 < other.m_texture2; - } - if (self.m_texture3 != other.m_texture3) { - return self.m_texture3 < other.m_texture3; - } - if (self.m_texture4 != other.m_texture4) { - return self.m_texture4 < other.m_texture4; - } - if (self.m_texture5 != other.m_texture5) { - return self.m_texture5 < other.m_texture5; - } - if (self.m_texture6 != other.m_texture6) { - return self.m_texture6 < other.m_texture6; - } - if (self.m_texture7 != other.m_texture7) { - return self.m_texture7 < other.m_texture7; - } - //! Sort by state bit-vector. - if (self.m_state != other.m_state) { - return self.m_state < other.m_state; - } - //! Comparing address makes sure states are never equal. - return &self < &other; -} - -void OpenGLState_constructDefault(OpenGLState &state) -{ - state.m_state = RENDER_DEFAULT; +inline bool OpenGLState_less( const OpenGLState& self, const OpenGLState& other ){ + //! Sort by sort-order override. + if ( self.m_sort != other.m_sort ) { + return self.m_sort < other.m_sort; + } + //! Sort by texture handle. + if ( self.m_texture != other.m_texture ) { + return self.m_texture < other.m_texture; + } + if ( self.m_texture1 != other.m_texture1 ) { + return self.m_texture1 < other.m_texture1; + } + if ( self.m_texture2 != other.m_texture2 ) { + return self.m_texture2 < other.m_texture2; + } + if ( self.m_texture3 != other.m_texture3 ) { + return self.m_texture3 < other.m_texture3; + } + if ( self.m_texture4 != other.m_texture4 ) { + return self.m_texture4 < other.m_texture4; + } + if ( self.m_texture5 != other.m_texture5 ) { + return self.m_texture5 < other.m_texture5; + } + if ( self.m_texture6 != other.m_texture6 ) { + return self.m_texture6 < other.m_texture6; + } + if ( self.m_texture7 != other.m_texture7 ) { + return self.m_texture7 < other.m_texture7; + } + //! Sort by state bit-vector. + if ( self.m_state != other.m_state ) { + return self.m_state < other.m_state; + } + //! Comparing address makes sure states are never equal. + return &self < &other; +} - state.m_texture = 0; - state.m_texture1 = 0; - state.m_texture2 = 0; - state.m_texture3 = 0; - state.m_texture4 = 0; - state.m_texture5 = 0; - state.m_texture6 = 0; - state.m_texture7 = 0; +void OpenGLState_constructDefault( OpenGLState& state ){ + state.m_state = RENDER_DEFAULT; - state.m_colour[0] = 1; - state.m_colour[1] = 1; - state.m_colour[2] = 1; - state.m_colour[3] = 1; + state.m_texture = 0; + state.m_texture1 = 0; + state.m_texture2 = 0; + state.m_texture3 = 0; + state.m_texture4 = 0; + state.m_texture5 = 0; + state.m_texture6 = 0; + state.m_texture7 = 0; - state.m_depthfunc = GL_LESS; + state.m_colour[0] = 1; + state.m_colour[1] = 1; + state.m_colour[2] = 1; + state.m_colour[3] = 1; - state.m_blend_src = GL_SRC_ALPHA; - state.m_blend_dst = GL_ONE_MINUS_SRC_ALPHA; + state.m_depthfunc = GL_LESS; - state.m_alphafunc = GL_ALWAYS; - state.m_alpharef = 0; + state.m_blend_src = GL_SRC_ALPHA; + state.m_blend_dst = GL_ONE_MINUS_SRC_ALPHA; - state.m_linewidth = 1; - state.m_pointsize = 1; + state.m_alphafunc = GL_ALWAYS; + state.m_alpharef = 0; - state.m_linestipple_factor = 1; - state.m_linestipple_pattern = 0xaaaa; + state.m_linewidth = 1; + state.m_pointsize = 1; - state.m_fog = OpenGLFogState(); + state.m_linestipple_factor = 1; + state.m_linestipple_pattern = 0xaaaa; + + state.m_fog = OpenGLFogState(); } /// \brief A container of Renderable references. /// May contain the same Renderable multiple times, with different transforms. -class OpenGLStateBucket { +class OpenGLStateBucket +{ public: - struct RenderTransform { - const Matrix4 *m_transform; - const OpenGLRenderable *m_renderable; - const RendererLight *m_light; +struct RenderTransform +{ + const Matrix4* m_transform; + const OpenGLRenderable *m_renderable; + const RendererLight* m_light; - RenderTransform(const OpenGLRenderable &renderable, const Matrix4 &transform, const RendererLight *light) - : m_transform(&transform), m_renderable(&renderable), m_light(light) - { - } - }; + RenderTransform( const OpenGLRenderable& renderable, const Matrix4& transform, const RendererLight* light ) + : m_transform( &transform ), m_renderable( &renderable ), m_light( light ){ + } +}; - typedef std::vector Renderables; +typedef std::vector Renderables; private: - OpenGLState m_state; - Renderables m_renderables; +OpenGLState m_state; +Renderables m_renderables; public: - OpenGLStateBucket() - { - } +OpenGLStateBucket(){ +} - void addRenderable(const OpenGLRenderable &renderable, const Matrix4 &modelview, const RendererLight *light = 0) - { - m_renderables.push_back(RenderTransform(renderable, modelview, light)); - } +void addRenderable( const OpenGLRenderable& renderable, const Matrix4& modelview, const RendererLight* light = 0 ){ + m_renderables.push_back( RenderTransform( renderable, modelview, light ) ); +} - OpenGLState &state() - { - return m_state; - } +OpenGLState& state(){ + return m_state; +} - void render(OpenGLState ¤t, unsigned int globalstate, const Vector3 &viewer); +void render( OpenGLState& current, unsigned int globalstate, const Vector3& viewer ); }; #define LIGHT_SHADER_DEBUG 0 #if LIGHT_SHADER_DEBUG - typedef std::vector LightDebugShaders; +typedef std::vector LightDebugShaders; LightDebugShaders g_lightDebugShaders; #endif -class OpenGLStateLess { +class OpenGLStateLess +{ public: - bool operator()(const OpenGLState &self, const OpenGLState &other) const - { - return OpenGLState_less(self, other); - } +bool operator()( const OpenGLState& self, const OpenGLState& other ) const { + return OpenGLState_less( self, other ); +} }; typedef ConstReference OpenGLStateReference; -typedef std::map OpenGLStates; +typedef std::map OpenGLStates; OpenGLStates g_state_sorted; -class OpenGLStateBucketAdd { - OpenGLStateBucket &m_bucket; - const OpenGLRenderable &m_renderable; - const Matrix4 &m_modelview; +class OpenGLStateBucketAdd +{ +OpenGLStateBucket& m_bucket; +const OpenGLRenderable& m_renderable; +const Matrix4& m_modelview; public: - using func = void(const RendererLight &); +using func = void(const RendererLight&); - OpenGLStateBucketAdd(OpenGLStateBucket &bucket, const OpenGLRenderable &renderable, const Matrix4 &modelview) : - m_bucket(bucket), m_renderable(renderable), m_modelview(modelview) - { - } +OpenGLStateBucketAdd( OpenGLStateBucket& bucket, const OpenGLRenderable& renderable, const Matrix4& modelview ) : + m_bucket( bucket ), m_renderable( renderable ), m_modelview( modelview ){ +} - void operator()(const RendererLight &light) - { - m_bucket.addRenderable(m_renderable, m_modelview, &light); - } +void operator()( const RendererLight& light ){ + m_bucket.addRenderable( m_renderable, m_modelview, &light ); +} }; -class CountLights { - std::size_t m_count; +class CountLights +{ +std::size_t m_count; public: - using func = void(RendererLight &); +using func = void(RendererLight&); - CountLights() : m_count(0) - { - } +CountLights() : m_count( 0 ){ +} - void operator()(const RendererLight &light) - { - ++m_count; - } +void operator()( const RendererLight& light ){ + ++m_count; +} - std::size_t count() const - { - return m_count; - } +std::size_t count() const { + return m_count; +} }; -class OpenGLShader : public Shader { - typedef std::list Passes; - Passes m_passes; - IShader *m_shader; - std::size_t m_used; - ModuleObservers m_observers; +class OpenGLShader : public Shader +{ +typedef std::list Passes; +Passes m_passes; +IShader* m_shader; +std::size_t m_used; +ModuleObservers m_observers; public: - OpenGLShader() : m_shader(0), m_used(0) - { - } - - ~OpenGLShader() - { - } - - void construct(const char *name); - - void destroy() - { - if (m_shader) { - m_shader->DecRef(); - } - m_shader = 0; - - for (Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i) { - delete *i; - } - m_passes.clear(); - } - - void addRenderable(const OpenGLRenderable &renderable, const Matrix4 &modelview, const LightList *lights) - { - for (Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i) { +OpenGLShader() : m_shader( 0 ), m_used( 0 ){ +} + +~OpenGLShader(){ +} + +void construct( const char* name ); + +void destroy(){ + if ( m_shader ) { + m_shader->DecRef(); + } + m_shader = 0; + + for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i ) + { + delete *i; + } + m_passes.clear(); +} + +void addRenderable( const OpenGLRenderable& renderable, const Matrix4& modelview, const LightList* lights ){ + for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i ) + { #if LIGHT_SHADER_DEBUG - if ( ( ( *i )->state().m_state & RENDER_BUMP ) != 0 ) { + if ( ( ( *i )->state().m_state & RENDER_BUMP ) != 0 ) { if ( lights != 0 ) { CountLights counter; lights->forEachLight( makeCallback1( counter ) ); @@ -1027,149 +983,140 @@ public: } else #else - if (((*i)->state().m_state & RENDER_BUMP) != 0) { - if (lights != 0) { - OpenGLStateBucketAdd add(*(*i), renderable, modelview); - lights->forEachLight(makeCallback(add)); - } - } else + if ( ( ( *i )->state().m_state & RENDER_BUMP ) != 0 ) { + if ( lights != 0 ) { + OpenGLStateBucketAdd add( *( *i ), renderable, modelview ); + lights->forEachLight(makeCallback( add ) ); + } + } + else #endif - { - (*i)->addRenderable(renderable, modelview); - } - } - } - - void incrementUsed() - { - if (++m_used == 1 && m_shader != 0) { - m_shader->SetInUse(true); - } - } - - void decrementUsed() - { - if (--m_used == 0 && m_shader != 0) { - m_shader->SetInUse(false); - } - } - - bool realised() const - { - return m_shader != 0; - } - - void attach(ModuleObserver &observer) - { - if (realised()) { - observer.realise(); - } - m_observers.attach(observer); - } - - void detach(ModuleObserver &observer) - { - if (realised()) { - observer.unrealise(); - } - m_observers.detach(observer); - } - - void realise(const CopiedString &name) - { - construct(name.c_str()); - - if (m_used != 0 && m_shader != 0) { - m_shader->SetInUse(true); - } - - for (Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i) { - g_state_sorted.insert(OpenGLStates::value_type(OpenGLStateReference((*i)->state()), *i)); - } - - m_observers.realise(); - } - - void unrealise() - { - m_observers.unrealise(); - - for (Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i) { - g_state_sorted.erase(OpenGLStateReference((*i)->state())); - } - - destroy(); - } - - qtexture_t &getTexture() const - { - ASSERT_NOTNULL(m_shader); - return *m_shader->getTexture(); - } - - unsigned int getFlags() const - { - ASSERT_NOTNULL(m_shader); - return m_shader->getFlags(); - } - - IShader &getShader() const - { - ASSERT_NOTNULL(m_shader); - return *m_shader; - } - - OpenGLState &appendDefaultPass() - { - m_passes.push_back(new OpenGLStateBucket); - OpenGLState &state = m_passes.back()->state(); - OpenGLState_constructDefault(state); - return state; - } + { + ( *i )->addRenderable( renderable, modelview ); + } + } +} + +void incrementUsed(){ + if ( ++m_used == 1 && m_shader != 0 ) { + m_shader->SetInUse( true ); + } +} + +void decrementUsed(){ + if ( --m_used == 0 && m_shader != 0 ) { + m_shader->SetInUse( false ); + } +} + +bool realised() const { + return m_shader != 0; +} + +void attach( ModuleObserver& observer ){ + if ( realised() ) { + observer.realise(); + } + m_observers.attach( observer ); +} + +void detach( ModuleObserver& observer ){ + if ( realised() ) { + observer.unrealise(); + } + m_observers.detach( observer ); +} + +void realise( const CopiedString& name ){ + construct( name.c_str() ); + + if ( m_used != 0 && m_shader != 0 ) { + m_shader->SetInUse( true ); + } + + for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i ) + { + g_state_sorted.insert( OpenGLStates::value_type( OpenGLStateReference( ( *i )->state() ), *i ) ); + } + + m_observers.realise(); +} + +void unrealise(){ + m_observers.unrealise(); + + for ( Passes::iterator i = m_passes.begin(); i != m_passes.end(); ++i ) + { + g_state_sorted.erase( OpenGLStateReference( ( *i )->state() ) ); + } + + destroy(); +} + +qtexture_t& getTexture() const { + ASSERT_NOTNULL( m_shader ); + return *m_shader->getTexture(); +} + +unsigned int getFlags() const { + ASSERT_NOTNULL( m_shader ); + return m_shader->getFlags(); +} + +IShader& getShader() const { + ASSERT_NOTNULL( m_shader ); + return *m_shader; +} + +OpenGLState& appendDefaultPass(){ + m_passes.push_back( new OpenGLStateBucket ); + OpenGLState& state = m_passes.back()->state(); + OpenGLState_constructDefault( state ); + return state; +} }; -inline bool lightEnabled(const RendererLight &light, const LightCullable &cullable) -{ - return cullable.testLight(light); +inline bool lightEnabled( const RendererLight& light, const LightCullable& cullable ){ + return cullable.testLight( light ); } -typedef std::set RendererLights; +typedef std::set RendererLights; #define DEBUG_LIGHT_SYNC 0 -class LinearLightList : public LightList { - LightCullable &m_cullable; - RendererLights &m_allLights; - Callback m_evaluateChanged; +class LinearLightList : public LightList +{ +LightCullable& m_cullable; +RendererLights& m_allLights; +Callback m_evaluateChanged; - typedef std::list Lights; - mutable Lights m_lights; - mutable bool m_lightsChanged; +typedef std::list Lights; +mutable Lights m_lights; +mutable bool m_lightsChanged; public: - LinearLightList(LightCullable &cullable, RendererLights &lights, const Callback &evaluateChanged) : - m_cullable(cullable), m_allLights(lights), m_evaluateChanged(evaluateChanged) - { - m_lightsChanged = true; - } - - void evaluateLights() const - { - m_evaluateChanged(); - if (m_lightsChanged) { - m_lightsChanged = false; - - m_lights.clear(); - m_cullable.clearLights(); - for (RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i) { - if (lightEnabled(*(*i), m_cullable)) { - m_lights.push_back(*i); - m_cullable.insertLight(*(*i)); - } - } - } -#if (DEBUG_LIGHT_SYNC) - else +LinearLightList( LightCullable& cullable, RendererLights& lights, const Callback& evaluateChanged ) : + m_cullable( cullable ), m_allLights( lights ), m_evaluateChanged( evaluateChanged ){ + m_lightsChanged = true; +} + +void evaluateLights() const { + m_evaluateChanged(); + if ( m_lightsChanged ) { + m_lightsChanged = false; + + m_lights.clear(); + m_cullable.clearLights(); + for ( RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i ) + { + if ( lightEnabled( *( *i ), m_cullable ) ) { + m_lights.push_back( *i ); + m_cullable.insertLight( *( *i ) ); + } + } + } +#if ( DEBUG_LIGHT_SYNC ) + else { Lights lights; for ( RendererLights::const_iterator i = m_allLights.begin(); i != m_allLights.end(); ++i ) @@ -1185,459 +1132,434 @@ public: ); } #endif - } +} - void forEachLight(const RendererLightCallback &callback) const - { - evaluateLights(); +void forEachLight( const RendererLightCallback& callback ) const { + evaluateLights(); - for (Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i) { - callback(*(*i)); - } - } + for ( Lights::const_iterator i = m_lights.begin(); i != m_lights.end(); ++i ) + { + callback( *( *i ) ); + } +} - void lightsChanged() const - { - m_lightsChanged = true; - } +void lightsChanged() const { + m_lightsChanged = true; +} }; -inline void setFogState(const OpenGLFogState &state) -{ - glFogi(GL_FOG_MODE, state.mode); - glFogf(GL_FOG_DENSITY, state.density); - glFogf(GL_FOG_START, state.start); - glFogf(GL_FOG_END, state.end); - glFogi(GL_FOG_INDEX, state.index); - glFogfv(GL_FOG_COLOR, vector4_to_array(state.colour)); +inline void setFogState( const OpenGLFogState& state ){ + glFogi( GL_FOG_MODE, state.mode ); + glFogf( GL_FOG_DENSITY, state.density ); + glFogf( GL_FOG_START, state.start ); + glFogf( GL_FOG_END, state.end ); + glFogi( GL_FOG_INDEX, state.index ); + glFogfv( GL_FOG_COLOR, vector4_to_array( state.colour ) ); } #define DEBUG_SHADERS 0 -class OpenGLShaderCache : public ShaderCache, public TexturesCacheObserver, public ModuleObserver { - class CreateOpenGLShader { - OpenGLShaderCache *m_cache; - public: - explicit CreateOpenGLShader(OpenGLShaderCache *cache = 0) - : m_cache(cache) - { - } - - OpenGLShader *construct(const CopiedString &name) - { - OpenGLShader *shader = new OpenGLShader; - if (m_cache->realised()) { - shader->realise(name); - } - return shader; - } - - void destroy(OpenGLShader *shader) - { - if (m_cache->realised()) { - shader->unrealise(); - } - delete shader; - } - }; - - typedef HashedCache, CreateOpenGLShader> Shaders; - Shaders m_shaders; - std::size_t m_unrealised; - - bool m_lightingEnabled; - bool m_lightingSupported; - bool m_useShaderLanguage; - +class OpenGLShaderCache : public ShaderCache, public TexturesCacheObserver, public ModuleObserver +{ +class CreateOpenGLShader +{ +OpenGLShaderCache* m_cache; public: - OpenGLShaderCache() - : m_shaders(CreateOpenGLShader(this)), - m_unrealised( - 3), // wait until shaders, gl-context and textures are realised before creating any render-states - m_lightingEnabled(true), - m_lightingSupported(false), - m_useShaderLanguage(false), - m_lightsChanged(true), - m_traverseRenderablesMutex(false) - { - } - - ~OpenGLShaderCache() - { - for (Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) { - globalOutputStream() << "leaked shader: " << makeQuoted((*i).key.c_str()) << "\n"; - } - } - - Shader *capture(const char *name) - { - ASSERT_MESSAGE(name[0] == '$' - || *name == '[' - || *name == '<' - || *name == '(' - || strchr(name, '\\') == 0, "shader name contains invalid characters: \"" << name << "\""); +explicit CreateOpenGLShader( OpenGLShaderCache* cache = 0 ) + : m_cache( cache ){ +} + +OpenGLShader* construct( const CopiedString& name ){ + OpenGLShader* shader = new OpenGLShader; + if ( m_cache->realised() ) { + shader->realise( name ); + } + return shader; +} + +void destroy( OpenGLShader* shader ){ + if ( m_cache->realised() ) { + shader->unrealise(); + } + delete shader; +} +}; + +typedef HashedCache, CreateOpenGLShader> Shaders; +Shaders m_shaders; +std::size_t m_unrealised; + +bool m_lightingEnabled; +bool m_lightingSupported; +bool m_useShaderLanguage; + +public: +OpenGLShaderCache() + : m_shaders( CreateOpenGLShader( this ) ), + m_unrealised( 3 ), // wait until shaders, gl-context and textures are realised before creating any render-states + m_lightingEnabled( true ), + m_lightingSupported( false ), + m_useShaderLanguage( false ), + m_lightsChanged( true ), + m_traverseRenderablesMutex( false ){ +} + +~OpenGLShaderCache(){ + for ( Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i ) + { + globalOutputStream() << "leaked shader: " << makeQuoted( ( *i ).key.c_str() ) << "\n"; + } +} + +Shader* capture( const char* name ){ + ASSERT_MESSAGE( name[0] == '$' + || *name == '[' + || *name == '<' + || *name == '(' + || strchr( name, '\\' ) == 0, "shader name contains invalid characters: \"" << name << "\"" ); #if DEBUG_SHADERS - globalOutputStream() << "shaders capture: " << makeQuoted( name ) << '\n'; + globalOutputStream() << "shaders capture: " << makeQuoted( name ) << '\n'; #endif - return m_shaders.capture(name).get(); - } + return m_shaders.capture( name ).get(); +} - void release(const char *name) - { +void release( const char *name ){ #if DEBUG_SHADERS - globalOutputStream() << "shaders release: " << makeQuoted( name ) << '\n'; -#endif - m_shaders.release(name); - } - - void - render(RenderStateFlags globalstate, const Matrix4 &modelview, const Matrix4 &projection, const Vector3 &viewer) - { - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(reinterpret_cast( &projection )); -#if 0 - //qglGetFloatv(GL_PROJECTION_MATRIX, reinterpret_cast(&projection)); + globalOutputStream() << "shaders release: " << makeQuoted( name ) << '\n'; #endif + m_shaders.release( name ); +} +void render( RenderStateFlags globalstate, const Matrix4& modelview, const Matrix4& projection, const Vector3& viewer ){ + glMatrixMode( GL_PROJECTION ); + glLoadMatrixf( reinterpret_cast( &projection ) ); + #if 0 + //qglGetFloatv(GL_PROJECTION_MATRIX, reinterpret_cast(&projection)); + #endif - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(reinterpret_cast( &modelview )); -#if 0 - //qglGetFloatv(GL_MODELVIEW_MATRIX, reinterpret_cast(&modelview)); -#endif + glMatrixMode( GL_MODELVIEW ); + glLoadMatrixf( reinterpret_cast( &modelview ) ); + #if 0 + //qglGetFloatv(GL_MODELVIEW_MATRIX, reinterpret_cast(&modelview)); + #endif + + ASSERT_MESSAGE( realised(), "render states are not realised" ); + + // global settings that are not set in renderstates + glFrontFace( GL_CW ); + glCullFace( GL_BACK ); + glPolygonOffset( -1, 1 ); + { + const GLubyte pattern[132] = { + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, + 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55 + }; + glPolygonStipple( pattern ); + } + glEnableClientState( GL_VERTEX_ARRAY ); + g_vertexArray_enabled = true; + glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); + + if ( GlobalOpenGL().GL_1_3() ) { + glActiveTexture( GL_TEXTURE0 ); + glClientActiveTexture( GL_TEXTURE0 ); + } + + if ( GlobalOpenGL().ARB_shader_objects() ) { + glUseProgramObjectARB( 0 ); + glDisableVertexAttribArrayARB( c_attr_TexCoord0 ); + glDisableVertexAttribArrayARB( c_attr_Tangent ); + glDisableVertexAttribArrayARB( c_attr_Binormal ); + } + + if ( globalstate & RENDER_TEXTURE ) { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + } + + OpenGLState current; + OpenGLState_constructDefault( current ); + current.m_sort = OpenGLState::eSortFirst; + + // default renderstate settings + glLineStipple( current.m_linestipple_factor, current.m_linestipple_pattern ); + glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); + glDisable( GL_LIGHTING ); + glDisable( GL_TEXTURE_2D ); + glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + g_texcoordArray_enabled = false; + glDisableClientState( GL_COLOR_ARRAY ); + g_colorArray_enabled = false; + glDisableClientState( GL_NORMAL_ARRAY ); + g_normalArray_enabled = false; + glDisable( GL_BLEND ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glDisable( GL_CULL_FACE ); + glShadeModel( GL_FLAT ); + glDisable( GL_DEPTH_TEST ); + glDepthMask( GL_FALSE ); + glDisable( GL_ALPHA_TEST ); + glDisable( GL_LINE_STIPPLE ); + glDisable( GL_POLYGON_STIPPLE ); + glDisable( GL_POLYGON_OFFSET_LINE ); + + glBindTexture( GL_TEXTURE_2D, 0 ); + glColor4f( 1,1,1,1 ); + glDepthFunc( GL_LESS ); + glAlphaFunc( GL_ALWAYS, 0 ); + glLineWidth( 1 ); + glPointSize( 1 ); + + glHint( GL_FOG_HINT, GL_NICEST ); + glDisable( GL_FOG ); + setFogState( OpenGLFogState() ); + + GlobalOpenGL_debugAssertNoErrors(); + + debug_string( "begin rendering" ); + for ( OpenGLStates::iterator i = g_state_sorted.begin(); i != g_state_sorted.end(); ++i ) + { + ( *i ).second->render( current, globalstate, viewer ); + } + debug_string( "end rendering" ); +} - ASSERT_MESSAGE(realised(), "render states are not realised"); - - // global settings that are not set in renderstates - glFrontFace(GL_CW); - glCullFace(GL_BACK); - glPolygonOffset(-1, 1); - { - const GLubyte pattern[132] = { - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, - 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55 - }; - glPolygonStipple(pattern); - } - glEnableClientState(GL_VERTEX_ARRAY); - g_vertexArray_enabled = true; - glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - - if (GlobalOpenGL().GL_1_3()) { - glActiveTexture(GL_TEXTURE0); - glClientActiveTexture(GL_TEXTURE0); - } - - if (GlobalOpenGL().ARB_shader_objects()) { - glUseProgramObjectARB(0); - glDisableVertexAttribArrayARB(c_attr_TexCoord0); - glDisableVertexAttribArrayARB(c_attr_Tangent); - glDisableVertexAttribArrayARB(c_attr_Binormal); - } - - if (globalstate & RENDER_TEXTURE) { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } - - OpenGLState current; - OpenGLState_constructDefault(current); - current.m_sort = OpenGLState::eSortFirst; - - // default renderstate settings - glLineStipple(current.m_linestipple_factor, current.m_linestipple_pattern); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glDisable(GL_LIGHTING); - glDisable(GL_TEXTURE_2D); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - g_texcoordArray_enabled = false; - glDisableClientState(GL_COLOR_ARRAY); - g_colorArray_enabled = false; - glDisableClientState(GL_NORMAL_ARRAY); - g_normalArray_enabled = false; - glDisable(GL_BLEND); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glShadeModel(GL_FLAT); - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - glDisable(GL_ALPHA_TEST); - glDisable(GL_LINE_STIPPLE); - glDisable(GL_POLYGON_STIPPLE); - glDisable(GL_POLYGON_OFFSET_LINE); - - glBindTexture(GL_TEXTURE_2D, 0); - glColor4f(1, 1, 1, 1); - glDepthFunc(GL_LESS); - glAlphaFunc(GL_ALWAYS, 0); - glLineWidth(1); - glPointSize(1); - - glHint(GL_FOG_HINT, GL_NICEST); - glDisable(GL_FOG); - setFogState(OpenGLFogState()); - - GlobalOpenGL_debugAssertNoErrors(); - - debug_string("begin rendering"); - for (OpenGLStates::iterator i = g_state_sorted.begin(); i != g_state_sorted.end(); ++i) { - (*i).second->render(current, globalstate, viewer); - } - debug_string("end rendering"); - } - - void realise() - { - if (--m_unrealised == 0) { - if (lightingSupported() && lightingEnabled()) { - if (useShaderLanguage()) { - g_bumpGLSL.create(); - g_depthFillGLSL.create(); - } else { - g_bumpARB.create(); - g_depthFillARB.create(); - } - } - - for (Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) { - if (!(*i).value.empty()) { - (*i).value->realise(i->key); - } - } - } - } - - void unrealise() - { - if (++m_unrealised == 1) { - for (Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i) { - if (!(*i).value.empty()) { - (*i).value->unrealise(); - } - } - if (GlobalOpenGL().contextValid && lightingSupported() && lightingEnabled()) { - if (useShaderLanguage()) { - g_bumpGLSL.destroy(); - g_depthFillGLSL.destroy(); - } else { - g_bumpARB.destroy(); - g_depthFillARB.destroy(); - } - } - } - } - - bool realised() - { - return m_unrealised == 0; - } - - - bool lightingEnabled() const - { - return m_lightingEnabled; - } - - bool lightingSupported() const - { - return m_lightingSupported; - } - - bool useShaderLanguage() const - { - return m_useShaderLanguage; - } - - void setLighting(bool supported, bool enabled) - { - bool refresh = (m_lightingSupported && m_lightingEnabled) != (supported && enabled); - - if (refresh) { - unrealise(); - GlobalShaderSystem().setLightingEnabled(supported && enabled); - } - - m_lightingSupported = supported; - m_lightingEnabled = enabled; - - if (refresh) { - realise(); - } - } - - void extensionsInitialised() - { - setLighting(GlobalOpenGL().GL_1_3() - && GlobalOpenGL().ARB_vertex_program() - && GlobalOpenGL().ARB_fragment_program() - && GlobalOpenGL().ARB_shader_objects() - && GlobalOpenGL().ARB_vertex_shader() - && GlobalOpenGL().ARB_fragment_shader() - && GlobalOpenGL().ARB_shading_language_100(), - m_lightingEnabled - ); - - if (!lightingSupported()) { - globalOutputStream() << "Lighting mode requires OpenGL features not supported by your graphics drivers:\n"; - if (!GlobalOpenGL().GL_1_3()) { - globalOutputStream() << " GL version 1.3 or better\n"; - } - if (!GlobalOpenGL().ARB_vertex_program()) { - globalOutputStream() << " GL_ARB_vertex_program\n"; - } - if (!GlobalOpenGL().ARB_fragment_program()) { - globalOutputStream() << " GL_ARB_fragment_program\n"; - } - if (!GlobalOpenGL().ARB_shader_objects()) { - globalOutputStream() << " GL_ARB_shader_objects\n"; - } - if (!GlobalOpenGL().ARB_vertex_shader()) { - globalOutputStream() << " GL_ARB_vertex_shader\n"; - } - if (!GlobalOpenGL().ARB_fragment_shader()) { - globalOutputStream() << " GL_ARB_fragment_shader\n"; - } - if (!GlobalOpenGL().ARB_shading_language_100()) { - globalOutputStream() << " GL_ARB_shading_language_100\n"; - } - } - } - - void setLightingEnabled(bool enabled) - { - setLighting(m_lightingSupported, enabled); - } +void realise(){ + if ( --m_unrealised == 0 ) { + if ( lightingSupported() && lightingEnabled() ) { + if ( useShaderLanguage() ) { + g_bumpGLSL.create(); + g_depthFillGLSL.create(); + } + else + { + g_bumpARB.create(); + g_depthFillARB.create(); + } + } + + for ( Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i ) + { + if ( !( *i ).value.empty() ) { + ( *i ).value->realise( i->key ); + } + } + } +} + +void unrealise(){ + if ( ++m_unrealised == 1 ) { + for ( Shaders::iterator i = m_shaders.begin(); i != m_shaders.end(); ++i ) + { + if ( !( *i ).value.empty() ) { + ( *i ).value->unrealise(); + } + } + if ( GlobalOpenGL().contextValid && lightingSupported() && lightingEnabled() ) { + if ( useShaderLanguage() ) { + g_bumpGLSL.destroy(); + g_depthFillGLSL.destroy(); + } + else + { + g_bumpARB.destroy(); + g_depthFillARB.destroy(); + } + } + } +} + +bool realised(){ + return m_unrealised == 0; +} + + +bool lightingEnabled() const { + return m_lightingEnabled; +} + +bool lightingSupported() const { + return m_lightingSupported; +} + +bool useShaderLanguage() const { + return m_useShaderLanguage; +} + +void setLighting( bool supported, bool enabled ){ + bool refresh = ( m_lightingSupported && m_lightingEnabled ) != ( supported && enabled ); + + if ( refresh ) { + unrealise(); + GlobalShaderSystem().setLightingEnabled( supported && enabled ); + } + + m_lightingSupported = supported; + m_lightingEnabled = enabled; + + if ( refresh ) { + realise(); + } +} + +void extensionsInitialised(){ + setLighting( GlobalOpenGL().GL_1_3() + && GlobalOpenGL().ARB_vertex_program() + && GlobalOpenGL().ARB_fragment_program() + && GlobalOpenGL().ARB_shader_objects() + && GlobalOpenGL().ARB_vertex_shader() + && GlobalOpenGL().ARB_fragment_shader() + && GlobalOpenGL().ARB_shading_language_100(), + m_lightingEnabled + ); + + if ( !lightingSupported() ) { + globalOutputStream() << "Lighting mode requires OpenGL features not supported by your graphics drivers:\n"; + if ( !GlobalOpenGL().GL_1_3() ) { + globalOutputStream() << " GL version 1.3 or better\n"; + } + if ( !GlobalOpenGL().ARB_vertex_program() ) { + globalOutputStream() << " GL_ARB_vertex_program\n"; + } + if ( !GlobalOpenGL().ARB_fragment_program() ) { + globalOutputStream() << " GL_ARB_fragment_program\n"; + } + if ( !GlobalOpenGL().ARB_shader_objects() ) { + globalOutputStream() << " GL_ARB_shader_objects\n"; + } + if ( !GlobalOpenGL().ARB_vertex_shader() ) { + globalOutputStream() << " GL_ARB_vertex_shader\n"; + } + if ( !GlobalOpenGL().ARB_fragment_shader() ) { + globalOutputStream() << " GL_ARB_fragment_shader\n"; + } + if ( !GlobalOpenGL().ARB_shading_language_100() ) { + globalOutputStream() << " GL_ARB_shading_language_100\n"; + } + } +} + +void setLightingEnabled( bool enabled ){ + setLighting( m_lightingSupported, enabled ); +} // light culling - RendererLights m_lights; - bool m_lightsChanged; - typedef std::map LightLists; - LightLists m_lightLists; - - const LightList &attach(LightCullable &cullable) - { - return (*m_lightLists.insert(LightLists::value_type(&cullable, LinearLightList(cullable, m_lights, - EvaluateChangedCaller( - *this)))).first).second; - } - - void detach(LightCullable &cullable) - { - m_lightLists.erase(&cullable); - } - - void changed(LightCullable &cullable) - { - LightLists::iterator i = m_lightLists.find(&cullable); - ASSERT_MESSAGE(i != m_lightLists.end(), "cullable not attached"); - (*i).second.lightsChanged(); - } - - void attach(RendererLight &light) - { - ASSERT_MESSAGE(m_lights.find(&light) == m_lights.end(), "light could not be attached"); - m_lights.insert(&light); - changed(light); - } - - void detach(RendererLight &light) - { - ASSERT_MESSAGE(m_lights.find(&light) != m_lights.end(), "light could not be detached"); - m_lights.erase(&light); - changed(light); - } - - void changed(RendererLight &light) - { - m_lightsChanged = true; - } - - void evaluateChanged() - { - if (m_lightsChanged) { - m_lightsChanged = false; - for (LightLists::iterator i = m_lightLists.begin(); i != m_lightLists.end(); ++i) { - (*i).second.lightsChanged(); - } - } - } - - typedef MemberCaller EvaluateChangedCaller; - - typedef std::set Renderables; - Renderables m_renderables; - mutable bool m_traverseRenderablesMutex; +RendererLights m_lights; +bool m_lightsChanged; +typedef std::map LightLists; +LightLists m_lightLists; + +const LightList& attach( LightCullable& cullable ){ + return ( *m_lightLists.insert( LightLists::value_type( &cullable, LinearLightList( cullable, m_lights, EvaluateChangedCaller( *this ) ) ) ).first ).second; +} + +void detach( LightCullable& cullable ){ + m_lightLists.erase( &cullable ); +} + +void changed( LightCullable& cullable ){ + LightLists::iterator i = m_lightLists.find( &cullable ); + ASSERT_MESSAGE( i != m_lightLists.end(), "cullable not attached" ); + ( *i ).second.lightsChanged(); +} + +void attach( RendererLight& light ){ + ASSERT_MESSAGE( m_lights.find( &light ) == m_lights.end(), "light could not be attached" ); + m_lights.insert( &light ); + changed( light ); +} + +void detach( RendererLight& light ){ + ASSERT_MESSAGE( m_lights.find( &light ) != m_lights.end(), "light could not be detached" ); + m_lights.erase( &light ); + changed( light ); +} + +void changed( RendererLight& light ){ + m_lightsChanged = true; +} + +void evaluateChanged(){ + if ( m_lightsChanged ) { + m_lightsChanged = false; + for ( LightLists::iterator i = m_lightLists.begin(); i != m_lightLists.end(); ++i ) + { + ( *i ).second.lightsChanged(); + } + } +} + +typedef MemberCaller EvaluateChangedCaller; + +typedef std::set Renderables; +Renderables m_renderables; +mutable bool m_traverseRenderablesMutex; // renderables - void attachRenderable(const Renderable &renderable) - { - ASSERT_MESSAGE(!m_traverseRenderablesMutex, "attaching renderable during traversal"); - ASSERT_MESSAGE(m_renderables.find(&renderable) == m_renderables.end(), "renderable could not be attached"); - m_renderables.insert(&renderable); - } - - void detachRenderable(const Renderable &renderable) - { - ASSERT_MESSAGE(!m_traverseRenderablesMutex, "detaching renderable during traversal"); - ASSERT_MESSAGE(m_renderables.find(&renderable) != m_renderables.end(), "renderable could not be detached"); - m_renderables.erase(&renderable); - } - - void forEachRenderable(const RenderableCallback &callback) const - { - ASSERT_MESSAGE(!m_traverseRenderablesMutex, "for-each during traversal"); - m_traverseRenderablesMutex = true; - for (Renderables::const_iterator i = m_renderables.begin(); i != m_renderables.end(); ++i) { - callback(*(*i)); - } - m_traverseRenderablesMutex = false; - } +void attachRenderable( const Renderable& renderable ){ + ASSERT_MESSAGE( !m_traverseRenderablesMutex, "attaching renderable during traversal" ); + ASSERT_MESSAGE( m_renderables.find( &renderable ) == m_renderables.end(), "renderable could not be attached" ); + m_renderables.insert( &renderable ); +} + +void detachRenderable( const Renderable& renderable ){ + ASSERT_MESSAGE( !m_traverseRenderablesMutex, "detaching renderable during traversal" ); + ASSERT_MESSAGE( m_renderables.find( &renderable ) != m_renderables.end(), "renderable could not be detached" ); + m_renderables.erase( &renderable ); +} + +void forEachRenderable( const RenderableCallback& callback ) const { + ASSERT_MESSAGE( !m_traverseRenderablesMutex, "for-each during traversal" ); + m_traverseRenderablesMutex = true; + for ( Renderables::const_iterator i = m_renderables.begin(); i != m_renderables.end(); ++i ) + { + callback( *( *i ) ); + } + m_traverseRenderablesMutex = false; +} }; -static OpenGLShaderCache *g_ShaderCache; +static OpenGLShaderCache* g_ShaderCache; -void ShaderCache_extensionsInitialised() -{ - g_ShaderCache->extensionsInitialised(); +void ShaderCache_extensionsInitialised(){ + g_ShaderCache->extensionsInitialised(); } -void ShaderCache_setBumpEnabled(bool enabled) -{ - g_ShaderCache->setLightingEnabled(enabled); +void ShaderCache_setBumpEnabled( bool enabled ){ + g_ShaderCache->setLightingEnabled( enabled ); } Vector3 g_DebugShaderColours[256]; -Shader *g_defaultPointLight = 0; +Shader* g_defaultPointLight = 0; -void ShaderCache_Construct() -{ - g_ShaderCache = new OpenGLShaderCache; - GlobalTexturesCache().attach(*g_ShaderCache); - GlobalShaderSystem().attach(*g_ShaderCache); +void ShaderCache_Construct(){ + g_ShaderCache = new OpenGLShaderCache; + GlobalTexturesCache().attach( *g_ShaderCache ); + GlobalShaderSystem().attach( *g_ShaderCache ); - if (g_pGameDescription->mGameType == "doom3") { - g_defaultPointLight = g_ShaderCache->capture("lights/defaultPointLight"); - //Shader* overbright = - g_ShaderCache->capture("$OVERBRIGHT"); + if ( g_pGameDescription->mGameType == "doom3" ) { + g_defaultPointLight = g_ShaderCache->capture( "lights/defaultPointLight" ); + //Shader* overbright = + g_ShaderCache->capture( "$OVERBRIGHT" ); #if LIGHT_SHADER_DEBUG - for ( std::size_t i = 0; i < 256; ++i ) + for ( std::size_t i = 0; i < 256; ++i ) { g_DebugShaderColours[i] = Vector3( i / 256.0, i / 256.0, i / 256.0 ); } @@ -1664,18 +1586,17 @@ void ShaderCache_Construct() buffer.clear(); } #endif - } + } } -void ShaderCache_Destroy() -{ - if (g_pGameDescription->mGameType == "doom3") { - g_ShaderCache->release("lights/defaultPointLight"); - g_ShaderCache->release("$OVERBRIGHT"); - g_defaultPointLight = 0; +void ShaderCache_Destroy(){ + if ( g_pGameDescription->mGameType == "doom3" ) { + g_ShaderCache->release( "lights/defaultPointLight" ); + g_ShaderCache->release( "$OVERBRIGHT" ); + g_defaultPointLight = 0; #if LIGHT_SHADER_DEBUG - g_lightDebugShaders.clear(); + g_lightDebugShaders.clear(); StringOutputStream buffer( 256 ); for ( std::size_t i = 0; i < 256; ++i ) { @@ -1683,890 +1604,890 @@ void ShaderCache_Destroy() g_ShaderCache->release( buffer.c_str() ); } #endif - } + } - GlobalShaderSystem().detach(*g_ShaderCache); - GlobalTexturesCache().detach(*g_ShaderCache); - delete g_ShaderCache; + GlobalShaderSystem().detach( *g_ShaderCache ); + GlobalTexturesCache().detach( *g_ShaderCache ); + delete g_ShaderCache; } -ShaderCache *GetShaderCache() -{ - return g_ShaderCache; +ShaderCache* GetShaderCache(){ + return g_ShaderCache; } -inline void setTextureState(GLint ¤t, const GLint &texture, GLenum textureUnit) -{ - if (texture != current) { - glActiveTexture(textureUnit); - glClientActiveTexture(textureUnit); - glBindTexture(GL_TEXTURE_2D, texture); - GlobalOpenGL_debugAssertNoErrors(); - current = texture; - } +inline void setTextureState( GLint& current, const GLint& texture, GLenum textureUnit ){ + if ( texture != current ) { + glActiveTexture( textureUnit ); + glClientActiveTexture( textureUnit ); + glBindTexture( GL_TEXTURE_2D, texture ); + GlobalOpenGL_debugAssertNoErrors(); + current = texture; + } } -inline void setTextureState(GLint ¤t, const GLint &texture) -{ - if (texture != current) { - glBindTexture(GL_TEXTURE_2D, texture); - GlobalOpenGL_debugAssertNoErrors(); - current = texture; - } +inline void setTextureState( GLint& current, const GLint& texture ){ + if ( texture != current ) { + glBindTexture( GL_TEXTURE_2D, texture ); + GlobalOpenGL_debugAssertNoErrors(); + current = texture; + } } -inline void setState(unsigned int state, unsigned int delta, unsigned int flag, GLenum glflag) -{ - if (delta & state & flag) { - glEnable(glflag); - GlobalOpenGL_debugAssertNoErrors(); - } else if (delta & ~state & flag) { - glDisable(glflag); - GlobalOpenGL_debugAssertNoErrors(); - } +inline void setState( unsigned int state, unsigned int delta, unsigned int flag, GLenum glflag ){ + if ( delta & state & flag ) { + glEnable( glflag ); + GlobalOpenGL_debugAssertNoErrors(); + } + else if ( delta & ~state & flag ) { + glDisable( glflag ); + GlobalOpenGL_debugAssertNoErrors(); + } } -void OpenGLState_apply(const OpenGLState &self, OpenGLState ¤t, unsigned int globalstate) -{ - debug_int("sort", int(self.m_sort)); - debug_int("texture", self.m_texture); - debug_int("state", self.m_state); - debug_int("address", int(std::size_t(&self))); - - count_state(); - - if (self.m_state & RENDER_OVERRIDE) { - globalstate |= RENDER_FILL | RENDER_DEPTHWRITE; - } - - const unsigned int state = self.m_state & globalstate; - const unsigned int delta = state ^current.m_state; - - GlobalOpenGL_debugAssertNoErrors(); - - GLProgram *program = (state & RENDER_PROGRAM) != 0 ? self.m_program : 0; - - if (program != current.m_program) { - if (current.m_program != 0) { - current.m_program->disable(); - glColor4fv(vector4_to_array(current.m_colour)); - debug_colour("cleaning program"); - } - - current.m_program = program; - - if (current.m_program != 0) { - current.m_program->enable(); - } - } - - if (delta & state & RENDER_FILL) { - //qglPolygonMode (GL_BACK, GL_LINE); - //qglPolygonMode (GL_FRONT, GL_FILL); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - GlobalOpenGL_debugAssertNoErrors(); - } else if (delta & ~state & RENDER_FILL) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState(state, delta, RENDER_OFFSETLINE, GL_POLYGON_OFFSET_LINE); - - if (delta & state & RENDER_LIGHTING) { - glEnable(GL_LIGHTING); - glEnable(GL_COLOR_MATERIAL); - glEnable(GL_RESCALE_NORMAL); - glEnableClientState(GL_NORMAL_ARRAY); - GlobalOpenGL_debugAssertNoErrors(); - g_normalArray_enabled = true; - } else if (delta & ~state & RENDER_LIGHTING) { - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - glDisable(GL_RESCALE_NORMAL); - glDisableClientState(GL_NORMAL_ARRAY); - GlobalOpenGL_debugAssertNoErrors(); - g_normalArray_enabled = false; - } - - if (delta & state & RENDER_TEXTURE) { - GlobalOpenGL_debugAssertNoErrors(); - - if (GlobalOpenGL().GL_1_3()) { - glActiveTexture(GL_TEXTURE0); - glClientActiveTexture(GL_TEXTURE0); - } - - glEnable(GL_TEXTURE_2D); - - glColor4f(1, 1, 1, self.m_colour[3]); - debug_colour("setting texture"); - - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - GlobalOpenGL_debugAssertNoErrors(); - g_texcoordArray_enabled = true; - } else if (delta & ~state & RENDER_TEXTURE) { - if (GlobalOpenGL().GL_1_3()) { - glActiveTexture(GL_TEXTURE0); - glClientActiveTexture(GL_TEXTURE0); - } - - glDisable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - GlobalOpenGL_debugAssertNoErrors(); - g_texcoordArray_enabled = false; - } - - if (delta & state & RENDER_BLEND) { +void OpenGLState_apply( const OpenGLState& self, OpenGLState& current, unsigned int globalstate ){ + debug_int( "sort", int(self.m_sort) ); + debug_int( "texture", self.m_texture ); + debug_int( "state", self.m_state ); + debug_int( "address", int(std::size_t( &self ) ) ); + + count_state(); + + if ( self.m_state & RENDER_OVERRIDE ) { + globalstate |= RENDER_FILL | RENDER_DEPTHWRITE; + } + + const unsigned int state = self.m_state & globalstate; + const unsigned int delta = state ^ current.m_state; + + GlobalOpenGL_debugAssertNoErrors(); + + GLProgram* program = ( state & RENDER_PROGRAM ) != 0 ? self.m_program : 0; + + if ( program != current.m_program ) { + if ( current.m_program != 0 ) { + current.m_program->disable(); + glColor4fv( vector4_to_array( current.m_colour ) ); + debug_colour( "cleaning program" ); + } + + current.m_program = program; + + if ( current.m_program != 0 ) { + current.m_program->enable(); + } + } + + if ( delta & state & RENDER_FILL ) { + //qglPolygonMode (GL_BACK, GL_LINE); + //qglPolygonMode (GL_FRONT, GL_FILL); + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + GlobalOpenGL_debugAssertNoErrors(); + } + else if ( delta & ~state & RENDER_FILL ) { + glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState( state, delta, RENDER_OFFSETLINE, GL_POLYGON_OFFSET_LINE ); + + if ( delta & state & RENDER_LIGHTING ) { + glEnable( GL_LIGHTING ); + glEnable( GL_COLOR_MATERIAL ); + glEnable( GL_RESCALE_NORMAL ); + glEnableClientState( GL_NORMAL_ARRAY ); + GlobalOpenGL_debugAssertNoErrors(); + g_normalArray_enabled = true; + } + else if ( delta & ~state & RENDER_LIGHTING ) { + glDisable( GL_LIGHTING ); + glDisable( GL_COLOR_MATERIAL ); + glDisable( GL_RESCALE_NORMAL ); + glDisableClientState( GL_NORMAL_ARRAY ); + GlobalOpenGL_debugAssertNoErrors(); + g_normalArray_enabled = false; + } + + if ( delta & state & RENDER_TEXTURE ) { + GlobalOpenGL_debugAssertNoErrors(); + + if ( GlobalOpenGL().GL_1_3() ) { + glActiveTexture( GL_TEXTURE0 ); + glClientActiveTexture( GL_TEXTURE0 ); + } + + glEnable( GL_TEXTURE_2D ); + + glColor4f( 1,1,1,self.m_colour[3] ); + debug_colour( "setting texture" ); + + glEnableClientState( GL_TEXTURE_COORD_ARRAY ); + GlobalOpenGL_debugAssertNoErrors(); + g_texcoordArray_enabled = true; + } + else if ( delta & ~state & RENDER_TEXTURE ) { + if ( GlobalOpenGL().GL_1_3() ) { + glActiveTexture( GL_TEXTURE0 ); + glClientActiveTexture( GL_TEXTURE0 ); + } + + glDisable( GL_TEXTURE_2D ); + glBindTexture( GL_TEXTURE_2D, 0 ); + glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + + GlobalOpenGL_debugAssertNoErrors(); + g_texcoordArray_enabled = false; + } + + if ( delta & state & RENDER_BLEND ) { // FIXME: some .TGA are buggy, have a completely empty alpha channel // if such brushes are rendered in this loop they would be totally transparent with GL_MODULATE // so I decided using GL_DECAL instead // if an empty-alpha-channel or nearly-empty texture is used. It will be blank-transparent. // this could get better if you can get glTexEnviv (GL_TEXTURE_ENV, to work .. patches are welcome - glEnable(GL_BLEND); - if (GlobalOpenGL().GL_1_3()) { - glActiveTexture(GL_TEXTURE0); - } - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); - GlobalOpenGL_debugAssertNoErrors(); - } else if (delta & ~state & RENDER_BLEND) { - glDisable(GL_BLEND); - if (GlobalOpenGL().GL_1_3()) { - glActiveTexture(GL_TEXTURE0); - } - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState(state, delta, RENDER_CULLFACE, GL_CULL_FACE); - - if (delta & state & RENDER_SMOOTH) { - glShadeModel(GL_SMOOTH); - GlobalOpenGL_debugAssertNoErrors(); - } else if (delta & ~state & RENDER_SMOOTH) { - glShadeModel(GL_FLAT); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState(state, delta, RENDER_SCALED, GL_NORMALIZE); // not GL_RESCALE_NORMAL - - setState(state, delta, RENDER_DEPTHTEST, GL_DEPTH_TEST); - - if (delta & state & RENDER_DEPTHWRITE) { - glDepthMask(GL_TRUE); + glEnable( GL_BLEND ); + if ( GlobalOpenGL().GL_1_3() ) { + glActiveTexture( GL_TEXTURE0 ); + } + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); + GlobalOpenGL_debugAssertNoErrors(); + } + else if ( delta & ~state & RENDER_BLEND ) { + glDisable( GL_BLEND ); + if ( GlobalOpenGL().GL_1_3() ) { + glActiveTexture( GL_TEXTURE0 ); + } + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState( state, delta, RENDER_CULLFACE, GL_CULL_FACE ); + + if ( delta & state & RENDER_SMOOTH ) { + glShadeModel( GL_SMOOTH ); + GlobalOpenGL_debugAssertNoErrors(); + } + else if ( delta & ~state & RENDER_SMOOTH ) { + glShadeModel( GL_FLAT ); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState( state, delta, RENDER_SCALED, GL_NORMALIZE ); // not GL_RESCALE_NORMAL + + setState( state, delta, RENDER_DEPTHTEST, GL_DEPTH_TEST ); + + if ( delta & state & RENDER_DEPTHWRITE ) { + glDepthMask( GL_TRUE ); #if DEBUG_RENDER - GLboolean depthEnabled; + GLboolean depthEnabled; glGetBooleanv( GL_DEPTH_WRITEMASK, &depthEnabled ); ASSERT_MESSAGE( depthEnabled, "failed to set depth buffer mask bit" ); #endif - debug_string("enabled depth-buffer writing"); + debug_string( "enabled depth-buffer writing" ); - GlobalOpenGL_debugAssertNoErrors(); - } else if (delta & ~state & RENDER_DEPTHWRITE) { - glDepthMask(GL_FALSE); + GlobalOpenGL_debugAssertNoErrors(); + } + else if ( delta & ~state & RENDER_DEPTHWRITE ) { + glDepthMask( GL_FALSE ); #if DEBUG_RENDER - GLboolean depthEnabled; + GLboolean depthEnabled; glGetBooleanv( GL_DEPTH_WRITEMASK, &depthEnabled ); ASSERT_MESSAGE( !depthEnabled, "failed to set depth buffer mask bit" ); #endif - debug_string("disabled depth-buffer writing"); - - GlobalOpenGL_debugAssertNoErrors(); - } - - if (delta & state & RENDER_COLOURWRITE) { - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - GlobalOpenGL_debugAssertNoErrors(); - } else if (delta & ~state & RENDER_COLOURWRITE) { - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState(state, delta, RENDER_ALPHATEST, GL_ALPHA_TEST); - - if (delta & state & RENDER_COLOURARRAY) { - glEnableClientState(GL_COLOR_ARRAY); - GlobalOpenGL_debugAssertNoErrors(); - debug_colour("enabling color_array"); - g_colorArray_enabled = true; - } else if (delta & ~state & RENDER_COLOURARRAY) { - glDisableClientState(GL_COLOR_ARRAY); - glColor4fv(vector4_to_array(self.m_colour)); - debug_colour("cleaning color_array"); - GlobalOpenGL_debugAssertNoErrors(); - g_colorArray_enabled = false; - } - - if (delta & ~state & RENDER_COLOURCHANGE) { - glColor4fv(vector4_to_array(self.m_colour)); - GlobalOpenGL_debugAssertNoErrors(); - } - - setState(state, delta, RENDER_LINESTIPPLE, GL_LINE_STIPPLE); - setState(state, delta, RENDER_LINESMOOTH, GL_LINE_SMOOTH); - - setState(state, delta, RENDER_POLYGONSTIPPLE, GL_POLYGON_STIPPLE); - setState(state, delta, RENDER_POLYGONSMOOTH, GL_POLYGON_SMOOTH); - - setState(state, delta, RENDER_FOG, GL_FOG); - - if ((state & RENDER_FOG) != 0) { - setFogState(self.m_fog); - GlobalOpenGL_debugAssertNoErrors(); - current.m_fog = self.m_fog; - } - - if (state & RENDER_DEPTHTEST && self.m_depthfunc != current.m_depthfunc) { - glDepthFunc(self.m_depthfunc); - GlobalOpenGL_debugAssertNoErrors(); - current.m_depthfunc = self.m_depthfunc; - } - - if (state & RENDER_LINESTIPPLE - && (self.m_linestipple_factor != current.m_linestipple_factor - || self.m_linestipple_pattern != current.m_linestipple_pattern)) { - glLineStipple(self.m_linestipple_factor, self.m_linestipple_pattern); - GlobalOpenGL_debugAssertNoErrors(); - current.m_linestipple_factor = self.m_linestipple_factor; - current.m_linestipple_pattern = self.m_linestipple_pattern; - } - - - if (state & RENDER_ALPHATEST - && (self.m_alphafunc != current.m_alphafunc - || self.m_alpharef != current.m_alpharef)) { - glAlphaFunc(self.m_alphafunc, self.m_alpharef); - GlobalOpenGL_debugAssertNoErrors(); - current.m_alphafunc = self.m_alphafunc; - current.m_alpharef = self.m_alpharef; - } - - { - GLint texture0 = 0; - GLint texture1 = 0; - GLint texture2 = 0; - GLint texture3 = 0; - GLint texture4 = 0; - GLint texture5 = 0; - GLint texture6 = 0; - GLint texture7 = 0; - //if(state & RENDER_TEXTURE) != 0) - { - texture0 = self.m_texture; - texture1 = self.m_texture1; - texture2 = self.m_texture2; - texture3 = self.m_texture3; - texture4 = self.m_texture4; - texture5 = self.m_texture5; - texture6 = self.m_texture6; - texture7 = self.m_texture7; - } - - if (GlobalOpenGL().GL_1_3()) { - setTextureState(current.m_texture, texture0, GL_TEXTURE0); - setTextureState(current.m_texture1, texture1, GL_TEXTURE1); - setTextureState(current.m_texture2, texture2, GL_TEXTURE2); - setTextureState(current.m_texture3, texture3, GL_TEXTURE3); - setTextureState(current.m_texture4, texture4, GL_TEXTURE4); - setTextureState(current.m_texture5, texture5, GL_TEXTURE5); - setTextureState(current.m_texture6, texture6, GL_TEXTURE6); - setTextureState(current.m_texture7, texture7, GL_TEXTURE7); - } else { - setTextureState(current.m_texture, texture0); - } - } - - - if (state & RENDER_TEXTURE && self.m_colour[3] != current.m_colour[3]) { - debug_colour("setting alpha"); - glColor4f(1, 1, 1, self.m_colour[3]); - GlobalOpenGL_debugAssertNoErrors(); - } - - if (!(state & RENDER_TEXTURE) - && (self.m_colour[0] != current.m_colour[0] - || self.m_colour[1] != current.m_colour[1] - || self.m_colour[2] != current.m_colour[2] - || self.m_colour[3] != current.m_colour[3])) { - glColor4fv(vector4_to_array(self.m_colour)); - debug_colour("setting non-texture"); - GlobalOpenGL_debugAssertNoErrors(); - } - current.m_colour = self.m_colour; - - if (state & RENDER_BLEND - && (self.m_blend_src != current.m_blend_src || self.m_blend_dst != current.m_blend_dst)) { - glBlendFunc(self.m_blend_src, self.m_blend_dst); - GlobalOpenGL_debugAssertNoErrors(); - current.m_blend_src = self.m_blend_src; - current.m_blend_dst = self.m_blend_dst; - } - - if (!(state & RENDER_FILL) - && self.m_linewidth != current.m_linewidth) { - glLineWidth(self.m_linewidth); - GlobalOpenGL_debugAssertNoErrors(); - current.m_linewidth = self.m_linewidth; - } - - if (!(state & RENDER_FILL) - && self.m_pointsize != current.m_pointsize) { - glPointSize(self.m_pointsize); - GlobalOpenGL_debugAssertNoErrors(); - current.m_pointsize = self.m_pointsize; - } - - current.m_state = state; - - GlobalOpenGL_debugAssertNoErrors(); -} - -void Renderables_flush(OpenGLStateBucket::Renderables &renderables, OpenGLState ¤t, unsigned int globalstate, - const Vector3 &viewer) -{ - const Matrix4 *transform = 0; - glPushMatrix(); - for (OpenGLStateBucket::Renderables::const_iterator i = renderables.begin(); i != renderables.end(); ++i) { - //qglLoadMatrixf(i->m_transform); - if (!transform || (transform != (*i).m_transform && !matrix4_affine_equal(*transform, *(*i).m_transform))) { - count_transform(); - transform = (*i).m_transform; - glPopMatrix(); - glPushMatrix(); - glMultMatrixf(reinterpret_cast( transform )); - glFrontFace( - ((current.m_state & RENDER_CULLFACE) != 0 && matrix4_handedness(*transform) == MATRIX4_RIGHTHANDED) - ? GL_CW : GL_CCW); - } - - count_prim(); - - if (current.m_program != 0 && (*i).m_light != 0) { - const IShader &lightShader = static_cast((*i).m_light->getShader())->getShader(); - if (lightShader.firstLayer() != 0) { - GLuint attenuation_xy = lightShader.firstLayer()->texture()->texture_number; - GLuint attenuation_z = lightShader.lightFalloffImage() != 0 - ? lightShader.lightFalloffImage()->texture_number - : static_cast( g_defaultPointLight )->getShader().lightFalloffImage()->texture_number; - - setTextureState(current.m_texture3, attenuation_xy, GL_TEXTURE3); - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_2D, attenuation_xy); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - - setTextureState(current.m_texture4, attenuation_z, GL_TEXTURE4); - glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_2D, attenuation_z); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - - AABB lightBounds((*i).m_light->aabb()); - - Matrix4 world2light(g_matrix4_identity); - - if ((*i).m_light->isProjected()) { - world2light = (*i).m_light->projection(); - matrix4_multiply_by_matrix4(world2light, matrix4_transposed((*i).m_light->rotation())); - matrix4_translate_by_vec3(world2light, vector3_negated(lightBounds.origin)); // world->lightBounds - } - if (!(*i).m_light->isProjected()) { - matrix4_translate_by_vec3(world2light, Vector3(0.5f, 0.5f, 0.5f)); - matrix4_scale_by_vec3(world2light, Vector3(0.5f, 0.5f, 0.5f)); - matrix4_scale_by_vec3(world2light, - Vector3(1.0f / lightBounds.extents.x(), 1.0f / lightBounds.extents.y(), - 1.0f / lightBounds.extents.z())); - matrix4_multiply_by_matrix4(world2light, matrix4_transposed((*i).m_light->rotation())); - matrix4_translate_by_vec3(world2light, vector3_negated(lightBounds.origin)); // world->lightBounds - } - - current.m_program->setParameters(viewer, *(*i).m_transform, lightBounds.origin + (*i).m_light->offset(), - (*i).m_light->colour(), world2light); - debug_string("set lightBounds parameters"); - } - } - - (*i).m_renderable->render(current.m_state); - } - glPopMatrix(); - renderables.clear(); -} - -void OpenGLStateBucket::render(OpenGLState ¤t, unsigned int globalstate, const Vector3 &viewer) -{ - if ((globalstate & m_state.m_state & RENDER_SCREEN) != 0) { - OpenGLState_apply(m_state, current, globalstate); - debug_colour("screen fill"); + debug_string( "disabled depth-buffer writing" ); + + GlobalOpenGL_debugAssertNoErrors(); + } + + if ( delta & state & RENDER_COLOURWRITE ) { + glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); + GlobalOpenGL_debugAssertNoErrors(); + } + else if ( delta & ~state & RENDER_COLOURWRITE ) { + glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState( state, delta, RENDER_ALPHATEST, GL_ALPHA_TEST ); + + if ( delta & state & RENDER_COLOURARRAY ) { + glEnableClientState( GL_COLOR_ARRAY ); + GlobalOpenGL_debugAssertNoErrors(); + debug_colour( "enabling color_array" ); + g_colorArray_enabled = true; + } + else if ( delta & ~state & RENDER_COLOURARRAY ) { + glDisableClientState( GL_COLOR_ARRAY ); + glColor4fv( vector4_to_array( self.m_colour ) ); + debug_colour( "cleaning color_array" ); + GlobalOpenGL_debugAssertNoErrors(); + g_colorArray_enabled = false; + } + + if ( delta & ~state & RENDER_COLOURCHANGE ) { + glColor4fv( vector4_to_array( self.m_colour ) ); + GlobalOpenGL_debugAssertNoErrors(); + } + + setState( state, delta, RENDER_LINESTIPPLE, GL_LINE_STIPPLE ); + setState( state, delta, RENDER_LINESMOOTH, GL_LINE_SMOOTH ); + + setState( state, delta, RENDER_POLYGONSTIPPLE, GL_POLYGON_STIPPLE ); + setState( state, delta, RENDER_POLYGONSMOOTH, GL_POLYGON_SMOOTH ); + + setState( state, delta, RENDER_FOG, GL_FOG ); + + if ( ( state & RENDER_FOG ) != 0 ) { + setFogState( self.m_fog ); + GlobalOpenGL_debugAssertNoErrors(); + current.m_fog = self.m_fog; + } + + if ( state & RENDER_DEPTHTEST && self.m_depthfunc != current.m_depthfunc ) { + glDepthFunc( self.m_depthfunc ); + GlobalOpenGL_debugAssertNoErrors(); + current.m_depthfunc = self.m_depthfunc; + } + + if ( state & RENDER_LINESTIPPLE + && ( self.m_linestipple_factor != current.m_linestipple_factor + || self.m_linestipple_pattern != current.m_linestipple_pattern ) ) { + glLineStipple( self.m_linestipple_factor, self.m_linestipple_pattern ); + GlobalOpenGL_debugAssertNoErrors(); + current.m_linestipple_factor = self.m_linestipple_factor; + current.m_linestipple_pattern = self.m_linestipple_pattern; + } + + + if ( state & RENDER_ALPHATEST + && ( self.m_alphafunc != current.m_alphafunc + || self.m_alpharef != current.m_alpharef ) ) { + glAlphaFunc( self.m_alphafunc, self.m_alpharef ); + GlobalOpenGL_debugAssertNoErrors(); + current.m_alphafunc = self.m_alphafunc; + current.m_alpharef = self.m_alpharef; + } + + { + GLint texture0 = 0; + GLint texture1 = 0; + GLint texture2 = 0; + GLint texture3 = 0; + GLint texture4 = 0; + GLint texture5 = 0; + GLint texture6 = 0; + GLint texture7 = 0; + //if(state & RENDER_TEXTURE) != 0) + { + texture0 = self.m_texture; + texture1 = self.m_texture1; + texture2 = self.m_texture2; + texture3 = self.m_texture3; + texture4 = self.m_texture4; + texture5 = self.m_texture5; + texture6 = self.m_texture6; + texture7 = self.m_texture7; + } + + if ( GlobalOpenGL().GL_1_3() ) { + setTextureState( current.m_texture, texture0, GL_TEXTURE0 ); + setTextureState( current.m_texture1, texture1, GL_TEXTURE1 ); + setTextureState( current.m_texture2, texture2, GL_TEXTURE2 ); + setTextureState( current.m_texture3, texture3, GL_TEXTURE3 ); + setTextureState( current.m_texture4, texture4, GL_TEXTURE4 ); + setTextureState( current.m_texture5, texture5, GL_TEXTURE5 ); + setTextureState( current.m_texture6, texture6, GL_TEXTURE6 ); + setTextureState( current.m_texture7, texture7, GL_TEXTURE7 ); + } + else + { + setTextureState( current.m_texture, texture0 ); + } + } + + + if ( state & RENDER_TEXTURE && self.m_colour[3] != current.m_colour[3] ) { + debug_colour( "setting alpha" ); + glColor4f( 1,1,1,self.m_colour[3] ); + GlobalOpenGL_debugAssertNoErrors(); + } + + if ( !( state & RENDER_TEXTURE ) + && ( self.m_colour[0] != current.m_colour[0] + || self.m_colour[1] != current.m_colour[1] + || self.m_colour[2] != current.m_colour[2] + || self.m_colour[3] != current.m_colour[3] ) ) { + glColor4fv( vector4_to_array( self.m_colour ) ); + debug_colour( "setting non-texture" ); + GlobalOpenGL_debugAssertNoErrors(); + } + current.m_colour = self.m_colour; + + if ( state & RENDER_BLEND + && ( self.m_blend_src != current.m_blend_src || self.m_blend_dst != current.m_blend_dst ) ) { + glBlendFunc( self.m_blend_src, self.m_blend_dst ); + GlobalOpenGL_debugAssertNoErrors(); + current.m_blend_src = self.m_blend_src; + current.m_blend_dst = self.m_blend_dst; + } + + if ( !( state & RENDER_FILL ) + && self.m_linewidth != current.m_linewidth ) { + glLineWidth( self.m_linewidth ); + GlobalOpenGL_debugAssertNoErrors(); + current.m_linewidth = self.m_linewidth; + } + + if ( !( state & RENDER_FILL ) + && self.m_pointsize != current.m_pointsize ) { + glPointSize( self.m_pointsize ); + GlobalOpenGL_debugAssertNoErrors(); + current.m_pointsize = self.m_pointsize; + } + + current.m_state = state; + + GlobalOpenGL_debugAssertNoErrors(); +} + +void Renderables_flush( OpenGLStateBucket::Renderables& renderables, OpenGLState& current, unsigned int globalstate, const Vector3& viewer ){ + const Matrix4* transform = 0; + glPushMatrix(); + for ( OpenGLStateBucket::Renderables::const_iterator i = renderables.begin(); i != renderables.end(); ++i ) + { + //qglLoadMatrixf(i->m_transform); + if ( !transform || ( transform != ( *i ).m_transform && !matrix4_affine_equal( *transform, *( *i ).m_transform ) ) ) { + count_transform(); + transform = ( *i ).m_transform; + glPopMatrix(); + glPushMatrix(); + glMultMatrixf( reinterpret_cast( transform ) ); + glFrontFace( ( ( current.m_state & RENDER_CULLFACE ) != 0 && matrix4_handedness( *transform ) == MATRIX4_RIGHTHANDED ) ? GL_CW : GL_CCW ); + } + + count_prim(); + + if ( current.m_program != 0 && ( *i ).m_light != 0 ) { + const IShader& lightShader = static_cast( ( *i ).m_light->getShader() )->getShader(); + if ( lightShader.firstLayer() != 0 ) { + GLuint attenuation_xy = lightShader.firstLayer()->texture()->texture_number; + GLuint attenuation_z = lightShader.lightFalloffImage() != 0 + ? lightShader.lightFalloffImage()->texture_number + : static_cast( g_defaultPointLight )->getShader().lightFalloffImage()->texture_number; + + setTextureState( current.m_texture3, attenuation_xy, GL_TEXTURE3 ); + glActiveTexture( GL_TEXTURE3 ); + glBindTexture( GL_TEXTURE_2D, attenuation_xy ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER ); + + setTextureState( current.m_texture4, attenuation_z, GL_TEXTURE4 ); + glActiveTexture( GL_TEXTURE4 ); + glBindTexture( GL_TEXTURE_2D, attenuation_z ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + + + AABB lightBounds( ( *i ).m_light->aabb() ); + + Matrix4 world2light( g_matrix4_identity ); + + if ( ( *i ).m_light->isProjected() ) { + world2light = ( *i ).m_light->projection(); + matrix4_multiply_by_matrix4( world2light, matrix4_transposed( ( *i ).m_light->rotation() ) ); + matrix4_translate_by_vec3( world2light, vector3_negated( lightBounds.origin ) ); // world->lightBounds + } + if ( !( *i ).m_light->isProjected() ) { + matrix4_translate_by_vec3( world2light, Vector3( 0.5f, 0.5f, 0.5f ) ); + matrix4_scale_by_vec3( world2light, Vector3( 0.5f, 0.5f, 0.5f ) ); + matrix4_scale_by_vec3( world2light, Vector3( 1.0f / lightBounds.extents.x(), 1.0f / lightBounds.extents.y(), 1.0f / lightBounds.extents.z() ) ); + matrix4_multiply_by_matrix4( world2light, matrix4_transposed( ( *i ).m_light->rotation() ) ); + matrix4_translate_by_vec3( world2light, vector3_negated( lightBounds.origin ) ); // world->lightBounds + } + + current.m_program->setParameters( viewer, *( *i ).m_transform, lightBounds.origin + ( *i ).m_light->offset(), ( *i ).m_light->colour(), world2light ); + debug_string( "set lightBounds parameters" ); + } + } + + ( *i ).m_renderable->render( current.m_state ); + } + glPopMatrix(); + renderables.clear(); +} - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadMatrixf(reinterpret_cast( &g_matrix4_identity )); +void OpenGLStateBucket::render( OpenGLState& current, unsigned int globalstate, const Vector3& viewer ){ + if ( ( globalstate & m_state.m_state & RENDER_SCREEN ) != 0 ) { + OpenGLState_apply( m_state, current, globalstate ); + debug_colour( "screen fill" ); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadMatrixf(reinterpret_cast( &g_matrix4_identity )); + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadMatrixf( reinterpret_cast( &g_matrix4_identity ) ); - glBegin(GL_QUADS); - glVertex3f(-1, -1, 0); - glVertex3f(1, -1, 0); - glVertex3f(1, 1, 0); - glVertex3f(-1, 1, 0); - glEnd(); + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadMatrixf( reinterpret_cast( &g_matrix4_identity ) ); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); + glBegin( GL_QUADS ); + glVertex3f( -1, -1, 0 ); + glVertex3f( 1, -1, 0 ); + glVertex3f( 1, 1, 0 ); + glVertex3f( -1, 1, 0 ); + glEnd(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - } else if (!m_renderables.empty()) { - OpenGLState_apply(m_state, current, globalstate); - Renderables_flush(m_renderables, current, globalstate, viewer); - } + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + + glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); + } + else if ( !m_renderables.empty() ) { + OpenGLState_apply( m_state, current, globalstate ); + Renderables_flush( m_renderables, current, globalstate, viewer ); + } } -class OpenGLStateMap : public OpenGLStateLibrary { - typedef std::map States; - States m_states; +class OpenGLStateMap : public OpenGLStateLibrary +{ +typedef std::map States; +States m_states; public: - ~OpenGLStateMap() - { - ASSERT_MESSAGE(m_states.empty(), "OpenGLStateMap::~OpenGLStateMap: not empty"); - } - - typedef States::iterator iterator; - - iterator begin() - { - return m_states.begin(); - } - - iterator end() - { - return m_states.end(); - } - - void getDefaultState(OpenGLState &state) const - { - OpenGLState_constructDefault(state); - } - - void insert(const char *name, const OpenGLState &state) - { - bool inserted = m_states.insert(States::value_type(name, state)).second; - ASSERT_MESSAGE(inserted, "OpenGLStateMap::insert: " << name << " already exists"); - } - - void erase(const char *name) - { - std::size_t count = m_states.erase(name); - ASSERT_MESSAGE(count == 1, "OpenGLStateMap::erase: " << name << " does not exist"); - } - - iterator find(const char *name) - { - return m_states.find(name); - } +~OpenGLStateMap(){ + ASSERT_MESSAGE( m_states.empty(), "OpenGLStateMap::~OpenGLStateMap: not empty" ); +} + +typedef States::iterator iterator; + +iterator begin(){ + return m_states.begin(); +} + +iterator end(){ + return m_states.end(); +} + +void getDefaultState( OpenGLState& state ) const { + OpenGLState_constructDefault( state ); +} + +void insert( const char* name, const OpenGLState& state ){ + bool inserted = m_states.insert( States::value_type( name, state ) ).second; + ASSERT_MESSAGE( inserted, "OpenGLStateMap::insert: " << name << " already exists" ); +} + +void erase( const char* name ){ + std::size_t count = m_states.erase( name ); + ASSERT_MESSAGE( count == 1, "OpenGLStateMap::erase: " << name << " does not exist" ); +} + +iterator find( const char* name ){ + return m_states.find( name ); +} }; -OpenGLStateMap *g_openglStates = 0; +OpenGLStateMap* g_openglStates = 0; -inline GLenum convertBlendFactor(BlendFactor factor) -{ - switch (factor) { - case BLEND_ZERO: - return GL_ZERO; - case BLEND_ONE: - return GL_ONE; - case BLEND_SRC_COLOUR: - return GL_SRC_COLOR; - case BLEND_ONE_MINUS_SRC_COLOUR: - return GL_ONE_MINUS_SRC_COLOR; - case BLEND_SRC_ALPHA: - return GL_SRC_ALPHA; - case BLEND_ONE_MINUS_SRC_ALPHA: - return GL_ONE_MINUS_SRC_ALPHA; - case BLEND_DST_COLOUR: - return GL_DST_COLOR; - case BLEND_ONE_MINUS_DST_COLOUR: - return GL_ONE_MINUS_DST_COLOR; - case BLEND_DST_ALPHA: - return GL_DST_ALPHA; - case BLEND_ONE_MINUS_DST_ALPHA: - return GL_ONE_MINUS_DST_ALPHA; - case BLEND_SRC_ALPHA_SATURATE: - return GL_SRC_ALPHA_SATURATE; - } - return GL_ZERO; +inline GLenum convertBlendFactor( BlendFactor factor ){ + switch ( factor ) + { + case BLEND_ZERO: + return GL_ZERO; + case BLEND_ONE: + return GL_ONE; + case BLEND_SRC_COLOUR: + return GL_SRC_COLOR; + case BLEND_ONE_MINUS_SRC_COLOUR: + return GL_ONE_MINUS_SRC_COLOR; + case BLEND_SRC_ALPHA: + return GL_SRC_ALPHA; + case BLEND_ONE_MINUS_SRC_ALPHA: + return GL_ONE_MINUS_SRC_ALPHA; + case BLEND_DST_COLOUR: + return GL_DST_COLOR; + case BLEND_ONE_MINUS_DST_COLOUR: + return GL_ONE_MINUS_DST_COLOR; + case BLEND_DST_ALPHA: + return GL_DST_ALPHA; + case BLEND_ONE_MINUS_DST_ALPHA: + return GL_ONE_MINUS_DST_ALPHA; + case BLEND_SRC_ALPHA_SATURATE: + return GL_SRC_ALPHA_SATURATE; + } + return GL_ZERO; } /// \todo Define special-case shaders in a data file. -void OpenGLShader::construct(const char *name) -{ - OpenGLState &state = appendDefaultPass(); - switch (name[0]) { - case '(': - sscanf(name, "(%g %g %g)", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]); - state.m_colour[3] = 1.0f; - state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | - RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - break; - - case '[': - sscanf(name, "[%g %g %g]", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]); - state.m_colour[3] = 0.5f; - state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | - RENDER_DEPTHWRITE | RENDER_BLEND; - state.m_sort = OpenGLState::eSortTranslucent; - break; - - case '<': - sscanf(name, "<%g %g %g>", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2]); - state.m_colour[3] = 1; - state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - state.m_depthfunc = GL_LESS; - state.m_linewidth = 1; - state.m_pointsize = 1; - break; - - case '$': { - OpenGLStateMap::iterator i = g_openglStates->find(name); - if (i != g_openglStates->end()) { - state = (*i).second; - break; - } - } - if (string_equal(name + 1, "POINT")) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortControlFirst; - state.m_pointsize = 4; - } else if (string_equal(name + 1, "SELPOINT")) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortControlFirst + 1; - state.m_pointsize = 4; - } else if (string_equal(name + 1, "BIGPOINT")) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortControlFirst; - state.m_pointsize = 6; - } else if (string_equal(name + 1, "PIVOT")) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortGUI1; - state.m_linewidth = 2; - state.m_depthfunc = GL_LEQUAL; - - OpenGLState &hiddenLine = appendDefaultPass(); - hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_LINESTIPPLE; - hiddenLine.m_sort = OpenGLState::eSortGUI0; - hiddenLine.m_linewidth = 2; - hiddenLine.m_depthfunc = GL_GREATER; - } else if (string_equal(name + 1, "LATTICE")) { - state.m_colour[0] = 1; - state.m_colour[1] = 0.5; - state.m_colour[2] = 0; - state.m_colour[3] = 1; - state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortControlFirst; - } else if (string_equal(name + 1, "WIREFRAME")) { - state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - } else if (string_equal(name + 1, "CAM_HIGHLIGHT")) { - state.m_colour[0] = 1; - state.m_colour[1] = 0; - state.m_colour[2] = 0; - state.m_colour[3] = 0.3f; - state.m_state = RENDER_FILL | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_BLEND | RENDER_COLOURWRITE | - RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortHighlight; - state.m_depthfunc = GL_LEQUAL; - } else if (string_equal(name + 1, "CAM_OVERLAY")) { +void OpenGLShader::construct( const char* name ){ + OpenGLState& state = appendDefaultPass(); + switch ( name[0] ) + { + case '(': + sscanf( name, "(%g %g %g)", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] ); + state.m_colour[3] = 1.0f; + state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + break; + + case '[': + sscanf( name, "[%g %g %g]", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] ); + state.m_colour[3] = 0.5f; + state.m_state = RENDER_FILL | RENDER_LIGHTING | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_BLEND; + state.m_sort = OpenGLState::eSortTranslucent; + break; + + case '<': + sscanf( name, "<%g %g %g>", &state.m_colour[0], &state.m_colour[1], &state.m_colour[2] ); + state.m_colour[3] = 1; + state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + state.m_depthfunc = GL_LESS; + state.m_linewidth = 1; + state.m_pointsize = 1; + break; + + case '$': + { + OpenGLStateMap::iterator i = g_openglStates->find( name ); + if ( i != g_openglStates->end() ) { + state = ( *i ).second; + break; + } + } + if ( string_equal( name + 1, "POINT" ) ) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortControlFirst; + state.m_pointsize = 4; + } + else if ( string_equal( name + 1, "SELPOINT" ) ) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortControlFirst + 1; + state.m_pointsize = 4; + } + else if ( string_equal( name + 1, "BIGPOINT" ) ) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortControlFirst; + state.m_pointsize = 6; + } + else if ( string_equal( name + 1, "PIVOT" ) ) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortGUI1; + state.m_linewidth = 2; + state.m_depthfunc = GL_LEQUAL; + + OpenGLState& hiddenLine = appendDefaultPass(); + hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHTEST | RENDER_LINESTIPPLE; + hiddenLine.m_sort = OpenGLState::eSortGUI0; + hiddenLine.m_linewidth = 2; + hiddenLine.m_depthfunc = GL_GREATER; + } + else if ( string_equal( name + 1, "LATTICE" ) ) { + state.m_colour[0] = 1; + state.m_colour[1] = 0.5; + state.m_colour[2] = 0; + state.m_colour[3] = 1; + state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortControlFirst; + } + else if ( string_equal( name + 1, "WIREFRAME" ) ) { + state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + } + else if ( string_equal( name + 1, "CAM_HIGHLIGHT" ) ) { + state.m_colour[0] = 1; + state.m_colour[1] = 0; + state.m_colour[2] = 0; + state.m_colour[3] = 0.3f; + state.m_state = RENDER_FILL | RENDER_DEPTHTEST | RENDER_CULLFACE | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortHighlight; + state.m_depthfunc = GL_LEQUAL; + } + else if ( string_equal( name + 1, "CAM_OVERLAY" ) ) { #if 0 - state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; state.m_sort = OpenGLState::eSortOverlayFirst; #else - state.m_state = - RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_OFFSETLINE; - state.m_sort = OpenGLState::eSortOverlayFirst + 1; - state.m_depthfunc = GL_LEQUAL; - - OpenGLState &hiddenLine = appendDefaultPass(); - hiddenLine.m_colour[0] = 0.75; - hiddenLine.m_colour[1] = 0.75; - hiddenLine.m_colour[2] = 0.75; - hiddenLine.m_colour[3] = 1; - hiddenLine.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_OFFSETLINE | - RENDER_LINESTIPPLE; - hiddenLine.m_sort = OpenGLState::eSortOverlayFirst; - hiddenLine.m_depthfunc = GL_GREATER; - hiddenLine.m_linestipple_factor = 2; + state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_OFFSETLINE; + state.m_sort = OpenGLState::eSortOverlayFirst + 1; + state.m_depthfunc = GL_LEQUAL; + + OpenGLState& hiddenLine = appendDefaultPass(); + hiddenLine.m_colour[0] = 0.75; + hiddenLine.m_colour[1] = 0.75; + hiddenLine.m_colour[2] = 0.75; + hiddenLine.m_colour[3] = 1; + hiddenLine.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_OFFSETLINE | RENDER_LINESTIPPLE; + hiddenLine.m_sort = OpenGLState::eSortOverlayFirst; + hiddenLine.m_depthfunc = GL_GREATER; + hiddenLine.m_linestipple_factor = 2; #endif - } else if (string_equal(name + 1, "XY_OVERLAY")) { - state.m_colour[0] = g_xywindow_globals.color_selbrushes[0]; - state.m_colour[1] = g_xywindow_globals.color_selbrushes[1]; - state.m_colour[2] = g_xywindow_globals.color_selbrushes[2]; - state.m_colour[3] = 1; - state.m_state = RENDER_COLOURWRITE | RENDER_LINESTIPPLE; - state.m_sort = OpenGLState::eSortOverlayFirst; - state.m_linewidth = 2; - state.m_linestipple_factor = 3; - } else if (string_equal(name + 1, "DEBUG_CLIPPED")) { - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortLast; - } else if (string_equal(name + 1, "POINTFILE")) { - state.m_colour[0] = 1; - state.m_colour[1] = 0; - state.m_colour[2] = 0; - state.m_colour[3] = 1; - state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - state.m_linewidth = 4; - } else if (string_equal(name + 1, "LIGHT_SPHERE")) { - state.m_colour[0] = .15f * .95f; - state.m_colour[1] = .15f * .95f; - state.m_colour[2] = .15f * .95f; - state.m_colour[3] = 1; - state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL | RENDER_COLOURWRITE | - RENDER_DEPTHWRITE; - state.m_blend_src = GL_ONE; - state.m_blend_dst = GL_ONE; - state.m_sort = OpenGLState::eSortTranslucent; - } else if (string_equal(name + 1, "Q3MAP2_LIGHT_SPHERE")) { - state.m_colour[0] = .05f; - state.m_colour[1] = .05f; - state.m_colour[2] = .05f; - state.m_colour[3] = 1; - state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL; - state.m_blend_src = GL_ONE; - state.m_blend_dst = GL_ONE; - state.m_sort = OpenGLState::eSortTranslucent; - } else if (string_equal(name + 1, "WIRE_OVERLAY")) { + } + else if ( string_equal( name + 1, "XY_OVERLAY" ) ) { + state.m_colour[0] = g_xywindow_globals.color_selbrushes[0]; + state.m_colour[1] = g_xywindow_globals.color_selbrushes[1]; + state.m_colour[2] = g_xywindow_globals.color_selbrushes[2]; + state.m_colour[3] = 1; + state.m_state = RENDER_COLOURWRITE | RENDER_LINESTIPPLE; + state.m_sort = OpenGLState::eSortOverlayFirst; + state.m_linewidth = 2; + state.m_linestipple_factor = 3; + } + else if ( string_equal( name + 1, "DEBUG_CLIPPED" ) ) { + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortLast; + } + else if ( string_equal( name + 1, "POINTFILE" ) ) { + state.m_colour[0] = 1; + state.m_colour[1] = 0; + state.m_colour[2] = 0; + state.m_colour[3] = 1; + state.m_state = RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + state.m_linewidth = 4; + } + else if ( string_equal( name + 1, "LIGHT_SPHERE" ) ) { + state.m_colour[0] = .15f * .95f; + state.m_colour[1] = .15f * .95f; + state.m_colour[2] = .15f * .95f; + state.m_colour[3] = 1; + state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_blend_src = GL_ONE; + state.m_blend_dst = GL_ONE; + state.m_sort = OpenGLState::eSortTranslucent; + } + else if ( string_equal( name + 1, "Q3MAP2_LIGHT_SPHERE" ) ) { + state.m_colour[0] = .05f; + state.m_colour[1] = .05f; + state.m_colour[2] = .05f; + state.m_colour[3] = 1; + state.m_state = RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_BLEND | RENDER_FILL; + state.m_blend_src = GL_ONE; + state.m_blend_dst = GL_ONE; + state.m_sort = OpenGLState::eSortTranslucent; + } + else if ( string_equal( name + 1, "WIRE_OVERLAY" ) ) { #if 0 - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; state.m_sort = OpenGLState::eSortOverlayFirst; #else - state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | - RENDER_OVERRIDE; - state.m_sort = OpenGLState::eSortGUI1; - state.m_depthfunc = GL_LEQUAL; - - OpenGLState &hiddenLine = appendDefaultPass(); - hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | - RENDER_OVERRIDE | RENDER_LINESTIPPLE; - hiddenLine.m_sort = OpenGLState::eSortGUI0; - hiddenLine.m_depthfunc = GL_GREATER; + state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; + state.m_sort = OpenGLState::eSortGUI1; + state.m_depthfunc = GL_LEQUAL; + + OpenGLState& hiddenLine = appendDefaultPass(); + hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_LINESTIPPLE; + hiddenLine.m_sort = OpenGLState::eSortGUI0; + hiddenLine.m_depthfunc = GL_GREATER; #endif - } else if (string_equal(name + 1, "FLATSHADE_OVERLAY")) { - state.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | - RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | - RENDER_OVERRIDE; - state.m_sort = OpenGLState::eSortGUI1; - state.m_depthfunc = GL_LEQUAL; - - OpenGLState &hiddenLine = appendDefaultPass(); - hiddenLine.m_state = - RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | - RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | - RENDER_POLYGONSTIPPLE; - hiddenLine.m_sort = OpenGLState::eSortGUI0; - hiddenLine.m_depthfunc = GL_GREATER; - } else if (string_equal(name + 1, "CLIPPER_OVERLAY")) { - state.m_colour[0] = g_xywindow_globals.color_clipper[0]; - state.m_colour[1] = g_xywindow_globals.color_clipper[1]; - state.m_colour[2] = g_xywindow_globals.color_clipper[2]; - state.m_colour[3] = 1; - state.m_state = - RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_FILL | RENDER_POLYGONSTIPPLE; - state.m_sort = OpenGLState::eSortOverlayFirst; - } else if (string_equal(name + 1, "OVERBRIGHT")) { - const float lightScale = 2; - state.m_colour[0] = lightScale * 0.5f; - state.m_colour[1] = lightScale * 0.5f; - state.m_colour[2] = lightScale * 0.5f; - state.m_colour[3] = 0.5; - state.m_state = RENDER_FILL | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_SCREEN; - state.m_sort = OpenGLState::eSortOverbrighten; - state.m_blend_src = GL_DST_COLOR; - state.m_blend_dst = GL_SRC_COLOR; - } else { - // default to something recognisable.. =) - ERROR_MESSAGE("hardcoded renderstate not found"); - state.m_colour[0] = 1; - state.m_colour[1] = 0; - state.m_colour[2] = 1; - state.m_colour[3] = 1; - state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFirst; - } - break; - default: - // construction from IShader - m_shader = QERApp_Shader_ForName(name); - - if (g_ShaderCache->lightingSupported() && g_ShaderCache->lightingEnabled() && m_shader->getBump() != 0 && - m_shader->getBump()->texture_number != 0) { // is a bump shader - state.m_state = RENDER_FILL | RENDER_CULLFACE | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE | - RENDER_COLOURWRITE | RENDER_PROGRAM; - state.m_colour[0] = 0; - state.m_colour[1] = 0; - state.m_colour[2] = 0; - state.m_colour[3] = 1; - state.m_sort = OpenGLState::eSortOpaque; - - if (g_ShaderCache->useShaderLanguage()) { - state.m_program = &g_depthFillGLSL; - } else { - state.m_program = &g_depthFillARB; - } - - OpenGLState &bumpPass = appendDefaultPass(); - bumpPass.m_texture = m_shader->getDiffuse()->texture_number; - bumpPass.m_texture1 = m_shader->getBump()->texture_number; - bumpPass.m_texture2 = m_shader->getSpecular()->texture_number; - - bumpPass.m_state = - RENDER_BLEND | RENDER_FILL | RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | - RENDER_SMOOTH | RENDER_BUMP | RENDER_PROGRAM; - - if (g_ShaderCache->useShaderLanguage()) { - bumpPass.m_state |= RENDER_LIGHTING; - bumpPass.m_program = &g_bumpGLSL; - } else { - bumpPass.m_program = &g_bumpARB; - } - - bumpPass.m_depthfunc = GL_LEQUAL; - bumpPass.m_sort = OpenGLState::eSortMultiFirst; - bumpPass.m_blend_src = GL_ONE; - bumpPass.m_blend_dst = GL_ONE; - } else { - state.m_texture = m_shader->getTexture()->texture_number; - - state.m_state = RENDER_FILL | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_LIGHTING | - RENDER_SMOOTH; - if ((m_shader->getFlags() & QER_CULL) != 0) { - if (m_shader->getCull() == IShader::eCullBack) { - state.m_state |= RENDER_CULLFACE; - } - } else { - state.m_state |= RENDER_CULLFACE; - } - if ((m_shader->getFlags() & QER_ALPHATEST) != 0) { - state.m_state |= RENDER_ALPHATEST; - IShader::EAlphaFunc alphafunc; - m_shader->getAlphaFunc(&alphafunc, &state.m_alpharef); - switch (alphafunc) { - case IShader::eAlways: - state.m_alphafunc = GL_ALWAYS; - break; - case IShader::eEqual: - state.m_alphafunc = GL_EQUAL; - break; - case IShader::eLess: - state.m_alphafunc = GL_LESS; - break; - case IShader::eGreater: - state.m_alphafunc = GL_GREATER; - break; - case IShader::eLEqual: - state.m_alphafunc = GL_LEQUAL; - break; - case IShader::eGEqual: - state.m_alphafunc = GL_GEQUAL; - break; - } - } - reinterpret_cast( state.m_colour ) = m_shader->getTexture()->color; - state.m_colour[3] = 1.0f; - - if ((m_shader->getFlags() & QER_TRANS) != 0) { - state.m_state |= RENDER_BLEND; - state.m_colour[3] = m_shader->getTrans(); - state.m_sort = OpenGLState::eSortTranslucent; - BlendFunc blendFunc = m_shader->getBlendFunc(); - state.m_blend_src = convertBlendFactor(blendFunc.m_src); - state.m_blend_dst = convertBlendFactor(blendFunc.m_dst); - if (state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA) { - state.m_state |= RENDER_DEPTHWRITE; - } - } else { - state.m_state |= RENDER_DEPTHWRITE; - state.m_sort = OpenGLState::eSortFullbright; - } - } - } + } + else if ( string_equal( name + 1, "FLATSHADE_OVERLAY" ) ) { + state.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE; + state.m_sort = OpenGLState::eSortGUI1; + state.m_depthfunc = GL_LEQUAL; + + OpenGLState& hiddenLine = appendDefaultPass(); + hiddenLine.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_POLYGONSTIPPLE; + hiddenLine.m_sort = OpenGLState::eSortGUI0; + hiddenLine.m_depthfunc = GL_GREATER; + } + else if ( string_equal( name + 1, "CLIPPER_OVERLAY" ) ) { + state.m_colour[0] = g_xywindow_globals.color_clipper[0]; + state.m_colour[1] = g_xywindow_globals.color_clipper[1]; + state.m_colour[2] = g_xywindow_globals.color_clipper[2]; + state.m_colour[3] = 1; + state.m_state = RENDER_CULLFACE | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_FILL | RENDER_POLYGONSTIPPLE; + state.m_sort = OpenGLState::eSortOverlayFirst; + } + else if ( string_equal( name + 1, "OVERBRIGHT" ) ) { + const float lightScale = 2; + state.m_colour[0] = lightScale * 0.5f; + state.m_colour[1] = lightScale * 0.5f; + state.m_colour[2] = lightScale * 0.5f; + state.m_colour[3] = 0.5; + state.m_state = RENDER_FILL | RENDER_BLEND | RENDER_COLOURWRITE | RENDER_SCREEN; + state.m_sort = OpenGLState::eSortOverbrighten; + state.m_blend_src = GL_DST_COLOR; + state.m_blend_dst = GL_SRC_COLOR; + } + else + { + // default to something recognisable.. =) + ERROR_MESSAGE( "hardcoded renderstate not found" ); + state.m_colour[0] = 1; + state.m_colour[1] = 0; + state.m_colour[2] = 1; + state.m_colour[3] = 1; + state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFirst; + } + break; + default: + // construction from IShader + m_shader = QERApp_Shader_ForName( name ); + + if ( g_ShaderCache->lightingSupported() && g_ShaderCache->lightingEnabled() && m_shader->getBump() != 0 && m_shader->getBump()->texture_number != 0 ) { // is a bump shader + state.m_state = RENDER_FILL | RENDER_CULLFACE | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_DEPTHWRITE | RENDER_COLOURWRITE | RENDER_PROGRAM; + state.m_colour[0] = 0; + state.m_colour[1] = 0; + state.m_colour[2] = 0; + state.m_colour[3] = 1; + state.m_sort = OpenGLState::eSortOpaque; + + if ( g_ShaderCache->useShaderLanguage() ) { + state.m_program = &g_depthFillGLSL; + } + else + { + state.m_program = &g_depthFillARB; + } + + OpenGLState& bumpPass = appendDefaultPass(); + bumpPass.m_texture = m_shader->getDiffuse()->texture_number; + bumpPass.m_texture1 = m_shader->getBump()->texture_number; + bumpPass.m_texture2 = m_shader->getSpecular()->texture_number; + + bumpPass.m_state = RENDER_BLEND | RENDER_FILL | RENDER_CULLFACE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_SMOOTH | RENDER_BUMP | RENDER_PROGRAM; + + if ( g_ShaderCache->useShaderLanguage() ) { + bumpPass.m_state |= RENDER_LIGHTING; + bumpPass.m_program = &g_bumpGLSL; + } + else + { + bumpPass.m_program = &g_bumpARB; + } + + bumpPass.m_depthfunc = GL_LEQUAL; + bumpPass.m_sort = OpenGLState::eSortMultiFirst; + bumpPass.m_blend_src = GL_ONE; + bumpPass.m_blend_dst = GL_ONE; + } + else + { + state.m_texture = m_shader->getTexture()->texture_number; + + state.m_state = RENDER_FILL | RENDER_TEXTURE | RENDER_DEPTHTEST | RENDER_COLOURWRITE | RENDER_LIGHTING | RENDER_SMOOTH; + if ( ( m_shader->getFlags() & QER_CULL ) != 0 ) { + if ( m_shader->getCull() == IShader::eCullBack ) { + state.m_state |= RENDER_CULLFACE; + } + } + else + { + state.m_state |= RENDER_CULLFACE; + } + if ( ( m_shader->getFlags() & QER_ALPHATEST ) != 0 ) { + state.m_state |= RENDER_ALPHATEST; + IShader::EAlphaFunc alphafunc; + m_shader->getAlphaFunc( &alphafunc, &state.m_alpharef ); + switch ( alphafunc ) + { + case IShader::eAlways: + state.m_alphafunc = GL_ALWAYS; + break; + case IShader::eEqual: + state.m_alphafunc = GL_EQUAL; + break; + case IShader::eLess: + state.m_alphafunc = GL_LESS; + break; + case IShader::eGreater: + state.m_alphafunc = GL_GREATER; + break; + case IShader::eLEqual: + state.m_alphafunc = GL_LEQUAL; + break; + case IShader::eGEqual: + state.m_alphafunc = GL_GEQUAL; + break; + } + } + reinterpret_cast( state.m_colour ) = m_shader->getTexture()->color; + state.m_colour[3] = 1.0f; + + if ( ( m_shader->getFlags() & QER_TRANS ) != 0 ) { + state.m_state |= RENDER_BLEND; + state.m_colour[3] = m_shader->getTrans(); + state.m_sort = OpenGLState::eSortTranslucent; + BlendFunc blendFunc = m_shader->getBlendFunc(); + state.m_blend_src = convertBlendFactor( blendFunc.m_src ); + state.m_blend_dst = convertBlendFactor( blendFunc.m_dst ); + if ( state.m_blend_src == GL_SRC_ALPHA || state.m_blend_dst == GL_SRC_ALPHA ) { + state.m_state |= RENDER_DEPTHWRITE; + } + } + else + { + state.m_state |= RENDER_DEPTHWRITE; + state.m_sort = OpenGLState::eSortFullbright; + } + } + } } #include "modulesystem/singletonmodule.h" #include "modulesystem/moduleregistry.h" -class OpenGLStateLibraryAPI { - OpenGLStateMap m_stateMap; +class OpenGLStateLibraryAPI +{ +OpenGLStateMap m_stateMap; public: - typedef OpenGLStateLibrary Type; +typedef OpenGLStateLibrary Type; - STRING_CONSTANT(Name, "*"); +STRING_CONSTANT( Name, "*" ); - OpenGLStateLibraryAPI() - { - g_openglStates = &m_stateMap; - } +OpenGLStateLibraryAPI(){ + g_openglStates = &m_stateMap; +} - ~OpenGLStateLibraryAPI() - { - g_openglStates = 0; - } +~OpenGLStateLibraryAPI(){ + g_openglStates = 0; +} - OpenGLStateLibrary *getTable() - { - return &m_stateMap; - } +OpenGLStateLibrary* getTable(){ + return &m_stateMap; +} }; typedef SingletonModule OpenGLStateLibraryModule; typedef Static StaticOpenGLStateLibraryModule; -StaticRegisterModule staticRegisterOpenGLStateLibrary(StaticOpenGLStateLibraryModule::instance()); +StaticRegisterModule staticRegisterOpenGLStateLibrary( StaticOpenGLStateLibraryModule::instance() ); -class ShaderCacheDependencies - : public GlobalShadersModuleRef, public GlobalTexturesModuleRef, public GlobalOpenGLStateLibraryModuleRef { +class ShaderCacheDependencies : public GlobalShadersModuleRef, public GlobalTexturesModuleRef, public GlobalOpenGLStateLibraryModuleRef +{ public: - ShaderCacheDependencies() : - GlobalShadersModuleRef(GlobalRadiant().getRequiredGameDescriptionKeyValue("shaders")) - { - } +ShaderCacheDependencies() : + GlobalShadersModuleRef( GlobalRadiant().getRequiredGameDescriptionKeyValue( "shaders" ) ){ +} }; -class ShaderCacheAPI { - ShaderCache *m_shaderCache; +class ShaderCacheAPI +{ +ShaderCache* m_shaderCache; public: - typedef ShaderCache Type; +typedef ShaderCache Type; - STRING_CONSTANT(Name, "*"); +STRING_CONSTANT( Name, "*" ); - ShaderCacheAPI() - { - ShaderCache_Construct(); +ShaderCacheAPI(){ + ShaderCache_Construct(); - m_shaderCache = GetShaderCache(); - } + m_shaderCache = GetShaderCache(); +} - ~ShaderCacheAPI() - { - ShaderCache_Destroy(); - } +~ShaderCacheAPI(){ + ShaderCache_Destroy(); +} - ShaderCache *getTable() - { - return m_shaderCache; - } +ShaderCache* getTable(){ + return m_shaderCache; +} }; typedef SingletonModule ShaderCacheModule; typedef Static StaticShaderCacheModule; -StaticRegisterModule staticRegisterShaderCache(StaticShaderCacheModule::instance()); +StaticRegisterModule staticRegisterShaderCache( StaticShaderCacheModule::instance() ); diff --git a/radiant/texwindow.cpp b/radiant/texwindow.cpp index 51903700..87094456 100644 --- a/radiant/texwindow.cpp +++ b/radiant/texwindow.cpp @@ -31,7 +31,7 @@ #include "debugging/debugging.h" #include "warnings.h" - + #include "defaults.h" #include "ifilesystem.h" #include "iundo.h" @@ -87,148 +87,136 @@ #include "shaders.h" #include "commands.h" -bool TextureBrowser_showWads() -{ - return !string_empty(g_pGameDescription->getKeyValue("show_wads")); +bool TextureBrowser_showWads(){ + return !string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ); } -void TextureBrowser_queueDraw(TextureBrowser &textureBrowser); +void TextureBrowser_queueDraw( TextureBrowser& textureBrowser ); -bool string_equal_start(const char *string, StringRange start) -{ - return string_equal_n(string, start.first, start.last - start.first); +bool string_equal_start( const char* string, StringRange start ){ + return string_equal_n( string, start.first, start.last - start.first ); } typedef std::set TextureGroups; -void TextureGroups_addWad(TextureGroups &groups, const char *archive) -{ - if (extension_equal(path_get_extension(archive), "wad")) { +void TextureGroups_addWad( TextureGroups& groups, const char* archive ){ + if ( extension_equal( path_get_extension( archive ), "wad" ) ) { #if 1 - groups.insert(archive); + groups.insert( archive ); #else - CopiedString archiveBaseName( path_get_filename_start( archive ), path_get_filename_base_end( archive ) ); + CopiedString archiveBaseName( path_get_filename_start( archive ), path_get_filename_base_end( archive ) ); groups.insert( archiveBaseName ); #endif - } + } } -typedef ReferenceCaller TextureGroupsAddWadCaller; +typedef ReferenceCaller TextureGroupsAddWadCaller; -namespace { - bool g_TextureBrowser_shaderlistOnly = false; - bool g_TextureBrowser_fixedSize = true; - bool g_TextureBrowser_filterMissing = false; - bool g_TextureBrowser_filterFallback = true; - bool g_TextureBrowser_enableAlpha = true; +namespace +{ +bool g_TextureBrowser_shaderlistOnly = false; +bool g_TextureBrowser_fixedSize = true; +bool g_TextureBrowser_filterMissing = false; +bool g_TextureBrowser_filterFallback = true; +bool g_TextureBrowser_enableAlpha = true; } CopiedString g_notex; CopiedString g_shadernotex; -bool isMissing(const char *name); +bool isMissing(const char* name); -bool isNotex(const char *name); +bool isNotex(const char* name); -bool isMissing(const char *name) -{ - if (string_equal(g_notex.c_str(), name)) { - return true; - } - if (string_equal(g_shadernotex.c_str(), name)) { - return true; - } - return false; +bool isMissing(const char* name){ + if ( string_equal( g_notex.c_str(), name ) ) { + return true; + } + if ( string_equal( g_shadernotex.c_str(), name ) ) { + return true; + } + return false; } -bool isNotex(const char *name) -{ - if (string_equal_suffix(name, "/" DEFAULT_NOTEX_BASENAME)) { - return true; - } - if (string_equal_suffix(name, "/" DEFAULT_SHADERNOTEX_BASENAME)) { - return true; - } - return false; +bool isNotex(const char* name){ + if ( string_equal_suffix( name, "/" DEFAULT_NOTEX_BASENAME ) ) { + return true; + } + if ( string_equal_suffix( name, "/" DEFAULT_SHADERNOTEX_BASENAME ) ) { + return true; + } + return false; } -void TextureGroups_addShader(TextureGroups &groups, const char *shaderName) -{ - const char *texture = path_make_relative(shaderName, "textures/"); +void TextureGroups_addShader( TextureGroups& groups, const char* shaderName ){ + const char* texture = path_make_relative( shaderName, "textures/" ); - // hide notex / shadernotex images - if (g_TextureBrowser_filterFallback) { - if (isNotex(shaderName)) { - return; - } - if (isNotex(texture)) { - return; - } - } + // hide notex / shadernotex images + if ( g_TextureBrowser_filterFallback ) { + if ( isNotex( shaderName ) ) { + return; + } + if ( isNotex( texture ) ) { + return; + } + } - if (texture != shaderName) { - const char *last = path_remove_directory(texture); - if (!string_empty(last)) { - groups.insert(CopiedString(StringRange(texture, --last))); - } - } + if ( texture != shaderName ) { + const char* last = path_remove_directory( texture ); + if ( !string_empty( last ) ) { + groups.insert( CopiedString( StringRange( texture, --last ) ) ); + } + } } -typedef ReferenceCaller TextureGroupsAddShaderCaller; +typedef ReferenceCaller TextureGroupsAddShaderCaller; -void TextureGroups_addDirectory(TextureGroups &groups, const char *directory) -{ - groups.insert(directory); +void TextureGroups_addDirectory( TextureGroups& groups, const char* directory ){ + groups.insert( directory ); } +typedef ReferenceCaller TextureGroupsAddDirectoryCaller; -typedef ReferenceCaller TextureGroupsAddDirectoryCaller; - -class DeferredAdjustment { - gdouble m_value; - guint m_handler; +class DeferredAdjustment +{ +gdouble m_value; +guint m_handler; - typedef void ( *ValueChangedFunction )(void *data, gdouble value); +typedef void ( *ValueChangedFunction )( void* data, gdouble value ); - ValueChangedFunction m_function; - void *m_data; +ValueChangedFunction m_function; +void* m_data; - static gboolean deferred_value_changed(gpointer data) - { - reinterpret_cast( data )->m_function( - reinterpret_cast( data )->m_data, - reinterpret_cast( data )->m_value - ); - reinterpret_cast( data )->m_handler = 0; - reinterpret_cast( data )->m_value = 0; - return FALSE; - } +static gboolean deferred_value_changed( gpointer data ){ + reinterpret_cast( data )->m_function( + reinterpret_cast( data )->m_data, + reinterpret_cast( data )->m_value + ); + reinterpret_cast( data )->m_handler = 0; + reinterpret_cast( data )->m_value = 0; + return FALSE; +} public: - DeferredAdjustment(ValueChangedFunction function, void *data) : m_value(0), m_handler(0), m_function(function), - m_data(data) - { - } - - void flush() - { - if (m_handler != 0) { - g_source_remove(m_handler); - deferred_value_changed(this); - } - } - - void value_changed(gdouble value) - { - m_value = value; - if (m_handler == 0) { - m_handler = g_idle_add(deferred_value_changed, this); - } - } - - static void adjustment_value_changed(ui::Adjustment adjustment, DeferredAdjustment *self) - { - self->value_changed(gtk_adjustment_get_value(adjustment)); - } +DeferredAdjustment( ValueChangedFunction function, void* data ) : m_value( 0 ), m_handler( 0 ), m_function( function ), m_data( data ){ +} + +void flush(){ + if ( m_handler != 0 ) { + g_source_remove( m_handler ); + deferred_value_changed( this ); + } +} + +void value_changed( gdouble value ){ + m_value = value; + if ( m_handler == 0 ) { + m_handler = g_idle_add( deferred_value_changed, this ); + } +} + +static void adjustment_value_changed(ui::Adjustment adjustment, DeferredAdjustment* self ){ + self->value_changed( gtk_adjustment_get_value(adjustment) ); +} }; @@ -236,239 +224,234 @@ class TextureBrowser; typedef ReferenceCaller TextureBrowserQueueDrawCaller; -void TextureBrowser_scrollChanged(void *data, gdouble value); +void TextureBrowser_scrollChanged( void* data, gdouble value ); -enum StartupShaders { - STARTUPSHADERS_NONE = 0, - STARTUPSHADERS_COMMON, +enum StartupShaders +{ + STARTUPSHADERS_NONE = 0, + STARTUPSHADERS_COMMON, }; -void TextureBrowser_hideUnusedExport(const Callback &importer); +void TextureBrowser_hideUnusedExport( const Callback & importer ); typedef FreeCaller &), TextureBrowser_hideUnusedExport> TextureBrowserHideUnusedExport; -void TextureBrowser_showShadersExport(const Callback &importer); +void TextureBrowser_showShadersExport( const Callback & importer ); -typedef FreeCaller &), TextureBrowser_showShadersExport> TextureBrowserShowShadersExport; +typedef FreeCaller &), TextureBrowser_showShadersExport> TextureBrowserShowShadersExport; -void TextureBrowser_showShaderlistOnly(const Callback &importer); +void TextureBrowser_showShaderlistOnly( const Callback & importer ); -typedef FreeCaller &), TextureBrowser_showShaderlistOnly> TextureBrowserShowShaderlistOnlyExport; +typedef FreeCaller &), TextureBrowser_showShaderlistOnly> TextureBrowserShowShaderlistOnlyExport; -void TextureBrowser_fixedSize(const Callback &importer); +void TextureBrowser_fixedSize( const Callback & importer ); typedef FreeCaller &), TextureBrowser_fixedSize> TextureBrowserFixedSizeExport; -void TextureBrowser_filterMissing(const Callback &importer); +void TextureBrowser_filterMissing( const Callback & importer ); typedef FreeCaller &), TextureBrowser_filterMissing> TextureBrowserFilterMissingExport; -void TextureBrowser_filterFallback(const Callback &importer); +void TextureBrowser_filterFallback( const Callback & importer ); -typedef FreeCaller &), TextureBrowser_filterFallback> TextureBrowserFilterFallbackExport; +typedef FreeCaller &), TextureBrowser_filterFallback> TextureBrowserFilterFallbackExport; -void TextureBrowser_enableAlpha(const Callback &importer); +void TextureBrowser_enableAlpha( const Callback & importer ); typedef FreeCaller &), TextureBrowser_enableAlpha> TextureBrowserEnableAlphaExport; -class TextureBrowser { +class TextureBrowser +{ public: - int width, height; - int originy; - int m_nTotalHeight; - - CopiedString shader; - - ui::Window m_parent{ui::null}; - ui::GLArea m_gl_widget{ui::null}; - ui::Widget m_texture_scroll{ui::null}; - ui::TreeView m_treeViewTree{ui::New}; - ui::TreeView m_treeViewTags{ui::null}; - ui::Frame m_tag_frame{ui::null}; - ui::ListStore m_assigned_store{ui::null}; - ui::ListStore m_available_store{ui::null}; - ui::TreeView m_assigned_tree{ui::null}; - ui::TreeView m_available_tree{ui::null}; - ui::Widget m_scr_win_tree{ui::null}; - ui::Widget m_scr_win_tags{ui::null}; - ui::Widget m_tag_notebook{ui::null}; - ui::Button m_search_button{ui::null}; - ui::Widget m_shader_info_item{ui::null}; - - std::set m_all_tags; - ui::ListStore m_all_tags_list{ui::null}; - std::vector m_copied_tags; - std::set m_found_shaders; - - ToggleItem m_hideunused_item; - ToggleItem m_hidenotex_item; - ToggleItem m_showshaders_item; - ToggleItem m_showshaderlistonly_item; - ToggleItem m_fixedsize_item; - ToggleItem m_filternotex_item; - ToggleItem m_enablealpha_item; - - guint m_sizeHandler; - guint m_exposeHandler; - - bool m_heightChanged; - bool m_originInvalid; - - DeferredAdjustment m_scrollAdjustment; - FreezePointer m_freezePointer; - - Vector3 color_textureback; +int width, height; +int originy; +int m_nTotalHeight; + +CopiedString shader; + +ui::Window m_parent{ui::null}; +ui::GLArea m_gl_widget{ui::null}; +ui::Widget m_texture_scroll{ui::null}; +ui::TreeView m_treeViewTree{ui::New}; +ui::TreeView m_treeViewTags{ui::null}; +ui::Frame m_tag_frame{ui::null}; +ui::ListStore m_assigned_store{ui::null}; +ui::ListStore m_available_store{ui::null}; +ui::TreeView m_assigned_tree{ui::null}; +ui::TreeView m_available_tree{ui::null}; +ui::Widget m_scr_win_tree{ui::null}; +ui::Widget m_scr_win_tags{ui::null}; +ui::Widget m_tag_notebook{ui::null}; +ui::Button m_search_button{ui::null}; +ui::Widget m_shader_info_item{ui::null}; + +std::set m_all_tags; +ui::ListStore m_all_tags_list{ui::null}; +std::vector m_copied_tags; +std::set m_found_shaders; + +ToggleItem m_hideunused_item; +ToggleItem m_hidenotex_item; +ToggleItem m_showshaders_item; +ToggleItem m_showshaderlistonly_item; +ToggleItem m_fixedsize_item; +ToggleItem m_filternotex_item; +ToggleItem m_enablealpha_item; + +guint m_sizeHandler; +guint m_exposeHandler; + +bool m_heightChanged; +bool m_originInvalid; + +DeferredAdjustment m_scrollAdjustment; +FreezePointer m_freezePointer; + +Vector3 color_textureback; // the increment step we use against the wheel mouse - std::size_t m_mouseWheelScrollIncrement; - std::size_t m_textureScale; +std::size_t m_mouseWheelScrollIncrement; +std::size_t m_textureScale; // make the texture increments match the grid changes - bool m_showShaders; - bool m_showTextureScrollbar; - StartupShaders m_startupShaders; +bool m_showShaders; +bool m_showTextureScrollbar; +StartupShaders m_startupShaders; // if true, the texture window will only display in-use shaders // if false, all the shaders in memory are displayed - bool m_hideUnused; - bool m_rmbSelected; - bool m_searchedTags; - bool m_tags; +bool m_hideUnused; +bool m_rmbSelected; +bool m_searchedTags; +bool m_tags; // The uniform size (in pixels) that textures are resized to when m_resizeTextures is true. - int m_uniformTextureSize; +int m_uniformTextureSize; // Return the display width of a texture in the texture browser - int getTextureWidth(qtexture_t *tex) - { - int width; - if (!g_TextureBrowser_fixedSize) { - // Don't use uniform size - width = (int) (tex->width * ((float) m_textureScale / 100)); - } else if - (tex->width >= tex->height) { - // Texture is square, or wider than it is tall - width = m_uniformTextureSize; - } else { - // Otherwise, preserve the texture's aspect ratio - width = (int) (m_uniformTextureSize * ((float) tex->width / tex->height)); - } - return width; - } +int getTextureWidth( qtexture_t* tex ){ + int width; + if ( !g_TextureBrowser_fixedSize ) { + // Don't use uniform size + width = (int)( tex->width * ( (float)m_textureScale / 100 ) ); + } + else if + ( tex->width >= tex->height ) { + // Texture is square, or wider than it is tall + width = m_uniformTextureSize; + } + else { + // Otherwise, preserve the texture's aspect ratio + width = (int)( m_uniformTextureSize * ( (float)tex->width / tex->height ) ); + } + return width; +} // Return the display height of a texture in the texture browser - int getTextureHeight(qtexture_t *tex) - { - int height; - if (!g_TextureBrowser_fixedSize) { - // Don't use uniform size - height = (int) (tex->height * ((float) m_textureScale / 100)); - } else if (tex->height >= tex->width) { - // Texture is square, or taller than it is wide - height = m_uniformTextureSize; - } else { - // Otherwise, preserve the texture's aspect ratio - height = (int) (m_uniformTextureSize * ((float) tex->height / tex->width)); - } - return height; - } - - TextureBrowser() : - m_texture_scroll(ui::null), - m_hideunused_item(TextureBrowserHideUnusedExport()), - m_hidenotex_item(TextureBrowserFilterFallbackExport()), - m_showshaders_item(TextureBrowserShowShadersExport()), - m_showshaderlistonly_item(TextureBrowserShowShaderlistOnlyExport()), - m_fixedsize_item(TextureBrowserFixedSizeExport()), - m_filternotex_item(TextureBrowserFilterMissingExport()), - m_enablealpha_item(TextureBrowserEnableAlphaExport()), - m_heightChanged(true), - m_originInvalid(true), - m_scrollAdjustment(TextureBrowser_scrollChanged, this), - color_textureback(0.25f, 0.25f, 0.25f), - m_mouseWheelScrollIncrement(64), - m_textureScale(50), - m_showShaders(true), - m_showTextureScrollbar(true), - m_startupShaders(STARTUPSHADERS_NONE), - m_hideUnused(false), - m_rmbSelected(false), - m_searchedTags(false), - m_tags(false), - m_uniformTextureSize(96) - { - } +int getTextureHeight( qtexture_t* tex ){ + int height; + if ( !g_TextureBrowser_fixedSize ) { + // Don't use uniform size + height = (int)( tex->height * ( (float)m_textureScale / 100 ) ); + } + else if ( tex->height >= tex->width ) { + // Texture is square, or taller than it is wide + height = m_uniformTextureSize; + } + else { + // Otherwise, preserve the texture's aspect ratio + height = (int)( m_uniformTextureSize * ( (float)tex->height / tex->width ) ); + } + return height; +} + +TextureBrowser() : + m_texture_scroll( ui::null ), + m_hideunused_item( TextureBrowserHideUnusedExport() ), + m_hidenotex_item( TextureBrowserFilterFallbackExport() ), + m_showshaders_item( TextureBrowserShowShadersExport() ), + m_showshaderlistonly_item( TextureBrowserShowShaderlistOnlyExport() ), + m_fixedsize_item( TextureBrowserFixedSizeExport() ), + m_filternotex_item( TextureBrowserFilterMissingExport() ), + m_enablealpha_item( TextureBrowserEnableAlphaExport() ), + m_heightChanged( true ), + m_originInvalid( true ), + m_scrollAdjustment( TextureBrowser_scrollChanged, this ), + color_textureback( 0.25f, 0.25f, 0.25f ), + m_mouseWheelScrollIncrement( 64 ), + m_textureScale( 50 ), + m_showShaders( true ), + m_showTextureScrollbar( true ), + m_startupShaders( STARTUPSHADERS_NONE ), + m_hideUnused( false ), + m_rmbSelected( false ), + m_searchedTags( false ), + m_tags( false ), + m_uniformTextureSize( 96 ){ +} }; -void ( *TextureBrowser_textureSelected )(const char *shader); +void ( *TextureBrowser_textureSelected )( const char* shader ); -void TextureBrowser_updateScroll(TextureBrowser &textureBrowser); +void TextureBrowser_updateScroll( TextureBrowser& textureBrowser ); -const char *TextureBrowser_getComonShadersName() -{ - const char *value = g_pGameDescription->getKeyValue("common_shaders_name"); - if (!string_empty(value)) { - return value; - } - return "Common"; +const char* TextureBrowser_getComonShadersName(){ + const char* value = g_pGameDescription->getKeyValue( "common_shaders_name" ); + if ( !string_empty( value ) ) { + return value; + } + return "Common"; } -const char *TextureBrowser_getComonShadersDir() -{ - const char *value = g_pGameDescription->getKeyValue("common_shaders_dir"); - if (!string_empty(value)) { - return value; - } - return "common/"; +const char* TextureBrowser_getComonShadersDir(){ + const char* value = g_pGameDescription->getKeyValue( "common_shaders_dir" ); + if ( !string_empty( value ) ) { + return value; + } + return "common/"; } -inline int TextureBrowser_fontHeight(TextureBrowser &textureBrowser) -{ - return GlobalOpenGL().m_font->getPixelHeight(); +inline int TextureBrowser_fontHeight( TextureBrowser& textureBrowser ){ + return GlobalOpenGL().m_font->getPixelHeight(); } -const char *TextureBrowser_GetSelectedShader(TextureBrowser &textureBrowser) -{ - return textureBrowser.shader.c_str(); +const char* TextureBrowser_GetSelectedShader( TextureBrowser& textureBrowser ){ + return textureBrowser.shader.c_str(); } -void TextureBrowser_SetStatus(TextureBrowser &textureBrowser, const char *name) -{ - IShader *shader = QERApp_Shader_ForName(name); - qtexture_t *q = shader->getTexture(); - StringOutputStream strTex(256); - strTex << name << " W: " << Unsigned(q->width) << " H: " << Unsigned(q->height); - shader->DecRef(); - g_pParentWnd->SetStatusText(g_pParentWnd->m_texture_status, strTex.c_str()); +void TextureBrowser_SetStatus( TextureBrowser& textureBrowser, const char* name ){ + IShader* shader = QERApp_Shader_ForName( name ); + qtexture_t* q = shader->getTexture(); + StringOutputStream strTex( 256 ); + strTex << name << " W: " << Unsigned( q->width ) << " H: " << Unsigned( q->height ); + shader->DecRef(); + g_pParentWnd->SetStatusText( g_pParentWnd->m_texture_status, strTex.c_str() ); } -void TextureBrowser_Focus(TextureBrowser &textureBrowser, const char *name); +void TextureBrowser_Focus( TextureBrowser& textureBrowser, const char* name ); -void TextureBrowser_SetSelectedShader(TextureBrowser &textureBrowser, const char *shader) -{ - textureBrowser.shader = shader; - TextureBrowser_SetStatus(textureBrowser, shader); - TextureBrowser_Focus(textureBrowser, shader); +void TextureBrowser_SetSelectedShader( TextureBrowser& textureBrowser, const char* shader ){ + textureBrowser.shader = shader; + TextureBrowser_SetStatus( textureBrowser, shader ); + TextureBrowser_Focus( textureBrowser, shader ); - if (FindTextureDialog_isOpen()) { - FindTextureDialog_selectTexture(shader); - } + if ( FindTextureDialog_isOpen() ) { + FindTextureDialog_selectTexture( shader ); + } - // disable the menu item "shader info" if no shader was selected - IShader *ishader = QERApp_Shader_ForName(shader); - CopiedString filename = ishader->getShaderFileName(); + // disable the menu item "shader info" if no shader was selected + IShader* ishader = QERApp_Shader_ForName( shader ); + CopiedString filename = ishader->getShaderFileName(); - if (filename.empty()) { - if (textureBrowser.m_shader_info_item != NULL) { - gtk_widget_set_sensitive(textureBrowser.m_shader_info_item, FALSE); - } - } else { - gtk_widget_set_sensitive(textureBrowser.m_shader_info_item, TRUE); - } + if ( filename.empty() ) { + if ( textureBrowser.m_shader_info_item != NULL ) { + gtk_widget_set_sensitive( textureBrowser.m_shader_info_item, FALSE ); + } + } + else { + gtk_widget_set_sensitive( textureBrowser.m_shader_info_item, TRUE ); + } - ishader->DecRef(); + ishader->DecRef(); } @@ -485,254 +468,239 @@ CopiedString g_TextureBrowser_currentDirectory; ============================================================================ */ -class TextureLayout { +class TextureLayout +{ public: // texture layout functions // TTimo: now based on shaders - int current_x, current_y, current_row; +int current_x, current_y, current_row; }; -void Texture_StartPos(TextureLayout &layout) -{ - layout.current_x = 8; - layout.current_y = -8; - layout.current_row = 0; +void Texture_StartPos( TextureLayout& layout ){ + layout.current_x = 8; + layout.current_y = -8; + layout.current_row = 0; } -void Texture_NextPos(TextureBrowser &textureBrowser, TextureLayout &layout, qtexture_t *current_texture, int *x, int *y) -{ - qtexture_t *q = current_texture; +void Texture_NextPos( TextureBrowser& textureBrowser, TextureLayout& layout, qtexture_t* current_texture, int *x, int *y ){ + qtexture_t* q = current_texture; - int nWidth = textureBrowser.getTextureWidth(q); - int nHeight = textureBrowser.getTextureHeight(q); - if (layout.current_x + nWidth > textureBrowser.width - 8 && - layout.current_row) { // go to the next row unless the texture is the first on the row - layout.current_x = 8; - layout.current_y -= layout.current_row + TextureBrowser_fontHeight(textureBrowser) + 4; - layout.current_row = 0; - } + int nWidth = textureBrowser.getTextureWidth( q ); + int nHeight = textureBrowser.getTextureHeight( q ); + if ( layout.current_x + nWidth > textureBrowser.width - 8 && layout.current_row ) { // go to the next row unless the texture is the first on the row + layout.current_x = 8; + layout.current_y -= layout.current_row + TextureBrowser_fontHeight( textureBrowser ) + 4; + layout.current_row = 0; + } - *x = layout.current_x; - *y = layout.current_y; + *x = layout.current_x; + *y = layout.current_y; - // Is our texture larger than the row? If so, grow the - // row height to match it + // Is our texture larger than the row? If so, grow the + // row height to match it - if (layout.current_row < nHeight) { - layout.current_row = nHeight; - } + if ( layout.current_row < nHeight ) { + layout.current_row = nHeight; + } - // never go less than 96, or the names get all crunched up - layout.current_x += nWidth < 96 ? 96 : nWidth; - layout.current_x += 8; + // never go less than 96, or the names get all crunched up + layout.current_x += nWidth < 96 ? 96 : nWidth; + layout.current_x += 8; } -bool TextureSearch_IsShown(const char *name) -{ - std::set::iterator iter; +bool TextureSearch_IsShown( const char* name ){ + std::set::iterator iter; - iter = GlobalTextureBrowser().m_found_shaders.find(name); + iter = GlobalTextureBrowser().m_found_shaders.find( name ); - if (iter == GlobalTextureBrowser().m_found_shaders.end()) { - return false; - } else { - return true; - } + if ( iter == GlobalTextureBrowser().m_found_shaders.end() ) { + return false; + } + else { + return true; + } } // if texture_showinuse jump over non in-use textures -bool Texture_IsShown(IShader *shader, bool show_shaders, bool hideUnused) -{ - // filter missing shaders - // ugly: filter on built-in fallback name after substitution - if (g_TextureBrowser_filterMissing) { - if (isMissing(shader->getTexture()->name)) { - return false; - } - } - // filter the fallback (notex/shadernotex) for missing shaders or editor image - if (g_TextureBrowser_filterFallback) { - if (isNotex(shader->getName())) { - return false; - } - if (isNotex(shader->getTexture()->name)) { - return false; - } - } - - if (g_TextureBrowser_currentDirectory == "Untagged") { - std::set::iterator iter; - - iter = GlobalTextureBrowser().m_found_shaders.find(shader->getName()); - - if (iter == GlobalTextureBrowser().m_found_shaders.end()) { - return false; - } else { - return true; - } - } - - if (!shader_equal_prefix(shader->getName(), "textures/")) { - return false; - } - - if (!show_shaders && !shader->IsDefault()) { - return false; - } - - if (hideUnused && !shader->IsInUse()) { - return false; - } - - if (GlobalTextureBrowser().m_searchedTags) { - if (!TextureSearch_IsShown(shader->getName())) { - return false; - } else { - return true; - } - } else { - if (!shader_equal_prefix(shader_get_textureName(shader->getName()), - g_TextureBrowser_currentDirectory.c_str())) { - return false; - } - } - - return true; -} - -void TextureBrowser_heightChanged(TextureBrowser &textureBrowser) -{ - textureBrowser.m_heightChanged = true; - - TextureBrowser_updateScroll(textureBrowser); - TextureBrowser_queueDraw(textureBrowser); -} - -void TextureBrowser_evaluateHeight(TextureBrowser &textureBrowser) -{ - if (textureBrowser.m_heightChanged) { - textureBrowser.m_heightChanged = false; - - textureBrowser.m_nTotalHeight = 0; - - TextureLayout layout; - Texture_StartPos(layout); - for (QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement()) { - IShader *shader = QERApp_ActiveShaders_IteratorCurrent(); - - if (!Texture_IsShown(shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused)) { - continue; - } - - int x, y; - Texture_NextPos(textureBrowser, layout, shader->getTexture(), &x, &y); - textureBrowser.m_nTotalHeight = std::max(textureBrowser.m_nTotalHeight, - abs(layout.current_y) + TextureBrowser_fontHeight(textureBrowser) + - textureBrowser.getTextureHeight(shader->getTexture()) + 4); - } - } +bool Texture_IsShown( IShader* shader, bool show_shaders, bool hideUnused ){ + // filter missing shaders + // ugly: filter on built-in fallback name after substitution + if ( g_TextureBrowser_filterMissing ) { + if ( isMissing( shader->getTexture()->name ) ) { + return false; + } + } + // filter the fallback (notex/shadernotex) for missing shaders or editor image + if ( g_TextureBrowser_filterFallback ) { + if ( isNotex( shader->getName() ) ) { + return false; + } + if ( isNotex( shader->getTexture()->name ) ) { + return false; + } + } + + if ( g_TextureBrowser_currentDirectory == "Untagged" ) { + std::set::iterator iter; + + iter = GlobalTextureBrowser().m_found_shaders.find( shader->getName() ); + + if ( iter == GlobalTextureBrowser().m_found_shaders.end() ) { + return false; + } + else { + return true; + } + } + + if ( !shader_equal_prefix( shader->getName(), "textures/" ) ) { + return false; + } + + if ( !show_shaders && !shader->IsDefault() ) { + return false; + } + + if ( hideUnused && !shader->IsInUse() ) { + return false; + } + + if ( GlobalTextureBrowser().m_searchedTags ) { + if ( !TextureSearch_IsShown( shader->getName() ) ) { + return false; + } + else { + return true; + } + } + else { + if ( !shader_equal_prefix( shader_get_textureName( shader->getName() ), g_TextureBrowser_currentDirectory.c_str() ) ) { + return false; + } + } + + return true; +} + +void TextureBrowser_heightChanged( TextureBrowser& textureBrowser ){ + textureBrowser.m_heightChanged = true; + + TextureBrowser_updateScroll( textureBrowser ); + TextureBrowser_queueDraw( textureBrowser ); +} + +void TextureBrowser_evaluateHeight( TextureBrowser& textureBrowser ){ + if ( textureBrowser.m_heightChanged ) { + textureBrowser.m_heightChanged = false; + + textureBrowser.m_nTotalHeight = 0; + + TextureLayout layout; + Texture_StartPos( layout ); + for ( QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement() ) + { + IShader* shader = QERApp_ActiveShaders_IteratorCurrent(); + + if ( !Texture_IsShown( shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused ) ) { + continue; + } + + int x, y; + Texture_NextPos( textureBrowser, layout, shader->getTexture(), &x, &y ); + textureBrowser.m_nTotalHeight = std::max( textureBrowser.m_nTotalHeight, abs( layout.current_y ) + TextureBrowser_fontHeight( textureBrowser ) + textureBrowser.getTextureHeight( shader->getTexture() ) + 4 ); + } + } +} + +int TextureBrowser_TotalHeight( TextureBrowser& textureBrowser ){ + TextureBrowser_evaluateHeight( textureBrowser ); + return textureBrowser.m_nTotalHeight; +} + +inline const int& min_int( const int& left, const int& right ){ + return std::min( left, right ); +} + +void TextureBrowser_clampOriginY( TextureBrowser& textureBrowser ){ + if ( textureBrowser.originy > 0 ) { + textureBrowser.originy = 0; + } + int lower = min_int( textureBrowser.height - TextureBrowser_TotalHeight( textureBrowser ), 0 ); + if ( textureBrowser.originy < lower ) { + textureBrowser.originy = lower; + } } -int TextureBrowser_TotalHeight(TextureBrowser &textureBrowser) -{ - TextureBrowser_evaluateHeight(textureBrowser); - return textureBrowser.m_nTotalHeight; +int TextureBrowser_getOriginY( TextureBrowser& textureBrowser ){ + if ( textureBrowser.m_originInvalid ) { + textureBrowser.m_originInvalid = false; + TextureBrowser_clampOriginY( textureBrowser ); + TextureBrowser_updateScroll( textureBrowser ); + } + return textureBrowser.originy; } -inline const int &min_int(const int &left, const int &right) -{ - return std::min(left, right); +void TextureBrowser_setOriginY( TextureBrowser& textureBrowser, int originy ){ + textureBrowser.originy = originy; + TextureBrowser_clampOriginY( textureBrowser ); + TextureBrowser_updateScroll( textureBrowser ); + TextureBrowser_queueDraw( textureBrowser ); } -void TextureBrowser_clampOriginY(TextureBrowser &textureBrowser) -{ - if (textureBrowser.originy > 0) { - textureBrowser.originy = 0; - } - int lower = min_int(textureBrowser.height - TextureBrowser_TotalHeight(textureBrowser), 0); - if (textureBrowser.originy < lower) { - textureBrowser.originy = lower; - } -} -int TextureBrowser_getOriginY(TextureBrowser &textureBrowser) -{ - if (textureBrowser.m_originInvalid) { - textureBrowser.m_originInvalid = false; - TextureBrowser_clampOriginY(textureBrowser); - TextureBrowser_updateScroll(textureBrowser); - } - return textureBrowser.originy; -} +Signal0 g_activeShadersChangedCallbacks; -void TextureBrowser_setOriginY(TextureBrowser &textureBrowser, int originy) -{ - textureBrowser.originy = originy; - TextureBrowser_clampOriginY(textureBrowser); - TextureBrowser_updateScroll(textureBrowser); - TextureBrowser_queueDraw(textureBrowser); +void TextureBrowser_addActiveShadersChangedCallback( const SignalHandler& handler ){ + g_activeShadersChangedCallbacks.connectLast( handler ); } +void TextureBrowser_constructTreeStore(); -Signal0 g_activeShadersChangedCallbacks; - -void TextureBrowser_addActiveShadersChangedCallback(const SignalHandler &handler) +class ShadersObserver : public ModuleObserver { - g_activeShadersChangedCallbacks.connectLast(handler); +Signal0 m_realiseCallbacks; +public: +void realise(){ + m_realiseCallbacks(); + TextureBrowser_constructTreeStore(); } -void TextureBrowser_constructTreeStore(); +void unrealise(){ +} -class ShadersObserver : public ModuleObserver { - Signal0 m_realiseCallbacks; -public: - void realise() - { - m_realiseCallbacks(); - TextureBrowser_constructTreeStore(); - } - - void unrealise() - { - } - - void insert(const SignalHandler &handler) - { - m_realiseCallbacks.connectLast(handler); - } +void insert( const SignalHandler& handler ){ + m_realiseCallbacks.connectLast( handler ); +} }; -namespace { - ShadersObserver g_ShadersObserver; +namespace +{ +ShadersObserver g_ShadersObserver; } -void TextureBrowser_addShadersRealiseCallback(const SignalHandler &handler) -{ - g_ShadersObserver.insert(handler); +void TextureBrowser_addShadersRealiseCallback( const SignalHandler& handler ){ + g_ShadersObserver.insert( handler ); } -void TextureBrowser_activeShadersChanged(TextureBrowser &textureBrowser) -{ - TextureBrowser_heightChanged(textureBrowser); - textureBrowser.m_originInvalid = true; +void TextureBrowser_activeShadersChanged( TextureBrowser& textureBrowser ){ + TextureBrowser_heightChanged( textureBrowser ); + textureBrowser.m_originInvalid = true; - g_activeShadersChangedCallbacks(); + g_activeShadersChangedCallbacks(); } struct TextureBrowser_ShowScrollbar { - static void Export(const TextureBrowser &self, const Callback &returnz) - { - returnz(self.m_showTextureScrollbar); - } - - static void Import(TextureBrowser &self, bool value) - { - self.m_showTextureScrollbar = value; - if (self.m_texture_scroll) { - self.m_texture_scroll.visible(self.m_showTextureScrollbar); - TextureBrowser_updateScroll(self); - } - } + static void Export(const TextureBrowser &self, const Callback &returnz) { + returnz(self.m_showTextureScrollbar); + } + + static void Import(TextureBrowser &self, bool value) { + self.m_showTextureScrollbar = value; + if (self.m_texture_scroll) { + self.m_texture_scroll.visible(self.m_showTextureScrollbar); + TextureBrowser_updateScroll(self); + } + } }; @@ -751,267 +719,249 @@ struct TextureBrowser_ShowScrollbar { ============== */ -bool endswith(const char *haystack, const char *needle) +bool endswith( const char *haystack, const char *needle ){ + size_t lh = strlen( haystack ); + size_t ln = strlen( needle ); + if ( lh < ln ) { + return false; + } + return !memcmp( haystack + ( lh - ln ), needle, ln ); +} + +bool texture_name_ignore( const char* name ){ + StringOutputStream strTemp( string_length( name ) ); + strTemp << LowerCase( name ); + + return + endswith( strTemp.c_str(), ".specular" ) || + endswith( strTemp.c_str(), ".glow" ) || + endswith( strTemp.c_str(), ".bump" ) || + endswith( strTemp.c_str(), ".diffuse" ) || + endswith( strTemp.c_str(), ".blend" ) || + endswith( strTemp.c_str(), ".alpha" ) || + endswith( strTemp.c_str(), "_alpha" ) || + /* Quetoo */ + endswith( strTemp.c_str(), "_h" ) || + endswith( strTemp.c_str(), "_local" ) || + endswith( strTemp.c_str(), "_nm" ) || + endswith( strTemp.c_str(), "_s" ) || + /* DarkPlaces */ + endswith( strTemp.c_str(), "_bump" ) || + endswith( strTemp.c_str(), "_glow" ) || + endswith( strTemp.c_str(), "_gloss" ) || + endswith( strTemp.c_str(), "_luma" ) || + endswith( strTemp.c_str(), "_norm" ) || + endswith( strTemp.c_str(), "_pants" ) || + endswith( strTemp.c_str(), "_shirt" ) || + endswith( strTemp.c_str(), "_reflect" ) || + /* Unvanquished */ + endswith( strTemp.c_str(), "_d" ) || + endswith( strTemp.c_str(), "_n" ) || + endswith( strTemp.c_str(), "_p" ) || + endswith( strTemp.c_str(), "_g" ) || + endswith( strTemp.c_str(), "_a" ) || + 0; +} + +class LoadShaderVisitor : public Archive::Visitor { - size_t lh = strlen(haystack); - size_t ln = strlen(needle); - if (lh < ln) { - return false; - } - return !memcmp(haystack + (lh - ln), needle, ln); -} - -bool texture_name_ignore(const char *name) -{ - StringOutputStream strTemp(string_length(name)); - strTemp << LowerCase(name); - - return - endswith(strTemp.c_str(), ".specular") || - endswith(strTemp.c_str(), ".glow") || - endswith(strTemp.c_str(), ".bump") || - endswith(strTemp.c_str(), ".diffuse") || - endswith(strTemp.c_str(), ".blend") || - endswith(strTemp.c_str(), ".alpha") || - endswith(strTemp.c_str(), "_alpha") || - /* Quetoo */ - endswith(strTemp.c_str(), "_h") || - endswith(strTemp.c_str(), "_local") || - endswith(strTemp.c_str(), "_nm") || - endswith(strTemp.c_str(), "_s") || - /* DarkPlaces */ - endswith(strTemp.c_str(), "_bump") || - endswith(strTemp.c_str(), "_glow") || - endswith(strTemp.c_str(), "_gloss") || - endswith(strTemp.c_str(), "_luma") || - endswith(strTemp.c_str(), "_norm") || - endswith(strTemp.c_str(), "_pants") || - endswith(strTemp.c_str(), "_shirt") || - endswith(strTemp.c_str(), "_reflect") || - /* Unvanquished */ - endswith(strTemp.c_str(), "_d") || - endswith(strTemp.c_str(), "_n") || - endswith(strTemp.c_str(), "_p") || - endswith(strTemp.c_str(), "_g") || - endswith(strTemp.c_str(), "_a") || - 0; -} - -class LoadShaderVisitor : public Archive::Visitor { public: - void visit(const char *name) - { - IShader *shader = QERApp_Shader_ForName( - CopiedString(StringRange(name, path_get_filename_base_end(name))).c_str()); - shader->DecRef(); - } +void visit( const char* name ){ + IShader* shader = QERApp_Shader_ForName( CopiedString( StringRange( name, path_get_filename_base_end( name ) ) ).c_str() ); + shader->DecRef(); +} }; -void TextureBrowser_SetHideUnused(TextureBrowser &textureBrowser, bool hideUnused); +void TextureBrowser_SetHideUnused( TextureBrowser& textureBrowser, bool hideUnused ); ui::Widget g_page_textures{ui::null}; -void TextureBrowser_toggleShow() -{ - GroupDialog_showPage(g_page_textures); +void TextureBrowser_toggleShow(){ + GroupDialog_showPage( g_page_textures ); } -void TextureBrowser_updateTitle() -{ - GroupDialog_updatePageTitle(g_page_textures); +void TextureBrowser_updateTitle(){ + GroupDialog_updatePageTitle( g_page_textures ); } -class TextureCategoryLoadShader { - const char *m_directory; - std::size_t &m_count; +class TextureCategoryLoadShader +{ +const char* m_directory; +std::size_t& m_count; public: - using func = void(const char *); - - TextureCategoryLoadShader(const char *directory, std::size_t &count) - : m_directory(directory), m_count(count) - { - m_count = 0; - } - - void operator()(const char *name) const - { - if (shader_equal_prefix(name, "textures/") - && shader_equal_prefix(name + string_length("textures/"), m_directory)) { - ++m_count; - // request the shader, this will load the texture if needed - // this Shader_ForName call is a kind of hack - IShader *pFoo = QERApp_Shader_ForName(name); - pFoo->DecRef(); - } - } +using func = void(const char *); + +TextureCategoryLoadShader( const char* directory, std::size_t& count ) + : m_directory( directory ), m_count( count ){ + m_count = 0; +} + +void operator()( const char* name ) const { + if ( shader_equal_prefix( name, "textures/" ) + && shader_equal_prefix( name + string_length( "textures/" ), m_directory ) ) { + ++m_count; + // request the shader, this will load the texture if needed + // this Shader_ForName call is a kind of hack + IShader *pFoo = QERApp_Shader_ForName( name ); + pFoo->DecRef(); + } +} }; -void TextureDirectory_loadTexture(const char *directory, const char *texture) -{ - StringOutputStream name(256); - name << directory << StringRange(texture, path_get_filename_base_end(texture)); +void TextureDirectory_loadTexture( const char* directory, const char* texture ){ + StringOutputStream name( 256 ); + name << directory << StringRange( texture, path_get_filename_base_end( texture ) ); - if (texture_name_ignore(name.c_str())) { - return; - } + if ( texture_name_ignore( name.c_str() ) ) { + return; + } - if (!shader_valid(name.c_str())) { - globalOutputStream() << "Skipping invalid texture name: [" << name.c_str() << "]\n"; - return; - } + if ( !shader_valid( name.c_str() ) ) { + globalOutputStream() << "Skipping invalid texture name: [" << name.c_str() << "]\n"; + return; + } - // if a texture is already in use to represent a shader, ignore it - IShader *shader = QERApp_Shader_ForName(name.c_str()); - shader->DecRef(); + // if a texture is already in use to represent a shader, ignore it + IShader* shader = QERApp_Shader_ForName( name.c_str() ); + shader->DecRef(); } -typedef ConstPointerCaller TextureDirectoryLoadTextureCaller; +typedef ConstPointerCaller TextureDirectoryLoadTextureCaller; -class LoadTexturesByTypeVisitor : public ImageModules::Visitor { - const char *m_dirstring; +class LoadTexturesByTypeVisitor : public ImageModules::Visitor +{ +const char* m_dirstring; public: - LoadTexturesByTypeVisitor(const char *dirstring) - : m_dirstring(dirstring) - { - } - - void visit(const char *minor, const _QERPlugImageTable &table) const - { - GlobalFileSystem().forEachFile(m_dirstring, minor, TextureDirectoryLoadTextureCaller(m_dirstring)); - } +LoadTexturesByTypeVisitor( const char* dirstring ) + : m_dirstring( dirstring ){ +} + +void visit( const char* minor, const _QERPlugImageTable& table ) const { + GlobalFileSystem().forEachFile( m_dirstring, minor, TextureDirectoryLoadTextureCaller( m_dirstring ) ); +} }; -void TextureBrowser_ShowDirectory(TextureBrowser &textureBrowser, const char *directory) -{ - if (TextureBrowser_showWads()) { - Archive *archive = GlobalFileSystem().getArchive(directory); - ASSERT_NOTNULL(archive); - LoadShaderVisitor visitor; - archive->forEachFile(Archive::VisitorFunc(visitor, Archive::eFiles, 0), "textures/"); - } else { - g_TextureBrowser_currentDirectory = directory; - TextureBrowser_heightChanged(textureBrowser); +void TextureBrowser_ShowDirectory( TextureBrowser& textureBrowser, const char* directory ){ + if ( TextureBrowser_showWads() ) { + Archive* archive = GlobalFileSystem().getArchive( directory ); + ASSERT_NOTNULL( archive ); + LoadShaderVisitor visitor; + archive->forEachFile( Archive::VisitorFunc( visitor, Archive::eFiles, 0 ), "textures/" ); + } + else + { + g_TextureBrowser_currentDirectory = directory; + TextureBrowser_heightChanged( textureBrowser ); - std::size_t shaders_count; - GlobalShaderSystem().foreachShaderName(makeCallback(TextureCategoryLoadShader(directory, shaders_count))); - globalOutputStream() << "Showing " << Unsigned(shaders_count) << " shaders.\n"; + std::size_t shaders_count; + GlobalShaderSystem().foreachShaderName(makeCallback( TextureCategoryLoadShader( directory, shaders_count ) ) ); + globalOutputStream() << "Showing " << Unsigned( shaders_count ) << " shaders.\n"; - if (g_pGameDescription->mGameType != "doom3") { - // load remaining texture files + if ( g_pGameDescription->mGameType != "doom3" ) { + // load remaining texture files - StringOutputStream dirstring(64); - dirstring << "textures/" << directory; + StringOutputStream dirstring( 64 ); + dirstring << "textures/" << directory; - Radiant_getImageModules().foreachModule(LoadTexturesByTypeVisitor(dirstring.c_str())); - } - } + Radiant_getImageModules().foreachModule( LoadTexturesByTypeVisitor( dirstring.c_str() ) ); + } + } - // we'll display the newly loaded textures + all the ones already in use - TextureBrowser_SetHideUnused(textureBrowser, false); + // we'll display the newly loaded textures + all the ones already in use + TextureBrowser_SetHideUnused( textureBrowser, false ); - TextureBrowser_updateTitle(); + TextureBrowser_updateTitle(); } -void TextureBrowser_ShowTagSearchResult(TextureBrowser &textureBrowser, const char *directory) -{ - g_TextureBrowser_currentDirectory = directory; - TextureBrowser_heightChanged(textureBrowser); +void TextureBrowser_ShowTagSearchResult( TextureBrowser& textureBrowser, const char* directory ){ + g_TextureBrowser_currentDirectory = directory; + TextureBrowser_heightChanged( textureBrowser ); - std::size_t shaders_count; - GlobalShaderSystem().foreachShaderName(makeCallback(TextureCategoryLoadShader(directory, shaders_count))); - globalOutputStream() << "Showing " << Unsigned(shaders_count) << " shaders.\n"; + std::size_t shaders_count; + GlobalShaderSystem().foreachShaderName(makeCallback( TextureCategoryLoadShader( directory, shaders_count ) ) ); + globalOutputStream() << "Showing " << Unsigned( shaders_count ) << " shaders.\n"; - if (g_pGameDescription->mGameType != "doom3") { - // load remaining texture files - StringOutputStream dirstring(64); - dirstring << "textures/" << directory; + if ( g_pGameDescription->mGameType != "doom3" ) { + // load remaining texture files + StringOutputStream dirstring( 64 ); + dirstring << "textures/" << directory; - { - LoadTexturesByTypeVisitor visitor(dirstring.c_str()); - Radiant_getImageModules().foreachModule(visitor); - } - } + { + LoadTexturesByTypeVisitor visitor( dirstring.c_str() ); + Radiant_getImageModules().foreachModule( visitor ); + } + } - // we'll display the newly loaded textures + all the ones already in use - TextureBrowser_SetHideUnused(textureBrowser, false); + // we'll display the newly loaded textures + all the ones already in use + TextureBrowser_SetHideUnused( textureBrowser, false ); } bool TextureBrowser_hideUnused(); -void TextureBrowser_hideUnusedExport(const Callback &importer) -{ - importer(TextureBrowser_hideUnused()); +void TextureBrowser_hideUnusedExport( const Callback & importer ){ + importer( TextureBrowser_hideUnused() ); } typedef FreeCaller &), TextureBrowser_hideUnusedExport> TextureBrowserHideUnusedExport; -void TextureBrowser_showShadersExport(const Callback &importer) -{ - importer(GlobalTextureBrowser().m_showShaders); +void TextureBrowser_showShadersExport( const Callback & importer ){ + importer( GlobalTextureBrowser().m_showShaders ); } -typedef FreeCaller &), TextureBrowser_showShadersExport> TextureBrowserShowShadersExport; +typedef FreeCaller &), TextureBrowser_showShadersExport> TextureBrowserShowShadersExport; -void TextureBrowser_showShaderlistOnly(const Callback &importer) -{ - importer(g_TextureBrowser_shaderlistOnly); +void TextureBrowser_showShaderlistOnly( const Callback & importer ){ + importer( g_TextureBrowser_shaderlistOnly ); } -typedef FreeCaller &), TextureBrowser_showShaderlistOnly> TextureBrowserShowShaderlistOnlyExport; +typedef FreeCaller &), TextureBrowser_showShaderlistOnly> TextureBrowserShowShaderlistOnlyExport; -void TextureBrowser_fixedSize(const Callback &importer) -{ - importer(g_TextureBrowser_fixedSize); +void TextureBrowser_fixedSize( const Callback & importer ){ + importer( g_TextureBrowser_fixedSize ); } typedef FreeCaller &), TextureBrowser_fixedSize> TextureBrowser_FixedSizeExport; -void TextureBrowser_filterMissing(const Callback &importer) -{ - importer(g_TextureBrowser_filterMissing); +void TextureBrowser_filterMissing( const Callback & importer ){ + importer( g_TextureBrowser_filterMissing ); } typedef FreeCaller &), TextureBrowser_filterMissing> TextureBrowser_filterMissingExport; -void TextureBrowser_filterFallback(const Callback &importer) -{ - importer(g_TextureBrowser_filterFallback); +void TextureBrowser_filterFallback( const Callback & importer ){ + importer( g_TextureBrowser_filterFallback ); } -typedef FreeCaller &), TextureBrowser_filterFallback> TextureBrowser_filterFallbackExport; +typedef FreeCaller &), TextureBrowser_filterFallback> TextureBrowser_filterFallbackExport; -void TextureBrowser_enableAlpha(const Callback &importer) -{ - importer(g_TextureBrowser_enableAlpha); +void TextureBrowser_enableAlpha( const Callback & importer ){ + importer( g_TextureBrowser_enableAlpha ); } typedef FreeCaller &), TextureBrowser_enableAlpha> TextureBrowser_enableAlphaExport; -void TextureBrowser_SetHideUnused(TextureBrowser &textureBrowser, bool hideUnused) -{ - if (hideUnused) { - textureBrowser.m_hideUnused = true; - } else { - textureBrowser.m_hideUnused = false; - } +void TextureBrowser_SetHideUnused( TextureBrowser& textureBrowser, bool hideUnused ){ + if ( hideUnused ) { + textureBrowser.m_hideUnused = true; + } + else + { + textureBrowser.m_hideUnused = false; + } - textureBrowser.m_hideunused_item.update(); + textureBrowser.m_hideunused_item.update(); - TextureBrowser_heightChanged(textureBrowser); - textureBrowser.m_originInvalid = true; + TextureBrowser_heightChanged( textureBrowser ); + textureBrowser.m_originInvalid = true; } -void TextureBrowser_ShowStartupShaders(TextureBrowser &textureBrowser) -{ - if (textureBrowser.m_startupShaders == STARTUPSHADERS_COMMON) { - TextureBrowser_ShowDirectory(textureBrowser, TextureBrowser_getComonShadersDir()); - } +void TextureBrowser_ShowStartupShaders( TextureBrowser& textureBrowser ){ + if ( textureBrowser.m_startupShaders == STARTUPSHADERS_COMMON ) { + TextureBrowser_ShowDirectory( textureBrowser, TextureBrowser_getComonShadersDir() ); + } } @@ -1019,76 +969,76 @@ void TextureBrowser_ShowStartupShaders(TextureBrowser &textureBrowser) // it might need to be split in parts or moved out .. dunno // scroll origin so the specified texture is completely on screen // if current texture is not displayed, nothing is changed -void TextureBrowser_Focus(TextureBrowser &textureBrowser, const char *name) -{ - TextureLayout layout; - // scroll origin so the texture is completely on screen - Texture_StartPos(layout); - - for (QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement()) { - IShader *shader = QERApp_ActiveShaders_IteratorCurrent(); - - if (!Texture_IsShown(shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused)) { - continue; - } - - int x, y; - Texture_NextPos(textureBrowser, layout, shader->getTexture(), &x, &y); - qtexture_t *q = shader->getTexture(); - if (!q) { - break; - } - - // we have found when texdef->name and the shader name match - // NOTE: as everywhere else for our comparisons, we are not case sensitive - if (shader_equal(name, shader->getName())) { - int textureHeight = (int) (q->height * ((float) textureBrowser.m_textureScale / 100)) - + 2 * TextureBrowser_fontHeight(textureBrowser); - - int originy = TextureBrowser_getOriginY(textureBrowser); - if (y > originy) { - originy = y; - } - - if (y - textureHeight < originy - textureBrowser.height) { - originy = (y - textureHeight) + textureBrowser.height; - } - - TextureBrowser_setOriginY(textureBrowser, originy); - return; - } - } -} - -IShader *Texture_At(TextureBrowser &textureBrowser, int mx, int my) -{ - my += TextureBrowser_getOriginY(textureBrowser) - textureBrowser.height; - - TextureLayout layout; - Texture_StartPos(layout); - for (QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement()) { - IShader *shader = QERApp_ActiveShaders_IteratorCurrent(); - - if (!Texture_IsShown(shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused)) { - continue; - } - - int x, y; - Texture_NextPos(textureBrowser, layout, shader->getTexture(), &x, &y); - qtexture_t *q = shader->getTexture(); - if (!q) { - break; - } - - int nWidth = textureBrowser.getTextureWidth(q); - int nHeight = textureBrowser.getTextureHeight(q); - if (mx > x && mx - x < nWidth - && my < y && y - my < nHeight + TextureBrowser_fontHeight(textureBrowser)) { - return shader; - } - } - - return 0; +void TextureBrowser_Focus( TextureBrowser& textureBrowser, const char* name ){ + TextureLayout layout; + // scroll origin so the texture is completely on screen + Texture_StartPos( layout ); + + for ( QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement() ) + { + IShader* shader = QERApp_ActiveShaders_IteratorCurrent(); + + if ( !Texture_IsShown( shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused ) ) { + continue; + } + + int x, y; + Texture_NextPos( textureBrowser, layout, shader->getTexture(), &x, &y ); + qtexture_t* q = shader->getTexture(); + if ( !q ) { + break; + } + + // we have found when texdef->name and the shader name match + // NOTE: as everywhere else for our comparisons, we are not case sensitive + if ( shader_equal( name, shader->getName() ) ) { + int textureHeight = (int)( q->height * ( (float)textureBrowser.m_textureScale / 100 ) ) + + 2 * TextureBrowser_fontHeight( textureBrowser ); + + int originy = TextureBrowser_getOriginY( textureBrowser ); + if ( y > originy ) { + originy = y; + } + + if ( y - textureHeight < originy - textureBrowser.height ) { + originy = ( y - textureHeight ) + textureBrowser.height; + } + + TextureBrowser_setOriginY( textureBrowser, originy ); + return; + } + } +} + +IShader* Texture_At( TextureBrowser& textureBrowser, int mx, int my ){ + my += TextureBrowser_getOriginY( textureBrowser ) - textureBrowser.height; + + TextureLayout layout; + Texture_StartPos( layout ); + for ( QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement() ) + { + IShader* shader = QERApp_ActiveShaders_IteratorCurrent(); + + if ( !Texture_IsShown( shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused ) ) { + continue; + } + + int x, y; + Texture_NextPos( textureBrowser, layout, shader->getTexture(), &x, &y ); + qtexture_t *q = shader->getTexture(); + if ( !q ) { + break; + } + + int nWidth = textureBrowser.getTextureWidth( q ); + int nHeight = textureBrowser.getTextureHeight( q ); + if ( mx > x && mx - x < nWidth + && my < y && y - my < nHeight + TextureBrowser_fontHeight( textureBrowser ) ) { + return shader; + } + } + + return 0; } /* @@ -1098,26 +1048,28 @@ IShader *Texture_At(TextureBrowser &textureBrowser, int mx, int my) By mouse click ============== */ -void SelectTexture(TextureBrowser &textureBrowser, int mx, int my, bool bShift) -{ - IShader *shader = Texture_At(textureBrowser, mx, my); - if (shader != 0) { - if (bShift) { - if (shader->IsDefault()) { - globalOutputStream() << "ERROR: " << shader->getName() << " is not a shader, it's a texture.\n"; - } else { - ViewShader(shader->getShaderFileName(), shader->getName()); - } - } else { - TextureBrowser_SetSelectedShader(textureBrowser, shader->getName()); - TextureBrowser_textureSelected(shader->getName()); - - if (!FindTextureDialog_isOpen() && !textureBrowser.m_rmbSelected) { - UndoableCommand undo("textureNameSetSelected"); - Select_SetShader(shader->getName()); - } - } - } +void SelectTexture( TextureBrowser& textureBrowser, int mx, int my, bool bShift ){ + IShader* shader = Texture_At( textureBrowser, mx, my ); + if ( shader != 0 ) { + if ( bShift ) { + if ( shader->IsDefault() ) { + globalOutputStream() << "ERROR: " << shader->getName() << " is not a shader, it's a texture.\n"; + } + else{ + ViewShader( shader->getShaderFileName(), shader->getName() ); + } + } + else + { + TextureBrowser_SetSelectedShader( textureBrowser, shader->getName() ); + TextureBrowser_textureSelected( shader->getName() ); + + if ( !FindTextureDialog_isOpen() && !textureBrowser.m_rmbSelected ) { + UndoableCommand undo( "textureNameSetSelected" ); + Select_SetShader( shader->getName() ); + } + } + } } /* @@ -1128,36 +1080,31 @@ void SelectTexture(TextureBrowser &textureBrowser, int mx, int my, bool bShift) ============================================================================ */ -void TextureBrowser_trackingDelta(int x, int y, unsigned int state, void *data) -{ - TextureBrowser &textureBrowser = *reinterpret_cast( data ); - if (y != 0) { - int scale = 1; +void TextureBrowser_trackingDelta( int x, int y, unsigned int state, void* data ){ + TextureBrowser& textureBrowser = *reinterpret_cast( data ); + if ( y != 0 ) { + int scale = 1; - if (state & GDK_SHIFT_MASK) { - scale = 4; - } + if ( state & GDK_SHIFT_MASK ) { + scale = 4; + } - int originy = TextureBrowser_getOriginY(textureBrowser); - originy += y * scale; - TextureBrowser_setOriginY(textureBrowser, originy); - } + int originy = TextureBrowser_getOriginY( textureBrowser ); + originy += y * scale; + TextureBrowser_setOriginY( textureBrowser, originy ); + } } -void TextureBrowser_Tracking_MouseDown(TextureBrowser &textureBrowser) -{ - textureBrowser.m_freezePointer.freeze_pointer(textureBrowser.m_parent, TextureBrowser_trackingDelta, - &textureBrowser); +void TextureBrowser_Tracking_MouseDown( TextureBrowser& textureBrowser ){ + textureBrowser.m_freezePointer.freeze_pointer( textureBrowser.m_parent, TextureBrowser_trackingDelta, &textureBrowser ); } -void TextureBrowser_Tracking_MouseUp(TextureBrowser &textureBrowser) -{ - textureBrowser.m_freezePointer.unfreeze_pointer(textureBrowser.m_parent); +void TextureBrowser_Tracking_MouseUp( TextureBrowser& textureBrowser ){ + textureBrowser.m_freezePointer.unfreeze_pointer( textureBrowser.m_parent ); } -void TextureBrowser_Selection_MouseDown(TextureBrowser &textureBrowser, guint32 flags, int pointx, int pointy) -{ - SelectTexture(textureBrowser, pointx, textureBrowser.height - 1 - pointy, (flags & GDK_SHIFT_MASK) != 0); +void TextureBrowser_Selection_MouseDown( TextureBrowser& textureBrowser, guint32 flags, int pointx, int pointy ){ + SelectTexture( textureBrowser, pointx, textureBrowser.height - 1 - pointy, ( flags & GDK_SHIFT_MASK ) != 0 ); } /* @@ -1176,520 +1123,520 @@ void TextureBrowser_Selection_MouseDown(TextureBrowser &textureBrowser, guint32 this allows a plugin to completely override the texture system ============ */ -void Texture_Draw(TextureBrowser &textureBrowser) -{ - int originy = TextureBrowser_getOriginY(textureBrowser); - - glClearColor(textureBrowser.color_textureback[0], - textureBrowser.color_textureback[1], - textureBrowser.color_textureback[2], - 0); - glViewport(0, 0, textureBrowser.width, textureBrowser.height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glDisable(GL_DEPTH_TEST); - if (g_TextureBrowser_enableAlpha) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } else { - glDisable(GL_BLEND); - } - glOrtho(0, textureBrowser.width, originy - textureBrowser.height, originy, -100, 100); - glEnable(GL_TEXTURE_2D); - - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - int last_y = 0, last_height = 0; - - TextureLayout layout; - Texture_StartPos(layout); - for (QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement()) { - IShader *shader = QERApp_ActiveShaders_IteratorCurrent(); - - if (!Texture_IsShown(shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused)) { - continue; - } - - int x, y; - Texture_NextPos(textureBrowser, layout, shader->getTexture(), &x, &y); - qtexture_t *q = shader->getTexture(); - if (!q) { - break; - } - - int nWidth = textureBrowser.getTextureWidth(q); - int nHeight = textureBrowser.getTextureHeight(q); - - if (y != last_y) { - last_y = y; - last_height = 0; - } - last_height = std::max(nHeight, last_height); - - // Is this texture visible? - if ((y - nHeight - TextureBrowser_fontHeight(textureBrowser) < originy) - && (y > originy - textureBrowser.height)) { - // borders rules: - // if it's the current texture, draw a thick red line, else: - // shaders have a white border, simple textures don't - // if !texture_showinuse: (some textures displayed may not be in use) - // draw an additional square around with 0.5 1 0.5 color - if (shader_equal(TextureBrowser_GetSelectedShader(textureBrowser), shader->getName())) { - glLineWidth(3); - if (textureBrowser.m_rmbSelected) { - glColor3f(0, 0, 1); - } else { - glColor3f(1, 0, 0); - } - glDisable(GL_TEXTURE_2D); - - glBegin(GL_LINE_LOOP); - glVertex2i(x - 4, y - TextureBrowser_fontHeight(textureBrowser) + 4); - glVertex2i(x - 4, y - TextureBrowser_fontHeight(textureBrowser) - nHeight - 4); - glVertex2i(x + 4 + nWidth, y - TextureBrowser_fontHeight(textureBrowser) - nHeight - 4); - glVertex2i(x + 4 + nWidth, y - TextureBrowser_fontHeight(textureBrowser) + 4); - glEnd(); - - glEnable(GL_TEXTURE_2D); - glLineWidth(1); - } else { - glLineWidth(1); - // shader border: - if (!shader->IsDefault()) { - glColor3f(1, 1, 1); - glDisable(GL_TEXTURE_2D); - - glBegin(GL_LINE_LOOP); - glVertex2i(x - 1, y + 1 - TextureBrowser_fontHeight(textureBrowser)); - glVertex2i(x - 1, y - nHeight - 1 - TextureBrowser_fontHeight(textureBrowser)); - glVertex2i(x + 1 + nWidth, y - nHeight - 1 - TextureBrowser_fontHeight(textureBrowser)); - glVertex2i(x + 1 + nWidth, y + 1 - TextureBrowser_fontHeight(textureBrowser)); - glEnd(); - glEnable(GL_TEXTURE_2D); - } - - // highlight in-use textures - if (!textureBrowser.m_hideUnused && shader->IsInUse()) { - glColor3f(0.5, 1, 0.5); - glDisable(GL_TEXTURE_2D); - glBegin(GL_LINE_LOOP); - glVertex2i(x - 3, y + 3 - TextureBrowser_fontHeight(textureBrowser)); - glVertex2i(x - 3, y - nHeight - 3 - TextureBrowser_fontHeight(textureBrowser)); - glVertex2i(x + 3 + nWidth, y - nHeight - 3 - TextureBrowser_fontHeight(textureBrowser)); - glVertex2i(x + 3 + nWidth, y + 3 - TextureBrowser_fontHeight(textureBrowser)); - glEnd(); - glEnable(GL_TEXTURE_2D); - } - } - - // draw checkerboard for transparent textures - if (g_TextureBrowser_enableAlpha) { - glDisable(GL_TEXTURE_2D); - glBegin(GL_QUADS); - int font_height = TextureBrowser_fontHeight(textureBrowser); - for (int i = 0; i < nHeight; i += 8) { - for (int j = 0; j < nWidth; j += 8) { - unsigned char color = (i + j) / 8 % 2 ? 0x66 : 0x99; - glColor3ub(color, color, color); - int left = j; - int right = std::min(j + 8, nWidth); - int top = i; - int bottom = std::min(i + 8, nHeight); - glVertex2i(x + right, y - nHeight - font_height + top); - glVertex2i(x + left, y - nHeight - font_height + top); - glVertex2i(x + left, y - nHeight - font_height + bottom); - glVertex2i(x + right, y - nHeight - font_height + bottom); - } - } - glEnd(); - glEnable(GL_TEXTURE_2D); - } - - // Draw the texture - glBindTexture(GL_TEXTURE_2D, q->texture_number); - GlobalOpenGL_debugAssertNoErrors(); - glColor3f(1, 1, 1); - glBegin(GL_QUADS); - glTexCoord2i(0, 0); - glVertex2i(x, y - TextureBrowser_fontHeight(textureBrowser)); - glTexCoord2i(1, 0); - glVertex2i(x + nWidth, y - TextureBrowser_fontHeight(textureBrowser)); - glTexCoord2i(1, 1); - glVertex2i(x + nWidth, y - TextureBrowser_fontHeight(textureBrowser) - nHeight); - glTexCoord2i(0, 1); - glVertex2i(x, y - TextureBrowser_fontHeight(textureBrowser) - nHeight); - glEnd(); - - // draw the texture name - glDisable(GL_TEXTURE_2D); - glColor3f(1, 1, 1); - - glRasterPos2i(x, y - TextureBrowser_fontHeight(textureBrowser) + 5); - - // don't draw the directory name - const char *name = shader->getName(); - name += strlen(name); - while (name != shader->getName() && *(name - 1) != '/' && *(name - 1) != '\\') { - name--; - } - - GlobalOpenGL().drawString(name); - glEnable(GL_TEXTURE_2D); - } - - //int totalHeight = abs(y) + last_height + TextureBrowser_fontHeight(textureBrowser) + 4; - } - - - // reset the current texture - glBindTexture(GL_TEXTURE_2D, 0); - //qglFinish(); -} - -void TextureBrowser_queueDraw(TextureBrowser &textureBrowser) -{ - if (textureBrowser.m_gl_widget) { - gtk_widget_queue_draw(textureBrowser.m_gl_widget); - } -} - - -void TextureBrowser_setScale(TextureBrowser &textureBrowser, std::size_t scale) -{ - textureBrowser.m_textureScale = scale; - - TextureBrowser_queueDraw(textureBrowser); -} - -void TextureBrowser_setUniformSize(TextureBrowser &textureBrowser, std::size_t scale) -{ - textureBrowser.m_uniformTextureSize = scale; - - TextureBrowser_queueDraw(textureBrowser); -} - - -void TextureBrowser_MouseWheel(TextureBrowser &textureBrowser, bool bUp) -{ - int originy = TextureBrowser_getOriginY(textureBrowser); - - if (bUp) { - originy += int(textureBrowser.m_mouseWheelScrollIncrement); - } else { - originy -= int(textureBrowser.m_mouseWheelScrollIncrement); - } - - TextureBrowser_setOriginY(textureBrowser, originy); +void Texture_Draw( TextureBrowser& textureBrowser ){ + int originy = TextureBrowser_getOriginY( textureBrowser ); + + glClearColor( textureBrowser.color_textureback[0], + textureBrowser.color_textureback[1], + textureBrowser.color_textureback[2], + 0 ); + glViewport( 0, 0, textureBrowser.width, textureBrowser.height ); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + glDisable( GL_DEPTH_TEST ); + if ( g_TextureBrowser_enableAlpha ) { + glEnable( GL_BLEND ); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + else { + glDisable( GL_BLEND ); + } + glOrtho( 0, textureBrowser.width, originy - textureBrowser.height, originy, -100, 100 ); + glEnable( GL_TEXTURE_2D ); + + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + + int last_y = 0, last_height = 0; + + TextureLayout layout; + Texture_StartPos( layout ); + for ( QERApp_ActiveShaders_IteratorBegin(); !QERApp_ActiveShaders_IteratorAtEnd(); QERApp_ActiveShaders_IteratorIncrement() ) + { + IShader* shader = QERApp_ActiveShaders_IteratorCurrent(); + + if ( !Texture_IsShown( shader, textureBrowser.m_showShaders, textureBrowser.m_hideUnused ) ) { + continue; + } + + int x, y; + Texture_NextPos( textureBrowser, layout, shader->getTexture(), &x, &y ); + qtexture_t *q = shader->getTexture(); + if ( !q ) { + break; + } + + int nWidth = textureBrowser.getTextureWidth( q ); + int nHeight = textureBrowser.getTextureHeight( q ); + + if ( y != last_y ) { + last_y = y; + last_height = 0; + } + last_height = std::max( nHeight, last_height ); + + // Is this texture visible? + if ( ( y - nHeight - TextureBrowser_fontHeight( textureBrowser ) < originy ) + && ( y > originy - textureBrowser.height ) ) { + // borders rules: + // if it's the current texture, draw a thick red line, else: + // shaders have a white border, simple textures don't + // if !texture_showinuse: (some textures displayed may not be in use) + // draw an additional square around with 0.5 1 0.5 color + if ( shader_equal( TextureBrowser_GetSelectedShader( textureBrowser ), shader->getName() ) ) { + glLineWidth( 3 ); + if ( textureBrowser.m_rmbSelected ) { + glColor3f( 0,0,1 ); + } + else { + glColor3f( 1,0,0 ); + } + glDisable( GL_TEXTURE_2D ); + + glBegin( GL_LINE_LOOP ); + glVertex2i( x - 4,y - TextureBrowser_fontHeight( textureBrowser ) + 4 ); + glVertex2i( x - 4,y - TextureBrowser_fontHeight( textureBrowser ) - nHeight - 4 ); + glVertex2i( x + 4 + nWidth,y - TextureBrowser_fontHeight( textureBrowser ) - nHeight - 4 ); + glVertex2i( x + 4 + nWidth,y - TextureBrowser_fontHeight( textureBrowser ) + 4 ); + glEnd(); + + glEnable( GL_TEXTURE_2D ); + glLineWidth( 1 ); + } + else + { + glLineWidth( 1 ); + // shader border: + if ( !shader->IsDefault() ) { + glColor3f( 1,1,1 ); + glDisable( GL_TEXTURE_2D ); + + glBegin( GL_LINE_LOOP ); + glVertex2i( x - 1,y + 1 - TextureBrowser_fontHeight( textureBrowser ) ); + glVertex2i( x - 1,y - nHeight - 1 - TextureBrowser_fontHeight( textureBrowser ) ); + glVertex2i( x + 1 + nWidth,y - nHeight - 1 - TextureBrowser_fontHeight( textureBrowser ) ); + glVertex2i( x + 1 + nWidth,y + 1 - TextureBrowser_fontHeight( textureBrowser ) ); + glEnd(); + glEnable( GL_TEXTURE_2D ); + } + + // highlight in-use textures + if ( !textureBrowser.m_hideUnused && shader->IsInUse() ) { + glColor3f( 0.5,1,0.5 ); + glDisable( GL_TEXTURE_2D ); + glBegin( GL_LINE_LOOP ); + glVertex2i( x - 3,y + 3 - TextureBrowser_fontHeight( textureBrowser ) ); + glVertex2i( x - 3,y - nHeight - 3 - TextureBrowser_fontHeight( textureBrowser ) ); + glVertex2i( x + 3 + nWidth,y - nHeight - 3 - TextureBrowser_fontHeight( textureBrowser ) ); + glVertex2i( x + 3 + nWidth,y + 3 - TextureBrowser_fontHeight( textureBrowser ) ); + glEnd(); + glEnable( GL_TEXTURE_2D ); + } + } + + // draw checkerboard for transparent textures + if ( g_TextureBrowser_enableAlpha ) + { + glDisable( GL_TEXTURE_2D ); + glBegin( GL_QUADS ); + int font_height = TextureBrowser_fontHeight( textureBrowser ); + for ( int i = 0; i < nHeight; i += 8 ) + { + for ( int j = 0; j < nWidth; j += 8 ) + { + unsigned char color = (i + j) / 8 % 2 ? 0x66 : 0x99; + glColor3ub( color, color, color ); + int left = j; + int right = std::min(j+8, nWidth); + int top = i; + int bottom = std::min(i+8, nHeight); + glVertex2i(x + right, y - nHeight - font_height + top); + glVertex2i(x + left, y - nHeight - font_height + top); + glVertex2i(x + left, y - nHeight - font_height + bottom); + glVertex2i(x + right, y - nHeight - font_height + bottom); + } + } + glEnd(); + glEnable( GL_TEXTURE_2D ); + } + + // Draw the texture + glBindTexture( GL_TEXTURE_2D, q->texture_number ); + GlobalOpenGL_debugAssertNoErrors(); + glColor3f( 1,1,1 ); + glBegin( GL_QUADS ); + glTexCoord2i( 0,0 ); + glVertex2i( x,y - TextureBrowser_fontHeight( textureBrowser ) ); + glTexCoord2i( 1,0 ); + glVertex2i( x + nWidth,y - TextureBrowser_fontHeight( textureBrowser ) ); + glTexCoord2i( 1,1 ); + glVertex2i( x + nWidth,y - TextureBrowser_fontHeight( textureBrowser ) - nHeight ); + glTexCoord2i( 0,1 ); + glVertex2i( x,y - TextureBrowser_fontHeight( textureBrowser ) - nHeight ); + glEnd(); + + // draw the texture name + glDisable( GL_TEXTURE_2D ); + glColor3f( 1,1,1 ); + + glRasterPos2i( x, y - TextureBrowser_fontHeight( textureBrowser ) + 5 ); + + // don't draw the directory name + const char* name = shader->getName(); + name += strlen( name ); + while ( name != shader->getName() && *( name - 1 ) != '/' && *( name - 1 ) != '\\' ) + name--; + + GlobalOpenGL().drawString( name ); + glEnable( GL_TEXTURE_2D ); + } + + //int totalHeight = abs(y) + last_height + TextureBrowser_fontHeight(textureBrowser) + 4; + } + + + // reset the current texture + glBindTexture( GL_TEXTURE_2D, 0 ); + //qglFinish(); +} + +void TextureBrowser_queueDraw( TextureBrowser& textureBrowser ){ + if ( textureBrowser.m_gl_widget ) { + gtk_widget_queue_draw( textureBrowser.m_gl_widget ); + } +} + + +void TextureBrowser_setScale( TextureBrowser& textureBrowser, std::size_t scale ){ + textureBrowser.m_textureScale = scale; + + TextureBrowser_queueDraw( textureBrowser ); +} + +void TextureBrowser_setUniformSize( TextureBrowser& textureBrowser, std::size_t scale ){ + textureBrowser.m_uniformTextureSize = scale; + + TextureBrowser_queueDraw( textureBrowser ); +} + + +void TextureBrowser_MouseWheel( TextureBrowser& textureBrowser, bool bUp ){ + int originy = TextureBrowser_getOriginY( textureBrowser ); + + if ( bUp ) { + originy += int(textureBrowser.m_mouseWheelScrollIncrement); + } + else + { + originy -= int(textureBrowser.m_mouseWheelScrollIncrement); + } + + TextureBrowser_setOriginY( textureBrowser, originy ); } XmlTagBuilder TagBuilder; -enum { - TAG_COLUMN, - N_COLUMNS -}; - -void BuildStoreAssignedTags(ui::ListStore store, const char *shader, TextureBrowser *textureBrowser) +enum { - GtkTreeIter iter; - - store.clear(); - - std::vector assigned_tags; - TagBuilder.GetShaderTags(shader, assigned_tags); - - for (size_t i = 0; i < assigned_tags.size(); i++) { - store.append(TAG_COLUMN, assigned_tags[i].c_str()); - } -} + TAG_COLUMN, + N_COLUMNS +}; -void BuildStoreAvailableTags(ui::ListStore storeAvailable, - ui::ListStore storeAssigned, - const std::set &allTags, - TextureBrowser *textureBrowser) -{ - GtkTreeIter iterAssigned; - GtkTreeIter iterAvailable; - std::set::const_iterator iterAll; - gchar *tag_assigned; - - storeAvailable.clear(); - - bool row = gtk_tree_model_get_iter_first(storeAssigned, &iterAssigned) != 0; - - if (!row) { // does the shader have tags assigned? - for (iterAll = allTags.begin(); iterAll != allTags.end(); ++iterAll) { - storeAvailable.append(TAG_COLUMN, (*iterAll).c_str()); - } - } else { - while (row) // available tags = all tags - assigned tags - { - gtk_tree_model_get(storeAssigned, &iterAssigned, TAG_COLUMN, &tag_assigned, -1); - - for (iterAll = allTags.begin(); iterAll != allTags.end(); ++iterAll) { - if (strcmp((char *) tag_assigned, (*iterAll).c_str()) != 0) { - storeAvailable.append(TAG_COLUMN, (*iterAll).c_str()); - } else { - row = gtk_tree_model_iter_next(storeAssigned, &iterAssigned) != 0; - - if (row) { - gtk_tree_model_get(storeAssigned, &iterAssigned, TAG_COLUMN, &tag_assigned, -1); - } - } - } - } - } -} - -gboolean TextureBrowser_button_press(ui::Widget widget, GdkEventButton *event, TextureBrowser *textureBrowser) -{ - if (event->type == GDK_BUTTON_PRESS) { - if (event->button == 3) { - if (GlobalTextureBrowser().m_tags) { - textureBrowser->m_rmbSelected = true; - TextureBrowser_Selection_MouseDown(*textureBrowser, event->state, static_cast( event->x ), - static_cast( event->y )); - - BuildStoreAssignedTags(textureBrowser->m_assigned_store, textureBrowser->shader.c_str(), - textureBrowser); - BuildStoreAvailableTags(textureBrowser->m_available_store, textureBrowser->m_assigned_store, - textureBrowser->m_all_tags, textureBrowser); - textureBrowser->m_heightChanged = true; - textureBrowser->m_tag_frame.show(); +void BuildStoreAssignedTags( ui::ListStore store, const char* shader, TextureBrowser* textureBrowser ){ + GtkTreeIter iter; + + store.clear(); + + std::vector assigned_tags; + TagBuilder.GetShaderTags( shader, assigned_tags ); + + for ( size_t i = 0; i < assigned_tags.size(); i++ ) + { + store.append(TAG_COLUMN, assigned_tags[i].c_str()); + } +} + +void BuildStoreAvailableTags( ui::ListStore storeAvailable, + ui::ListStore storeAssigned, + const std::set& allTags, + TextureBrowser* textureBrowser ){ + GtkTreeIter iterAssigned; + GtkTreeIter iterAvailable; + std::set::const_iterator iterAll; + gchar* tag_assigned; + + storeAvailable.clear(); + + bool row = gtk_tree_model_get_iter_first(storeAssigned, &iterAssigned ) != 0; + + if ( !row ) { // does the shader have tags assigned? + for ( iterAll = allTags.begin(); iterAll != allTags.end(); ++iterAll ) + { + storeAvailable.append(TAG_COLUMN, (*iterAll).c_str()); + } + } + else + { + while ( row ) // available tags = all tags - assigned tags + { + gtk_tree_model_get(storeAssigned, &iterAssigned, TAG_COLUMN, &tag_assigned, -1 ); + + for ( iterAll = allTags.begin(); iterAll != allTags.end(); ++iterAll ) + { + if ( strcmp( (char*)tag_assigned, ( *iterAll ).c_str() ) != 0 ) { + storeAvailable.append(TAG_COLUMN, (*iterAll).c_str()); + } + else + { + row = gtk_tree_model_iter_next(storeAssigned, &iterAssigned ) != 0; + + if ( row ) { + gtk_tree_model_get(storeAssigned, &iterAssigned, TAG_COLUMN, &tag_assigned, -1 ); + } + } + } + } + } +} + +gboolean TextureBrowser_button_press( ui::Widget widget, GdkEventButton* event, TextureBrowser* textureBrowser ){ + if ( event->type == GDK_BUTTON_PRESS ) { + if ( event->button == 3 ) { + if ( GlobalTextureBrowser().m_tags ) { + textureBrowser->m_rmbSelected = true; + TextureBrowser_Selection_MouseDown( *textureBrowser, event->state, static_cast( event->x ), static_cast( event->y ) ); + + BuildStoreAssignedTags( textureBrowser->m_assigned_store, textureBrowser->shader.c_str(), textureBrowser ); + BuildStoreAvailableTags( textureBrowser->m_available_store, textureBrowser->m_assigned_store, textureBrowser->m_all_tags, textureBrowser ); + textureBrowser->m_heightChanged = true; + textureBrowser->m_tag_frame.show(); ui::process(); - TextureBrowser_Focus(*textureBrowser, textureBrowser->shader.c_str()); - } else { - TextureBrowser_Tracking_MouseDown(*textureBrowser); - } - } else if (event->button == 1) { - TextureBrowser_Selection_MouseDown(*textureBrowser, event->state, static_cast( event->x ), - static_cast( event->y )); + TextureBrowser_Focus( *textureBrowser, textureBrowser->shader.c_str() ); + } + else + { + TextureBrowser_Tracking_MouseDown( *textureBrowser ); + } + } + else if ( event->button == 1 ) { + TextureBrowser_Selection_MouseDown( *textureBrowser, event->state, static_cast( event->x ), static_cast( event->y ) ); - if (GlobalTextureBrowser().m_tags) { - textureBrowser->m_rmbSelected = false; - textureBrowser->m_tag_frame.hide(); - } - } - } - return FALSE; + if ( GlobalTextureBrowser().m_tags ) { + textureBrowser->m_rmbSelected = false; + textureBrowser->m_tag_frame.hide(); + } + } + } + return FALSE; } -gboolean TextureBrowser_button_release(ui::Widget widget, GdkEventButton *event, TextureBrowser *textureBrowser) -{ - if (event->type == GDK_BUTTON_RELEASE) { - if (event->button == 3) { - if (!GlobalTextureBrowser().m_tags) { - TextureBrowser_Tracking_MouseUp(*textureBrowser); - } - } - } - return FALSE; +gboolean TextureBrowser_button_release( ui::Widget widget, GdkEventButton* event, TextureBrowser* textureBrowser ){ + if ( event->type == GDK_BUTTON_RELEASE ) { + if ( event->button == 3 ) { + if ( !GlobalTextureBrowser().m_tags ) { + TextureBrowser_Tracking_MouseUp( *textureBrowser ); + } + } + } + return FALSE; } -gboolean TextureBrowser_motion(ui::Widget widget, GdkEventMotion *event, TextureBrowser *textureBrowser) -{ - return FALSE; +gboolean TextureBrowser_motion( ui::Widget widget, GdkEventMotion *event, TextureBrowser* textureBrowser ){ + return FALSE; } -gboolean TextureBrowser_scroll(ui::Widget widget, GdkEventScroll *event, TextureBrowser *textureBrowser) -{ - if (event->direction == GDK_SCROLL_UP) { - TextureBrowser_MouseWheel(*textureBrowser, true); - } else if (event->direction == GDK_SCROLL_DOWN) { - TextureBrowser_MouseWheel(*textureBrowser, false); - } - return FALSE; +gboolean TextureBrowser_scroll( ui::Widget widget, GdkEventScroll* event, TextureBrowser* textureBrowser ){ + if ( event->direction == GDK_SCROLL_UP ) { + TextureBrowser_MouseWheel( *textureBrowser, true ); + } + else if ( event->direction == GDK_SCROLL_DOWN ) { + TextureBrowser_MouseWheel( *textureBrowser, false ); + } + return FALSE; } -void TextureBrowser_scrollChanged(void *data, gdouble value) -{ - //globalOutputStream() << "vertical scroll\n"; - TextureBrowser_setOriginY(*reinterpret_cast( data ), -(int) value); +void TextureBrowser_scrollChanged( void* data, gdouble value ){ + //globalOutputStream() << "vertical scroll\n"; + TextureBrowser_setOriginY( *reinterpret_cast( data ), -(int)value ); } -static void TextureBrowser_verticalScroll(ui::Adjustment adjustment, TextureBrowser *textureBrowser) -{ - textureBrowser->m_scrollAdjustment.value_changed(gtk_adjustment_get_value(adjustment)); +static void TextureBrowser_verticalScroll(ui::Adjustment adjustment, TextureBrowser* textureBrowser ){ + textureBrowser->m_scrollAdjustment.value_changed( gtk_adjustment_get_value(adjustment) ); } -void TextureBrowser_updateScroll(TextureBrowser &textureBrowser) -{ - if (textureBrowser.m_showTextureScrollbar) { - int totalHeight = TextureBrowser_TotalHeight(textureBrowser); +void TextureBrowser_updateScroll( TextureBrowser& textureBrowser ){ + if ( textureBrowser.m_showTextureScrollbar ) { + int totalHeight = TextureBrowser_TotalHeight( textureBrowser ); - totalHeight = std::max(totalHeight, textureBrowser.height); + totalHeight = std::max( totalHeight, textureBrowser.height ); - auto vadjustment = gtk_range_get_adjustment(GTK_RANGE(textureBrowser.m_texture_scroll)); + auto vadjustment = gtk_range_get_adjustment( GTK_RANGE( textureBrowser.m_texture_scroll ) ); - gtk_adjustment_set_value(vadjustment, -TextureBrowser_getOriginY(textureBrowser)); - gtk_adjustment_set_page_size(vadjustment, textureBrowser.height); - gtk_adjustment_set_page_increment(vadjustment, textureBrowser.height / 2); - gtk_adjustment_set_step_increment(vadjustment, 20); - gtk_adjustment_set_lower(vadjustment, 0); - gtk_adjustment_set_upper(vadjustment, totalHeight); + gtk_adjustment_set_value(vadjustment, -TextureBrowser_getOriginY( textureBrowser )); + gtk_adjustment_set_page_size(vadjustment, textureBrowser.height); + gtk_adjustment_set_page_increment(vadjustment, textureBrowser.height / 2); + gtk_adjustment_set_step_increment(vadjustment, 20); + gtk_adjustment_set_lower(vadjustment, 0); + gtk_adjustment_set_upper(vadjustment, totalHeight); - g_signal_emit_by_name(G_OBJECT(vadjustment), "changed"); - } + g_signal_emit_by_name( G_OBJECT( vadjustment ), "changed" ); + } } -gboolean TextureBrowser_size_allocate(ui::Widget widget, GtkAllocation *allocation, TextureBrowser *textureBrowser) -{ - textureBrowser->width = allocation->width; - textureBrowser->height = allocation->height; - TextureBrowser_heightChanged(*textureBrowser); - textureBrowser->m_originInvalid = true; - TextureBrowser_queueDraw(*textureBrowser); - return FALSE; +gboolean TextureBrowser_size_allocate( ui::Widget widget, GtkAllocation* allocation, TextureBrowser* textureBrowser ){ + textureBrowser->width = allocation->width; + textureBrowser->height = allocation->height; + TextureBrowser_heightChanged( *textureBrowser ); + textureBrowser->m_originInvalid = true; + TextureBrowser_queueDraw( *textureBrowser ); + return FALSE; } -gboolean TextureBrowser_expose(ui::Widget widget, GdkEventExpose *event, TextureBrowser *textureBrowser) -{ - if (glwidget_make_current(textureBrowser->m_gl_widget) != FALSE) { - GlobalOpenGL_debugAssertNoErrors(); - TextureBrowser_evaluateHeight(*textureBrowser); - Texture_Draw(*textureBrowser); - GlobalOpenGL_debugAssertNoErrors(); - glwidget_swap_buffers(textureBrowser->m_gl_widget); - } - return FALSE; +gboolean TextureBrowser_expose( ui::Widget widget, GdkEventExpose* event, TextureBrowser* textureBrowser ){ + if ( glwidget_make_current( textureBrowser->m_gl_widget ) != FALSE ) { + GlobalOpenGL_debugAssertNoErrors(); + TextureBrowser_evaluateHeight( *textureBrowser ); + Texture_Draw( *textureBrowser ); + GlobalOpenGL_debugAssertNoErrors(); + glwidget_swap_buffers( textureBrowser->m_gl_widget ); + } + return FALSE; } TextureBrowser g_TextureBrowser; -TextureBrowser &GlobalTextureBrowser() -{ - return g_TextureBrowser; +TextureBrowser& GlobalTextureBrowser(){ + return g_TextureBrowser; } -bool TextureBrowser_hideUnused() -{ - return g_TextureBrowser.m_hideUnused; +bool TextureBrowser_hideUnused(){ + return g_TextureBrowser.m_hideUnused; } -void TextureBrowser_ToggleHideUnused() -{ - if (g_TextureBrowser.m_hideUnused) { - TextureBrowser_SetHideUnused(g_TextureBrowser, false); - } else { - TextureBrowser_SetHideUnused(g_TextureBrowser, true); - } +void TextureBrowser_ToggleHideUnused(){ + if ( g_TextureBrowser.m_hideUnused ) { + TextureBrowser_SetHideUnused( g_TextureBrowser, false ); + } + else + { + TextureBrowser_SetHideUnused( g_TextureBrowser, true ); + } } -void TextureGroups_constructTreeModel(TextureGroups groups, ui::TreeStore store) -{ - // put the information from the old textures menu into a treeview - GtkTreeIter iter, child; - - TextureGroups::const_iterator i = groups.begin(); - while (i != groups.end()) { - const char *dirName = (*i).c_str(); - const char *firstUnderscore = strchr(dirName, '_'); - StringRange dirRoot(dirName, (firstUnderscore == 0) ? dirName : firstUnderscore + 1); - - TextureGroups::const_iterator next = i; - ++next; - if (firstUnderscore != 0 - && next != groups.end() - && string_equal_start((*next).c_str(), dirRoot)) { - gtk_tree_store_append(store, &iter, NULL); - gtk_tree_store_set(store, &iter, 0, CopiedString(StringRange(dirName, firstUnderscore)).c_str(), -1); - - // keep going... - while (i != groups.end() && string_equal_start((*i).c_str(), dirRoot)) { - gtk_tree_store_append(store, &child, &iter); - gtk_tree_store_set(store, &child, 0, (*i).c_str(), -1); - ++i; - } - } else { - gtk_tree_store_append(store, &iter, NULL); - gtk_tree_store_set(store, &iter, 0, dirName, -1); - ++i; - } - } -} - -TextureGroups TextureGroups_constructTreeView() -{ - TextureGroups groups; +void TextureGroups_constructTreeModel( TextureGroups groups, ui::TreeStore store ){ + // put the information from the old textures menu into a treeview + GtkTreeIter iter, child; - if (TextureBrowser_showWads()) { - GlobalFileSystem().forEachArchive(TextureGroupsAddWadCaller(groups)); - } else { - // scan texture dirs and pak files only if not restricting to shaderlist - if (g_pGameDescription->mGameType != "doom3" && !g_TextureBrowser_shaderlistOnly) { - GlobalFileSystem().forEachDirectory("textures/", TextureGroupsAddDirectoryCaller(groups)); - } + TextureGroups::const_iterator i = groups.begin(); + while ( i != groups.end() ) + { + const char* dirName = ( *i ).c_str(); + const char* firstUnderscore = strchr( dirName, '_' ); + StringRange dirRoot( dirName, ( firstUnderscore == 0 ) ? dirName : firstUnderscore + 1 ); - GlobalShaderSystem().foreachShaderName(TextureGroupsAddShaderCaller(groups)); - } + TextureGroups::const_iterator next = i; + ++next; + if ( firstUnderscore != 0 + && next != groups.end() + && string_equal_start( ( *next ).c_str(), dirRoot ) ) { + gtk_tree_store_append( store, &iter, NULL ); + gtk_tree_store_set( store, &iter, 0, CopiedString( StringRange( dirName, firstUnderscore ) ).c_str(), -1 ); - return groups; + // keep going... + while ( i != groups.end() && string_equal_start( ( *i ).c_str(), dirRoot ) ) + { + gtk_tree_store_append( store, &child, &iter ); + gtk_tree_store_set( store, &child, 0, ( *i ).c_str(), -1 ); + ++i; + } + } + else + { + gtk_tree_store_append( store, &iter, NULL ); + gtk_tree_store_set( store, &iter, 0, dirName, -1 ); + ++i; + } + } } -void TextureBrowser_constructTreeStore() -{ - TextureGroups groups = TextureGroups_constructTreeView(); - auto store = ui::TreeStore::from(gtk_tree_store_new(1, G_TYPE_STRING)); - TextureGroups_constructTreeModel(groups, store); +TextureGroups TextureGroups_constructTreeView(){ + TextureGroups groups; + + if ( TextureBrowser_showWads() ) { + GlobalFileSystem().forEachArchive( TextureGroupsAddWadCaller( groups ) ); + } + else + { + // scan texture dirs and pak files only if not restricting to shaderlist + if ( g_pGameDescription->mGameType != "doom3" && !g_TextureBrowser_shaderlistOnly ) { + GlobalFileSystem().forEachDirectory( "textures/", TextureGroupsAddDirectoryCaller( groups ) ); + } - gtk_tree_view_set_model(g_TextureBrowser.m_treeViewTree, store); + GlobalShaderSystem().foreachShaderName( TextureGroupsAddShaderCaller( groups ) ); + } - g_object_unref(G_OBJECT(store)); + return groups; } -void TextureBrowser_constructTreeStoreTags() -{ - TextureGroups groups; - auto store = ui::TreeStore::from(gtk_tree_store_new(1, G_TYPE_STRING)); +void TextureBrowser_constructTreeStore(){ + TextureGroups groups = TextureGroups_constructTreeView(); + auto store = ui::TreeStore::from(gtk_tree_store_new( 1, G_TYPE_STRING )); + TextureGroups_constructTreeModel( groups, store ); + + gtk_tree_view_set_model(g_TextureBrowser.m_treeViewTree, store); + + g_object_unref( G_OBJECT( store ) ); +} + +void TextureBrowser_constructTreeStoreTags(){ + TextureGroups groups; + auto store = ui::TreeStore::from(gtk_tree_store_new( 1, G_TYPE_STRING )); auto model = g_TextureBrowser.m_all_tags_list; - gtk_tree_view_set_model(g_TextureBrowser.m_treeViewTags, model); + gtk_tree_view_set_model(g_TextureBrowser.m_treeViewTags, model ); - g_object_unref(G_OBJECT(store)); + g_object_unref( G_OBJECT( store ) ); } -void TreeView_onRowActivated(ui::TreeView treeview, ui::TreePath path, ui::TreeViewColumn col, gpointer userdata) -{ - GtkTreeIter iter; +void TreeView_onRowActivated( ui::TreeView treeview, ui::TreePath path, ui::TreeViewColumn col, gpointer userdata ){ + GtkTreeIter iter; - auto model = gtk_tree_view_get_model(treeview); + auto model = gtk_tree_view_get_model(treeview ); - if (gtk_tree_model_get_iter(model, &iter, path)) { - gchar dirName[1024]; + if ( gtk_tree_model_get_iter( model, &iter, path ) ) { + gchar dirName[1024]; - gchar *buffer; - gtk_tree_model_get(model, &iter, 0, &buffer, -1); - strcpy(dirName, buffer); - g_free(buffer); + gchar* buffer; + gtk_tree_model_get( model, &iter, 0, &buffer, -1 ); + strcpy( dirName, buffer ); + g_free( buffer ); - g_TextureBrowser.m_searchedTags = false; + g_TextureBrowser.m_searchedTags = false; - if (!TextureBrowser_showWads()) { - strcat(dirName, "/"); - } + if ( !TextureBrowser_showWads() ) { + strcat( dirName, "/" ); + } - ScopeDisableScreenUpdates disableScreenUpdates(dirName, "Loading Textures"); - TextureBrowser_ShowDirectory(GlobalTextureBrowser(), dirName); - TextureBrowser_queueDraw(GlobalTextureBrowser()); - } + ScopeDisableScreenUpdates disableScreenUpdates( dirName, "Loading Textures" ); + TextureBrowser_ShowDirectory( GlobalTextureBrowser(), dirName ); + TextureBrowser_queueDraw( GlobalTextureBrowser() ); + } } -void TextureBrowser_createTreeViewTree() -{ - gtk_tree_view_set_enable_search(g_TextureBrowser.m_treeViewTree, FALSE); +void TextureBrowser_createTreeViewTree(){ + gtk_tree_view_set_enable_search(g_TextureBrowser.m_treeViewTree, FALSE ); - gtk_tree_view_set_headers_visible(g_TextureBrowser.m_treeViewTree, FALSE); - g_TextureBrowser.m_treeViewTree.connect("row-activated", (GCallback) TreeView_onRowActivated, NULL); + gtk_tree_view_set_headers_visible(g_TextureBrowser.m_treeViewTree, FALSE ); + g_TextureBrowser.m_treeViewTree.connect( "row-activated", (GCallback) TreeView_onRowActivated, NULL ); - auto renderer = ui::CellRendererText(ui::New); - gtk_tree_view_insert_column_with_attributes(g_TextureBrowser.m_treeViewTree, -1, "", renderer, "text", 0, NULL); + auto renderer = ui::CellRendererText(ui::New); + gtk_tree_view_insert_column_with_attributes(g_TextureBrowser.m_treeViewTree, -1, "", renderer, "text", 0, NULL ); - TextureBrowser_constructTreeStore(); + TextureBrowser_constructTreeStore(); } void TextureBrowser_addTag(); @@ -1698,1060 +1645,1008 @@ void TextureBrowser_renameTag(); void TextureBrowser_deleteTag(); -void TextureBrowser_createContextMenu(ui::Widget treeview, GdkEventButton *event) -{ - ui::Widget menu = ui::Menu(ui::New); +void TextureBrowser_createContextMenu( ui::Widget treeview, GdkEventButton *event ){ + ui::Widget menu = ui::Menu(ui::New); - ui::Widget menuitem = ui::MenuItem("Add tag"); - menuitem.connect("activate", (GCallback) TextureBrowser_addTag, treeview); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + ui::Widget menuitem = ui::MenuItem( "Add tag" ); + menuitem.connect( "activate", (GCallback)TextureBrowser_addTag, treeview ); + gtk_menu_shell_append( GTK_MENU_SHELL( menu ), menuitem ); - menuitem = ui::MenuItem("Rename tag"); - menuitem.connect("activate", (GCallback) TextureBrowser_renameTag, treeview); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + menuitem = ui::MenuItem( "Rename tag" ); + menuitem.connect( "activate", (GCallback)TextureBrowser_renameTag, treeview ); + gtk_menu_shell_append( GTK_MENU_SHELL( menu ), menuitem ); - menuitem = ui::MenuItem("Delete tag"); - menuitem.connect("activate", (GCallback) TextureBrowser_deleteTag, treeview); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + menuitem = ui::MenuItem( "Delete tag" ); + menuitem.connect( "activate", (GCallback)TextureBrowser_deleteTag, treeview ); + gtk_menu_shell_append( GTK_MENU_SHELL( menu ), menuitem ); - gtk_widget_show_all(menu); + gtk_widget_show_all( menu ); - gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, - (event != NULL) ? event->button : 0, - gdk_event_get_time((GdkEvent *) event)); + gtk_menu_popup( GTK_MENU( menu ), NULL, NULL, NULL, NULL, + ( event != NULL ) ? event->button : 0, + gdk_event_get_time( (GdkEvent*)event ) ); } -gboolean TreeViewTags_onButtonPressed(ui::TreeView treeview, GdkEventButton *event) -{ - if (event->type == GDK_BUTTON_PRESS && event->button == 3) { - GtkTreePath *path; - auto selection = gtk_tree_view_get_selection(treeview); +gboolean TreeViewTags_onButtonPressed( ui::TreeView treeview, GdkEventButton *event ){ + if ( event->type == GDK_BUTTON_PRESS && event->button == 3 ) { + GtkTreePath *path; + auto selection = gtk_tree_view_get_selection(treeview ); - if (gtk_tree_view_get_path_at_pos(treeview, event->x, event->y, &path, NULL, NULL, NULL)) { - gtk_tree_selection_unselect_all(selection); - gtk_tree_selection_select_path(selection, path); - gtk_tree_path_free(path); - } + if ( gtk_tree_view_get_path_at_pos(treeview, event->x, event->y, &path, NULL, NULL, NULL ) ) { + gtk_tree_selection_unselect_all( selection ); + gtk_tree_selection_select_path( selection, path ); + gtk_tree_path_free( path ); + } - TextureBrowser_createContextMenu(treeview, event); - return TRUE; - } - return FALSE; + TextureBrowser_createContextMenu( treeview, event ); + return TRUE; + } + return FALSE; } -void TextureBrowser_createTreeViewTags() -{ - g_TextureBrowser.m_treeViewTags = ui::TreeView(ui::New); - gtk_tree_view_set_enable_search(g_TextureBrowser.m_treeViewTags, FALSE); +void TextureBrowser_createTreeViewTags(){ + g_TextureBrowser.m_treeViewTags = ui::TreeView(ui::New); + gtk_tree_view_set_enable_search(g_TextureBrowser.m_treeViewTags, FALSE ); - g_TextureBrowser.m_treeViewTags.connect("button-press-event", (GCallback) TreeViewTags_onButtonPressed, NULL); + g_TextureBrowser.m_treeViewTags.connect( "button-press-event", (GCallback)TreeViewTags_onButtonPressed, NULL ); - gtk_tree_view_set_headers_visible(g_TextureBrowser.m_treeViewTags, FALSE); + gtk_tree_view_set_headers_visible(g_TextureBrowser.m_treeViewTags, FALSE ); - auto renderer = ui::CellRendererText(ui::New); - gtk_tree_view_insert_column_with_attributes(g_TextureBrowser.m_treeViewTags, -1, "", renderer, "text", 0, NULL); + auto renderer = ui::CellRendererText(ui::New); + gtk_tree_view_insert_column_with_attributes(g_TextureBrowser.m_treeViewTags, -1, "", renderer, "text", 0, NULL ); - TextureBrowser_constructTreeStoreTags(); + TextureBrowser_constructTreeStoreTags(); } -ui::MenuItem TextureBrowser_constructViewMenu(ui::Menu menu) -{ - ui::MenuItem textures_menu_item = ui::MenuItem(new_sub_menu_item_with_mnemonic("_View")); +ui::MenuItem TextureBrowser_constructViewMenu( ui::Menu menu ){ + ui::MenuItem textures_menu_item = ui::MenuItem(new_sub_menu_item_with_mnemonic( "_View" )); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } - create_check_menu_item_with_mnemonic(menu, "Hide _Unused", "ShowInUse"); - if (string_empty(g_pGameDescription->getKeyValue("show_wads"))) { - create_check_menu_item_with_mnemonic(menu, "Hide Image Missing", "FilterMissing"); - } + create_check_menu_item_with_mnemonic( menu, "Hide _Unused", "ShowInUse" ); + if ( string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) { + create_check_menu_item_with_mnemonic( menu, "Hide Image Missing", "FilterMissing" ); + } - // hide notex and shadernotex on texture browser: no one wants to apply them - create_check_menu_item_with_mnemonic(menu, "Hide Fallback", "FilterFallback"); + // hide notex and shadernotex on texture browser: no one wants to apply them + create_check_menu_item_with_mnemonic( menu, "Hide Fallback", "FilterFallback" ); - menu_separator(menu); + menu_separator( menu ); - create_menu_item_with_mnemonic(menu, "Show All", "ShowAllTextures"); + create_menu_item_with_mnemonic( menu, "Show All", "ShowAllTextures" ); - // we always want to show shaders but don't want a "Show Shaders" menu for doom3 and .wad file games - if (g_pGameDescription->mGameType == "doom3" || !string_empty(g_pGameDescription->getKeyValue("show_wads"))) { - g_TextureBrowser.m_showShaders = true; - } else { - create_check_menu_item_with_mnemonic(menu, "Show shaders", "ToggleShowShaders"); - } + // we always want to show shaders but don't want a "Show Shaders" menu for doom3 and .wad file games + if ( g_pGameDescription->mGameType == "doom3" || !string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) { + g_TextureBrowser.m_showShaders = true; + } + else + { + create_check_menu_item_with_mnemonic( menu, "Show shaders", "ToggleShowShaders" ); + } - if (g_pGameDescription->mGameType != "doom3" && string_empty(g_pGameDescription->getKeyValue("show_wads"))) { - create_check_menu_item_with_mnemonic(menu, "Shaders Only", "ToggleShowShaderlistOnly"); - } - if (g_TextureBrowser.m_tags) { - create_menu_item_with_mnemonic(menu, "Show Untagged", "ShowUntagged"); - } + if ( g_pGameDescription->mGameType != "doom3" && string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) { + create_check_menu_item_with_mnemonic( menu, "Shaders Only", "ToggleShowShaderlistOnly" ); + } + if ( g_TextureBrowser.m_tags ) { + create_menu_item_with_mnemonic( menu, "Show Untagged", "ShowUntagged" ); + } - menu_separator(menu); - create_check_menu_item_with_mnemonic(menu, "Fixed Size", "FixedSize"); - create_check_menu_item_with_mnemonic(menu, "Transparency", "EnableAlpha"); + menu_separator( menu ); + create_check_menu_item_with_mnemonic( menu, "Fixed Size", "FixedSize" ); + create_check_menu_item_with_mnemonic( menu, "Transparency", "EnableAlpha" ); - if (string_empty(g_pGameDescription->getKeyValue("show_wads"))) { - menu_separator(menu); - g_TextureBrowser.m_shader_info_item = ui::Widget( - create_menu_item_with_mnemonic(menu, "Shader Info", "ShaderInfo")); - gtk_widget_set_sensitive(g_TextureBrowser.m_shader_info_item, FALSE); - } + if ( string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) { + menu_separator( menu ); + g_TextureBrowser.m_shader_info_item = ui::Widget(create_menu_item_with_mnemonic( menu, "Shader Info", "ShaderInfo" )); + gtk_widget_set_sensitive( g_TextureBrowser.m_shader_info_item, FALSE ); + } - return textures_menu_item; + return textures_menu_item; } -ui::MenuItem TextureBrowser_constructToolsMenu(ui::Menu menu) -{ - ui::MenuItem textures_menu_item = ui::MenuItem(new_sub_menu_item_with_mnemonic("_Tools")); +ui::MenuItem TextureBrowser_constructToolsMenu( ui::Menu menu ){ + ui::MenuItem textures_menu_item = ui::MenuItem(new_sub_menu_item_with_mnemonic( "_Tools" )); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } - create_menu_item_with_mnemonic(menu, "Flush & Reload Shaders", "RefreshShaders"); - create_menu_item_with_mnemonic(menu, "Find / Replace...", "FindReplaceTextures"); + create_menu_item_with_mnemonic( menu, "Flush & Reload Shaders", "RefreshShaders" ); + create_menu_item_with_mnemonic( menu, "Find / Replace...", "FindReplaceTextures" ); - return textures_menu_item; + return textures_menu_item; } -ui::MenuItem TextureBrowser_constructTagsMenu(ui::Menu menu) -{ - ui::MenuItem textures_menu_item = ui::MenuItem(new_sub_menu_item_with_mnemonic("T_ags")); +ui::MenuItem TextureBrowser_constructTagsMenu( ui::Menu menu ){ + ui::MenuItem textures_menu_item = ui::MenuItem(new_sub_menu_item_with_mnemonic( "T_ags" )); - if (g_Layout_enableDetachableMenus.m_value) { - menu_tearoff(menu); - } + if ( g_Layout_enableDetachableMenus.m_value ) { + menu_tearoff( menu ); + } - create_menu_item_with_mnemonic(menu, "Add tag", "AddTag"); - create_menu_item_with_mnemonic(menu, "Rename tag", "RenameTag"); - create_menu_item_with_mnemonic(menu, "Delete tag", "DeleteTag"); - menu_separator(menu); - create_menu_item_with_mnemonic(menu, "Copy tags from selected", "CopyTag"); - create_menu_item_with_mnemonic(menu, "Paste tags to selected", "PasteTag"); + create_menu_item_with_mnemonic( menu, "Add tag", "AddTag" ); + create_menu_item_with_mnemonic( menu, "Rename tag", "RenameTag" ); + create_menu_item_with_mnemonic( menu, "Delete tag", "DeleteTag" ); + menu_separator( menu ); + create_menu_item_with_mnemonic( menu, "Copy tags from selected", "CopyTag" ); + create_menu_item_with_mnemonic( menu, "Paste tags to selected", "PasteTag" ); - return textures_menu_item; + return textures_menu_item; } -gboolean TextureBrowser_tagMoveHelper(ui::TreeModel model, ui::TreePath path, GtkTreeIter iter, GSList **selected) -{ - g_assert(selected != NULL); +gboolean TextureBrowser_tagMoveHelper( ui::TreeModel model, ui::TreePath path, GtkTreeIter iter, GSList** selected ){ + g_assert( selected != NULL ); - auto rowref = gtk_tree_row_reference_new(model, path); - *selected = g_slist_append(*selected, rowref); + auto rowref = gtk_tree_row_reference_new( model, path ); + *selected = g_slist_append( *selected, rowref ); - return FALSE; + return FALSE; } -void TextureBrowser_assignTags() -{ - GSList *selected = NULL; - GSList *node; - gchar *tag_assigned; - - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree); - - gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) TextureBrowser_tagMoveHelper, - &selected); - - if (selected != NULL) { - for (node = selected; node != NULL; node = node->next) { - auto path = gtk_tree_row_reference_get_path((GtkTreeRowReference *) node->data); - - if (path) { - GtkTreeIter iter; - - if (gtk_tree_model_get_iter(g_TextureBrowser.m_available_store, &iter, path)) { - gtk_tree_model_get(g_TextureBrowser.m_available_store, &iter, TAG_COLUMN, &tag_assigned, -1); - if (!TagBuilder.CheckShaderTag(g_TextureBrowser.shader.c_str())) { - // create a custom shader/texture entry - IShader *ishader = QERApp_Shader_ForName(g_TextureBrowser.shader.c_str()); - CopiedString filename = ishader->getShaderFileName(); - - if (filename.empty()) { - // it's a texture - TagBuilder.AddShaderNode(g_TextureBrowser.shader.c_str(), CUSTOM, TEXTURE); - } else { - // it's a shader - TagBuilder.AddShaderNode(g_TextureBrowser.shader.c_str(), CUSTOM, SHADER); - } - ishader->DecRef(); - } - TagBuilder.AddShaderTag(g_TextureBrowser.shader.c_str(), (char *) tag_assigned, TAG); - - gtk_list_store_remove(g_TextureBrowser.m_available_store, &iter); - g_TextureBrowser.m_assigned_store.append(TAG_COLUMN, tag_assigned); - } - } - } - - g_slist_foreach(selected, (GFunc) gtk_tree_row_reference_free, NULL); - - // Save changes - TagBuilder.SaveXmlDoc(); - } - g_slist_free(selected); -} - -void TextureBrowser_removeTags() -{ - GSList *selected = NULL; - GSList *node; - gchar *tag; +void TextureBrowser_assignTags(){ + GSList* selected = NULL; + GSList* node; + gchar* tag_assigned; + + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree ); - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_assigned_tree); + gtk_tree_selection_selected_foreach( selection, (GtkTreeSelectionForeachFunc)TextureBrowser_tagMoveHelper, &selected ); - gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) TextureBrowser_tagMoveHelper, - &selected); + if ( selected != NULL ) { + for ( node = selected; node != NULL; node = node->next ) + { + auto path = gtk_tree_row_reference_get_path( (GtkTreeRowReference*)node->data ); - if (selected != NULL) { - for (node = selected; node != NULL; node = node->next) { - auto path = gtk_tree_row_reference_get_path((GtkTreeRowReference *) node->data); + if ( path ) { + GtkTreeIter iter; - if (path) { - GtkTreeIter iter; + if ( gtk_tree_model_get_iter(g_TextureBrowser.m_available_store, &iter, path ) ) { + gtk_tree_model_get(g_TextureBrowser.m_available_store, &iter, TAG_COLUMN, &tag_assigned, -1 ); + if ( !TagBuilder.CheckShaderTag( g_TextureBrowser.shader.c_str() ) ) { + // create a custom shader/texture entry + IShader* ishader = QERApp_Shader_ForName( g_TextureBrowser.shader.c_str() ); + CopiedString filename = ishader->getShaderFileName(); - if (gtk_tree_model_get_iter(g_TextureBrowser.m_assigned_store, &iter, path)) { - gtk_tree_model_get(g_TextureBrowser.m_assigned_store, &iter, TAG_COLUMN, &tag, -1); - TagBuilder.DeleteShaderTag(g_TextureBrowser.shader.c_str(), tag); - gtk_list_store_remove(g_TextureBrowser.m_assigned_store, &iter); - } - } - } + if ( filename.empty() ) { + // it's a texture + TagBuilder.AddShaderNode( g_TextureBrowser.shader.c_str(), CUSTOM, TEXTURE ); + } + else { + // it's a shader + TagBuilder.AddShaderNode( g_TextureBrowser.shader.c_str(), CUSTOM, SHADER ); + } + ishader->DecRef(); + } + TagBuilder.AddShaderTag( g_TextureBrowser.shader.c_str(), (char*)tag_assigned, TAG ); - g_slist_foreach(selected, (GFunc) gtk_tree_row_reference_free, NULL); + gtk_list_store_remove( g_TextureBrowser.m_available_store, &iter ); + g_TextureBrowser.m_assigned_store.append(TAG_COLUMN, tag_assigned); + } + } + } - // Update the "available tags list" - BuildStoreAvailableTags(g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, - g_TextureBrowser.m_all_tags, &g_TextureBrowser); + g_slist_foreach( selected, (GFunc)gtk_tree_row_reference_free, NULL ); - // Save changes - TagBuilder.SaveXmlDoc(); - } - g_slist_free(selected); + // Save changes + TagBuilder.SaveXmlDoc(); + } + g_slist_free( selected ); } -void TextureBrowser_buildTagList() -{ - g_TextureBrowser.m_all_tags_list.clear(); +void TextureBrowser_removeTags(){ + GSList* selected = NULL; + GSList* node; + gchar* tag; + + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_assigned_tree ); + + gtk_tree_selection_selected_foreach( selection, (GtkTreeSelectionForeachFunc)TextureBrowser_tagMoveHelper, &selected ); + + if ( selected != NULL ) { + for ( node = selected; node != NULL; node = node->next ) + { + auto path = gtk_tree_row_reference_get_path( (GtkTreeRowReference*)node->data ); - std::set::iterator iter; + if ( path ) { + GtkTreeIter iter; - for (iter = g_TextureBrowser.m_all_tags.begin(); iter != g_TextureBrowser.m_all_tags.end(); ++iter) { - g_TextureBrowser.m_all_tags_list.append(TAG_COLUMN, (*iter).c_str()); - } + if ( gtk_tree_model_get_iter(g_TextureBrowser.m_assigned_store, &iter, path ) ) { + gtk_tree_model_get(g_TextureBrowser.m_assigned_store, &iter, TAG_COLUMN, &tag, -1 ); + TagBuilder.DeleteShaderTag( g_TextureBrowser.shader.c_str(), tag ); + gtk_list_store_remove( g_TextureBrowser.m_assigned_store, &iter ); + } + } + } + + g_slist_foreach( selected, (GFunc)gtk_tree_row_reference_free, NULL ); + + // Update the "available tags list" + BuildStoreAvailableTags( g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, g_TextureBrowser.m_all_tags, &g_TextureBrowser ); + + // Save changes + TagBuilder.SaveXmlDoc(); + } + g_slist_free( selected ); } -void TextureBrowser_searchTags() -{ - GSList *selected = NULL; - GSList *node; - gchar *tag; - char buffer[256]; - char tags_searched[256]; +void TextureBrowser_buildTagList(){ + g_TextureBrowser.m_all_tags_list.clear(); + + std::set::iterator iter; + + for ( iter = g_TextureBrowser.m_all_tags.begin(); iter != g_TextureBrowser.m_all_tags.end(); ++iter ) + { + g_TextureBrowser.m_all_tags_list.append(TAG_COLUMN, (*iter).c_str()); + } +} + +void TextureBrowser_searchTags(){ + GSList* selected = NULL; + GSList* node; + gchar* tag; + char buffer[256]; + char tags_searched[256]; - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags); + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags ); - gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc) TextureBrowser_tagMoveHelper, - &selected); + gtk_tree_selection_selected_foreach( selection, (GtkTreeSelectionForeachFunc)TextureBrowser_tagMoveHelper, &selected ); - if (selected != NULL) { - strcpy(buffer, "/root/*/*[tag='"); - strcpy(tags_searched, "[TAGS] "); + if ( selected != NULL ) { + strcpy( buffer, "/root/*/*[tag='" ); + strcpy( tags_searched, "[TAGS] " ); - for (node = selected; node != NULL; node = node->next) { - auto path = gtk_tree_row_reference_get_path((GtkTreeRowReference *) node->data); + for ( node = selected; node != NULL; node = node->next ) + { + auto path = gtk_tree_row_reference_get_path( (GtkTreeRowReference*)node->data ); - if (path) { - GtkTreeIter iter; + if ( path ) { + GtkTreeIter iter; - if (gtk_tree_model_get_iter(g_TextureBrowser.m_all_tags_list, &iter, path)) { - gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iter, TAG_COLUMN, &tag, -1); + if ( gtk_tree_model_get_iter(g_TextureBrowser.m_all_tags_list, &iter, path ) ) { + gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iter, TAG_COLUMN, &tag, -1 ); - strcat(buffer, tag); - strcat(tags_searched, tag); - if (node != g_slist_last(node)) { - strcat(buffer, "' and tag='"); - strcat(tags_searched, ", "); - } - } - } - } + strcat( buffer, tag ); + strcat( tags_searched, tag ); + if ( node != g_slist_last( node ) ) { + strcat( buffer, "' and tag='" ); + strcat( tags_searched, ", " ); + } + } + } + } - strcat(buffer, "']"); + strcat( buffer, "']" ); - g_slist_foreach(selected, (GFunc) gtk_tree_row_reference_free, NULL); + g_slist_foreach( selected, (GFunc)gtk_tree_row_reference_free, NULL ); - g_TextureBrowser.m_found_shaders.clear(); // delete old list - TagBuilder.TagSearch(buffer, g_TextureBrowser.m_found_shaders); + g_TextureBrowser.m_found_shaders.clear(); // delete old list + TagBuilder.TagSearch( buffer, g_TextureBrowser.m_found_shaders ); - if (!g_TextureBrowser.m_found_shaders.empty()) { // found something - size_t shaders_found = g_TextureBrowser.m_found_shaders.size(); + if ( !g_TextureBrowser.m_found_shaders.empty() ) { // found something + size_t shaders_found = g_TextureBrowser.m_found_shaders.size(); - globalOutputStream() << "Found " << (unsigned int) shaders_found << " textures and shaders with " - << tags_searched << "\n"; - ScopeDisableScreenUpdates disableScreenUpdates("Searching...", "Loading Textures"); + globalOutputStream() << "Found " << (unsigned int)shaders_found << " textures and shaders with " << tags_searched << "\n"; + ScopeDisableScreenUpdates disableScreenUpdates( "Searching...", "Loading Textures" ); - std::set::iterator iter; + std::set::iterator iter; - for (iter = g_TextureBrowser.m_found_shaders.begin(); - iter != g_TextureBrowser.m_found_shaders.end(); iter++) { - std::string path = (*iter).c_str(); - size_t pos = path.find_last_of("/", path.size()); - std::string name = path.substr(pos + 1, path.size()); - path = path.substr(0, pos + 1); - TextureDirectory_loadTexture(path.c_str(), name.c_str()); - } - } - g_TextureBrowser.m_searchedTags = true; - g_TextureBrowser_currentDirectory = tags_searched; + for ( iter = g_TextureBrowser.m_found_shaders.begin(); iter != g_TextureBrowser.m_found_shaders.end(); iter++ ) + { + std::string path = ( *iter ).c_str(); + size_t pos = path.find_last_of( "/", path.size() ); + std::string name = path.substr( pos + 1, path.size() ); + path = path.substr( 0, pos + 1 ); + TextureDirectory_loadTexture( path.c_str(), name.c_str() ); + } + } + g_TextureBrowser.m_searchedTags = true; + g_TextureBrowser_currentDirectory = tags_searched; - g_TextureBrowser.m_nTotalHeight = 0; - TextureBrowser_setOriginY(g_TextureBrowser, 0); - TextureBrowser_heightChanged(g_TextureBrowser); - TextureBrowser_updateTitle(); - } - g_slist_free(selected); + g_TextureBrowser.m_nTotalHeight = 0; + TextureBrowser_setOriginY( g_TextureBrowser, 0 ); + TextureBrowser_heightChanged( g_TextureBrowser ); + TextureBrowser_updateTitle(); + } + g_slist_free( selected ); } -void TextureBrowser_toggleSearchButton() -{ - gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(g_TextureBrowser.m_tag_notebook)); +void TextureBrowser_toggleSearchButton(){ + gint page = gtk_notebook_get_current_page( GTK_NOTEBOOK( g_TextureBrowser.m_tag_notebook ) ); - if (page == 0) { // tag page - gtk_widget_show_all(g_TextureBrowser.m_search_button); - } else { - g_TextureBrowser.m_search_button.hide(); - } + if ( page == 0 ) { // tag page + gtk_widget_show_all( g_TextureBrowser.m_search_button ); + } + else { + g_TextureBrowser.m_search_button.hide(); + } } -void TextureBrowser_constructTagNotebook() -{ - g_TextureBrowser.m_tag_notebook = ui::Widget::from(gtk_notebook_new()); - ui::Widget labelTags = ui::Label("Tags"); - ui::Widget labelTextures = ui::Label("Textures"); +void TextureBrowser_constructTagNotebook(){ + g_TextureBrowser.m_tag_notebook = ui::Widget::from(gtk_notebook_new()); + ui::Widget labelTags = ui::Label( "Tags" ); + ui::Widget labelTextures = ui::Label( "Textures" ); - gtk_notebook_append_page(GTK_NOTEBOOK(g_TextureBrowser.m_tag_notebook), g_TextureBrowser.m_scr_win_tree, - labelTextures); - gtk_notebook_append_page(GTK_NOTEBOOK(g_TextureBrowser.m_tag_notebook), g_TextureBrowser.m_scr_win_tags, labelTags); + gtk_notebook_append_page( GTK_NOTEBOOK( g_TextureBrowser.m_tag_notebook ), g_TextureBrowser.m_scr_win_tree, labelTextures ); + gtk_notebook_append_page( GTK_NOTEBOOK( g_TextureBrowser.m_tag_notebook ), g_TextureBrowser.m_scr_win_tags, labelTags ); - g_TextureBrowser.m_tag_notebook.connect("switch-page", G_CALLBACK(TextureBrowser_toggleSearchButton), NULL); + g_TextureBrowser.m_tag_notebook.connect( "switch-page", G_CALLBACK( TextureBrowser_toggleSearchButton ), NULL ); - gtk_widget_show_all(g_TextureBrowser.m_tag_notebook); + gtk_widget_show_all( g_TextureBrowser.m_tag_notebook ); } -void TextureBrowser_constructSearchButton() -{ - auto image = ui::Widget::from(gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_SMALL_TOOLBAR)); - g_TextureBrowser.m_search_button = ui::Button(ui::New); - g_TextureBrowser.m_search_button.connect("clicked", G_CALLBACK(TextureBrowser_searchTags), NULL); - gtk_widget_set_tooltip_text(g_TextureBrowser.m_search_button, "Search with selected tags"); - g_TextureBrowser.m_search_button.add(image); +void TextureBrowser_constructSearchButton(){ + auto image = ui::Widget::from(gtk_image_new_from_stock( GTK_STOCK_FIND, GTK_ICON_SIZE_SMALL_TOOLBAR )); + g_TextureBrowser.m_search_button = ui::Button(ui::New); + g_TextureBrowser.m_search_button.connect( "clicked", G_CALLBACK( TextureBrowser_searchTags ), NULL ); + gtk_widget_set_tooltip_text(g_TextureBrowser.m_search_button, "Search with selected tags"); + g_TextureBrowser.m_search_button.add(image); } -void TextureBrowser_checkTagFile() -{ - const char SHADERTAG_FILE[] = "shadertags.xml"; - CopiedString default_filename, rc_filename; - StringOutputStream stream(256); - - stream << LocalRcPath_get(); - stream << SHADERTAG_FILE; - rc_filename = stream.c_str(); - - if (file_exists(rc_filename.c_str())) { - g_TextureBrowser.m_tags = TagBuilder.OpenXmlDoc(rc_filename.c_str()); - - if (g_TextureBrowser.m_tags) { - globalOutputStream() << "Loading tag file " << rc_filename.c_str() << ".\n"; - } - } else { - // load default tagfile - stream.clear(); - stream << g_pGameDescription->mGameToolsPath.c_str(); - stream << SHADERTAG_FILE; - default_filename = stream.c_str(); - - if (file_exists(default_filename.c_str())) { - g_TextureBrowser.m_tags = TagBuilder.OpenXmlDoc(default_filename.c_str(), rc_filename.c_str()); - - if (g_TextureBrowser.m_tags) { - globalOutputStream() << "Loading default tag file " << default_filename.c_str() << ".\n"; - } - } else { - globalErrorStream() << "Unable to find default tag file " << default_filename.c_str() - << ". No tag support.\n"; - } - } -} - -void TextureBrowser_SetNotex() -{ - IShader *notex = QERApp_Shader_ForName(DEFAULT_NOTEX_NAME); - IShader *shadernotex = QERApp_Shader_ForName(DEFAULT_SHADERNOTEX_NAME); +void TextureBrowser_checkTagFile(){ + const char SHADERTAG_FILE[] = "shadertags.xml"; + CopiedString default_filename, rc_filename; + StringOutputStream stream( 256 ); + + stream << LocalRcPath_get(); + stream << SHADERTAG_FILE; + rc_filename = stream.c_str(); - g_notex = notex->getTexture()->name; - g_shadernotex = shadernotex->getTexture()->name; + if ( file_exists( rc_filename.c_str() ) ) { + g_TextureBrowser.m_tags = TagBuilder.OpenXmlDoc( rc_filename.c_str() ); + + if ( g_TextureBrowser.m_tags ) { + globalOutputStream() << "Loading tag file " << rc_filename.c_str() << ".\n"; + } + } + else + { + // load default tagfile + stream.clear(); + stream << g_pGameDescription->mGameToolsPath.c_str(); + stream << SHADERTAG_FILE; + default_filename = stream.c_str(); + + if ( file_exists( default_filename.c_str() ) ) { + g_TextureBrowser.m_tags = TagBuilder.OpenXmlDoc( default_filename.c_str(), rc_filename.c_str() ); + + if ( g_TextureBrowser.m_tags ) { + globalOutputStream() << "Loading default tag file " << default_filename.c_str() << ".\n"; + } + } + else + { + globalErrorStream() << "Unable to find default tag file " << default_filename.c_str() << ". No tag support.\n"; + } + } +} + +void TextureBrowser_SetNotex(){ + IShader* notex = QERApp_Shader_ForName( DEFAULT_NOTEX_NAME ); + IShader* shadernotex = QERApp_Shader_ForName( DEFAULT_SHADERNOTEX_NAME ); + + g_notex = notex->getTexture()->name; + g_shadernotex = shadernotex->getTexture()->name; notex->DecRef(); shadernotex->DecRef(); } -ui::Widget TextureBrowser_constructWindow(ui::Window toplevel) -{ - // The gl_widget and the tag assignment frame should be packed into a GtkVPaned with the slider - // position stored in local.pref. gtk_paned_get_position() and gtk_paned_set_position() don't - // seem to work in gtk 2.4 and the arrow buttons don't handle GTK_FILL, so here's another thing - // for the "once-the-gtk-libs-are-updated-TODO-list" :x - - TextureBrowser_checkTagFile(); - TextureBrowser_SetNotex(); - - GlobalShaderSystem().setActiveShadersChangedNotify( - ReferenceCaller(g_TextureBrowser)); - - g_TextureBrowser.m_parent = toplevel; - - auto table = ui::Table(3, 3, FALSE); - auto vbox = ui::VBox(FALSE, 0); - table.attach(vbox, {0, 1, 1, 3}, {GTK_FILL, GTK_FILL}); - vbox.show(); - - ui::Widget menu_bar{ui::null}; - - { // menu bar - menu_bar = ui::Widget::from(gtk_menu_bar_new()); - auto menu_view = ui::Menu(ui::New); - auto view_item = TextureBrowser_constructViewMenu(menu_view); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(view_item), menu_view); - gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), view_item); - - auto menu_tools = ui::Menu(ui::New); - auto tools_item = TextureBrowser_constructToolsMenu(menu_tools); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(tools_item), menu_tools); - gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), tools_item); - - table.attach(menu_bar, {0, 3, 0, 1}, {GTK_FILL, GTK_SHRINK}); - menu_bar.show(); - } - { // Texture TreeView - g_TextureBrowser.m_scr_win_tree = ui::ScrolledWindow(ui::New); - gtk_container_set_border_width(GTK_CONTAINER(g_TextureBrowser.m_scr_win_tree), 0); - - // vertical only scrolling for treeview - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(g_TextureBrowser.m_scr_win_tree), GTK_POLICY_NEVER, - GTK_POLICY_ALWAYS); - - g_TextureBrowser.m_scr_win_tree.show(); - - TextureBrowser_createTreeViewTree(); - - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(g_TextureBrowser.m_scr_win_tree), - g_TextureBrowser.m_treeViewTree); - g_TextureBrowser.m_treeViewTree.show(); - } - { // gl_widget scrollbar - auto w = ui::Widget::from(gtk_vscrollbar_new(ui::Adjustment(0, 0, 0, 1, 1, 0))); - table.attach(w, {2, 3, 1, 2}, {GTK_SHRINK, GTK_FILL}); - w.show(); - g_TextureBrowser.m_texture_scroll = w; - - auto vadjustment = ui::Adjustment::from(gtk_range_get_adjustment(GTK_RANGE(g_TextureBrowser.m_texture_scroll))); - vadjustment.connect("value_changed", G_CALLBACK(TextureBrowser_verticalScroll), &g_TextureBrowser); - - g_TextureBrowser.m_texture_scroll.visible(g_TextureBrowser.m_showTextureScrollbar); - } - { // gl_widget - g_TextureBrowser.m_gl_widget = glwidget_new(FALSE); - g_object_ref(g_TextureBrowser.m_gl_widget._handle); - - gtk_widget_set_events(g_TextureBrowser.m_gl_widget, - GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK); - gtk_widget_set_can_focus(g_TextureBrowser.m_gl_widget, true); - - table.attach(g_TextureBrowser.m_gl_widget, {1, 2, 1, 2}); - g_TextureBrowser.m_gl_widget.show(); - - g_TextureBrowser.m_sizeHandler = g_TextureBrowser.m_gl_widget.connect("size_allocate", - G_CALLBACK(TextureBrowser_size_allocate), - &g_TextureBrowser); - g_TextureBrowser.m_exposeHandler = g_TextureBrowser.m_gl_widget.on_render(G_CALLBACK(TextureBrowser_expose), - &g_TextureBrowser); - - g_TextureBrowser.m_gl_widget.connect("button_press_event", G_CALLBACK(TextureBrowser_button_press), - &g_TextureBrowser); - g_TextureBrowser.m_gl_widget.connect("button_release_event", G_CALLBACK(TextureBrowser_button_release), - &g_TextureBrowser); - g_TextureBrowser.m_gl_widget.connect("motion_notify_event", G_CALLBACK(TextureBrowser_motion), - &g_TextureBrowser); - g_TextureBrowser.m_gl_widget.connect("scroll_event", G_CALLBACK(TextureBrowser_scroll), &g_TextureBrowser); - } - - // tag stuff - if (g_TextureBrowser.m_tags) { - { // fill tag GtkListStore - g_TextureBrowser.m_all_tags_list = ui::ListStore::from(gtk_list_store_new(N_COLUMNS, G_TYPE_STRING)); - auto sortable = GTK_TREE_SORTABLE(g_TextureBrowser.m_all_tags_list); - gtk_tree_sortable_set_sort_column_id(sortable, TAG_COLUMN, GTK_SORT_ASCENDING); - - TagBuilder.GetAllTags(g_TextureBrowser.m_all_tags); - TextureBrowser_buildTagList(); - } - { // tag menu bar - auto menu_tags = ui::Menu(ui::New); - auto tags_item = TextureBrowser_constructTagsMenu(menu_tags); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(tags_item), menu_tags); - gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), tags_item); - } - { // Tag TreeView - g_TextureBrowser.m_scr_win_tags = ui::ScrolledWindow(ui::New); - gtk_container_set_border_width(GTK_CONTAINER(g_TextureBrowser.m_scr_win_tags), 0); - - // vertical only scrolling for treeview - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(g_TextureBrowser.m_scr_win_tags), GTK_POLICY_NEVER, - GTK_POLICY_ALWAYS); - - TextureBrowser_createTreeViewTags(); - - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags); - gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); - - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(g_TextureBrowser.m_scr_win_tags), - g_TextureBrowser.m_treeViewTags); - g_TextureBrowser.m_treeViewTags.show(); - } - { // Texture/Tag notebook - TextureBrowser_constructTagNotebook(); - vbox.pack_start(g_TextureBrowser.m_tag_notebook, TRUE, TRUE, 0); - } - { // Tag search button - TextureBrowser_constructSearchButton(); - vbox.pack_end(g_TextureBrowser.m_search_button, FALSE, FALSE, 0); - } - auto frame_table = ui::Table(3, 3, FALSE); - { // Tag frame - - g_TextureBrowser.m_tag_frame = ui::Frame("Tag assignment"); - gtk_frame_set_label_align(GTK_FRAME(g_TextureBrowser.m_tag_frame), 0.5, 0.5); - gtk_frame_set_shadow_type(GTK_FRAME(g_TextureBrowser.m_tag_frame), GTK_SHADOW_NONE); - - table.attach(g_TextureBrowser.m_tag_frame, {1, 3, 2, 3}, {GTK_FILL, GTK_SHRINK}); - - frame_table.show(); - - g_TextureBrowser.m_tag_frame.add(frame_table); - } - { // assigned tag list - ui::Widget scrolled_win = ui::ScrolledWindow(ui::New); - gtk_container_set_border_width(GTK_CONTAINER(scrolled_win), 0); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); - - g_TextureBrowser.m_assigned_store = ui::ListStore::from(gtk_list_store_new(N_COLUMNS, G_TYPE_STRING)); - - auto sortable = GTK_TREE_SORTABLE(g_TextureBrowser.m_assigned_store); - gtk_tree_sortable_set_sort_column_id(sortable, TAG_COLUMN, GTK_SORT_ASCENDING); - - auto renderer = ui::CellRendererText(ui::New); - - g_TextureBrowser.m_assigned_tree = ui::TreeView( - ui::TreeModel::from(g_TextureBrowser.m_assigned_store._handle)); - g_TextureBrowser.m_assigned_store.unref(); - g_TextureBrowser.m_assigned_tree.connect("row-activated", (GCallback) TextureBrowser_removeTags, NULL); - gtk_tree_view_set_headers_visible(g_TextureBrowser.m_assigned_tree, FALSE); - - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_assigned_tree); - gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); - - auto column = ui::TreeViewColumn("", renderer, {{"text", TAG_COLUMN}}); - gtk_tree_view_append_column(g_TextureBrowser.m_assigned_tree, column); - g_TextureBrowser.m_assigned_tree.show(); - - scrolled_win.show(); - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_win), g_TextureBrowser.m_assigned_tree); - - frame_table.attach(scrolled_win, {0, 1, 1, 3}, {GTK_FILL, GTK_FILL}); - } - { // available tag list - ui::Widget scrolled_win = ui::ScrolledWindow(ui::New); - gtk_container_set_border_width(GTK_CONTAINER(scrolled_win), 0); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); - - g_TextureBrowser.m_available_store = ui::ListStore::from(gtk_list_store_new(N_COLUMNS, G_TYPE_STRING)); - auto sortable = GTK_TREE_SORTABLE(g_TextureBrowser.m_available_store); - gtk_tree_sortable_set_sort_column_id(sortable, TAG_COLUMN, GTK_SORT_ASCENDING); - - auto renderer = ui::CellRendererText(ui::New); - - g_TextureBrowser.m_available_tree = ui::TreeView( - ui::TreeModel::from(g_TextureBrowser.m_available_store._handle)); - g_TextureBrowser.m_available_store.unref(); - g_TextureBrowser.m_available_tree.connect("row-activated", (GCallback) TextureBrowser_assignTags, NULL); - gtk_tree_view_set_headers_visible(g_TextureBrowser.m_available_tree, FALSE); - - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree); - gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); - - auto column = ui::TreeViewColumn("", renderer, {{"text", TAG_COLUMN}}); - gtk_tree_view_append_column(g_TextureBrowser.m_available_tree, column); - g_TextureBrowser.m_available_tree.show(); - - scrolled_win.show(); - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_win), g_TextureBrowser.m_available_tree); - - frame_table.attach(scrolled_win, {2, 3, 1, 3}, {GTK_FILL, GTK_FILL}); - } - { // tag arrow buttons - auto m_btn_left = ui::Button(ui::New); - auto m_btn_right = ui::Button(ui::New); - auto m_arrow_left = ui::Widget::from(gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_OUT)); - auto m_arrow_right = ui::Widget::from(gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_OUT)); - m_btn_left.add(m_arrow_left); - m_btn_right.add(m_arrow_right); - - // workaround. the size of the tag frame depends of the requested size of the arrow buttons. - m_arrow_left.dimensions(-1, 68); - m_arrow_right.dimensions(-1, 68); - - frame_table.attach(m_btn_left, {1, 2, 1, 2}, {GTK_SHRINK, GTK_EXPAND}); - frame_table.attach(m_btn_right, {1, 2, 2, 3}, {GTK_SHRINK, GTK_EXPAND}); - - m_btn_left.connect("clicked", G_CALLBACK(TextureBrowser_assignTags), NULL); - m_btn_right.connect("clicked", G_CALLBACK(TextureBrowser_removeTags), NULL); - - m_btn_left.show(); - m_btn_right.show(); - m_arrow_left.show(); - m_arrow_right.show(); - } - { // tag fram labels - ui::Widget m_lbl_assigned = ui::Label("Assigned"); - ui::Widget m_lbl_unassigned = ui::Label("Available"); +ui::Widget TextureBrowser_constructWindow( ui::Window toplevel ){ + // The gl_widget and the tag assignment frame should be packed into a GtkVPaned with the slider + // position stored in local.pref. gtk_paned_get_position() and gtk_paned_set_position() don't + // seem to work in gtk 2.4 and the arrow buttons don't handle GTK_FILL, so here's another thing + // for the "once-the-gtk-libs-are-updated-TODO-list" :x + + TextureBrowser_checkTagFile(); + TextureBrowser_SetNotex(); + + GlobalShaderSystem().setActiveShadersChangedNotify( ReferenceCaller( g_TextureBrowser ) ); + + g_TextureBrowser.m_parent = toplevel; + + auto table = ui::Table(3, 3, FALSE); + auto vbox = ui::VBox(FALSE, 0); + table.attach(vbox, {0, 1, 1, 3}, {GTK_FILL, GTK_FILL}); + vbox.show(); + + ui::Widget menu_bar{ui::null}; + + { // menu bar + menu_bar = ui::Widget::from(gtk_menu_bar_new()); + auto menu_view = ui::Menu(ui::New); + auto view_item = TextureBrowser_constructViewMenu( menu_view ); + gtk_menu_item_set_submenu( GTK_MENU_ITEM( view_item ), menu_view ); + gtk_menu_shell_append( GTK_MENU_SHELL( menu_bar ), view_item ); + + auto menu_tools = ui::Menu(ui::New); + auto tools_item = TextureBrowser_constructToolsMenu( menu_tools ); + gtk_menu_item_set_submenu( GTK_MENU_ITEM( tools_item ), menu_tools ); + gtk_menu_shell_append( GTK_MENU_SHELL( menu_bar ), tools_item ); + + table.attach(menu_bar, {0, 3, 0, 1}, {GTK_FILL, GTK_SHRINK}); + menu_bar.show(); + } + { // Texture TreeView + g_TextureBrowser.m_scr_win_tree = ui::ScrolledWindow(ui::New); + gtk_container_set_border_width( GTK_CONTAINER( g_TextureBrowser.m_scr_win_tree ), 0 ); + + // vertical only scrolling for treeview + gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( g_TextureBrowser.m_scr_win_tree ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS ); + + g_TextureBrowser.m_scr_win_tree.show(); + + TextureBrowser_createTreeViewTree(); + + gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( g_TextureBrowser.m_scr_win_tree ), g_TextureBrowser.m_treeViewTree ); + g_TextureBrowser.m_treeViewTree.show(); + } + { // gl_widget scrollbar + auto w = ui::Widget::from(gtk_vscrollbar_new( ui::Adjustment( 0,0,0,1,1,0 ) )); + table.attach(w, {2, 3, 1, 2}, {GTK_SHRINK, GTK_FILL}); + w.show(); + g_TextureBrowser.m_texture_scroll = w; + + auto vadjustment = ui::Adjustment::from(gtk_range_get_adjustment( GTK_RANGE( g_TextureBrowser.m_texture_scroll ) )); + vadjustment.connect( "value_changed", G_CALLBACK( TextureBrowser_verticalScroll ), &g_TextureBrowser ); + + g_TextureBrowser.m_texture_scroll.visible(g_TextureBrowser.m_showTextureScrollbar); + } + { // gl_widget + g_TextureBrowser.m_gl_widget = glwidget_new( FALSE ); + g_object_ref( g_TextureBrowser.m_gl_widget._handle ); + + gtk_widget_set_events( g_TextureBrowser.m_gl_widget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK ); + gtk_widget_set_can_focus( g_TextureBrowser.m_gl_widget, true ); + + table.attach(g_TextureBrowser.m_gl_widget, {1, 2, 1, 2}); + g_TextureBrowser.m_gl_widget.show(); + + g_TextureBrowser.m_sizeHandler = g_TextureBrowser.m_gl_widget.connect( "size_allocate", G_CALLBACK( TextureBrowser_size_allocate ), &g_TextureBrowser ); + g_TextureBrowser.m_exposeHandler = g_TextureBrowser.m_gl_widget.on_render( G_CALLBACK( TextureBrowser_expose ), &g_TextureBrowser ); + + g_TextureBrowser.m_gl_widget.connect( "button_press_event", G_CALLBACK( TextureBrowser_button_press ), &g_TextureBrowser ); + g_TextureBrowser.m_gl_widget.connect( "button_release_event", G_CALLBACK( TextureBrowser_button_release ), &g_TextureBrowser ); + g_TextureBrowser.m_gl_widget.connect( "motion_notify_event", G_CALLBACK( TextureBrowser_motion ), &g_TextureBrowser ); + g_TextureBrowser.m_gl_widget.connect( "scroll_event", G_CALLBACK( TextureBrowser_scroll ), &g_TextureBrowser ); + } + + // tag stuff + if ( g_TextureBrowser.m_tags ) { + { // fill tag GtkListStore + g_TextureBrowser.m_all_tags_list = ui::ListStore::from(gtk_list_store_new( N_COLUMNS, G_TYPE_STRING )); + auto sortable = GTK_TREE_SORTABLE( g_TextureBrowser.m_all_tags_list ); + gtk_tree_sortable_set_sort_column_id( sortable, TAG_COLUMN, GTK_SORT_ASCENDING ); + + TagBuilder.GetAllTags( g_TextureBrowser.m_all_tags ); + TextureBrowser_buildTagList(); + } + { // tag menu bar + auto menu_tags = ui::Menu(ui::New); + auto tags_item = TextureBrowser_constructTagsMenu( menu_tags ); + gtk_menu_item_set_submenu( GTK_MENU_ITEM( tags_item ), menu_tags ); + gtk_menu_shell_append( GTK_MENU_SHELL( menu_bar ), tags_item ); + } + { // Tag TreeView + g_TextureBrowser.m_scr_win_tags = ui::ScrolledWindow(ui::New); + gtk_container_set_border_width( GTK_CONTAINER( g_TextureBrowser.m_scr_win_tags ), 0 ); + + // vertical only scrolling for treeview + gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( g_TextureBrowser.m_scr_win_tags ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS ); + + TextureBrowser_createTreeViewTags(); + + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags ); + gtk_tree_selection_set_mode( selection, GTK_SELECTION_MULTIPLE ); + + gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( g_TextureBrowser.m_scr_win_tags ), g_TextureBrowser.m_treeViewTags ); + g_TextureBrowser.m_treeViewTags.show(); + } + { // Texture/Tag notebook + TextureBrowser_constructTagNotebook(); + vbox.pack_start( g_TextureBrowser.m_tag_notebook, TRUE, TRUE, 0 ); + } + { // Tag search button + TextureBrowser_constructSearchButton(); + vbox.pack_end(g_TextureBrowser.m_search_button, FALSE, FALSE, 0); + } + auto frame_table = ui::Table(3, 3, FALSE); + { // Tag frame + + g_TextureBrowser.m_tag_frame = ui::Frame( "Tag assignment" ); + gtk_frame_set_label_align( GTK_FRAME( g_TextureBrowser.m_tag_frame ), 0.5, 0.5 ); + gtk_frame_set_shadow_type( GTK_FRAME( g_TextureBrowser.m_tag_frame ), GTK_SHADOW_NONE ); + + table.attach(g_TextureBrowser.m_tag_frame, {1, 3, 2, 3}, {GTK_FILL, GTK_SHRINK}); + + frame_table.show(); + + g_TextureBrowser.m_tag_frame.add(frame_table); + } + { // assigned tag list + ui::Widget scrolled_win = ui::ScrolledWindow(ui::New); + gtk_container_set_border_width( GTK_CONTAINER( scrolled_win ), 0 ); + gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scrolled_win ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS ); + + g_TextureBrowser.m_assigned_store = ui::ListStore::from(gtk_list_store_new( N_COLUMNS, G_TYPE_STRING )); + + auto sortable = GTK_TREE_SORTABLE( g_TextureBrowser.m_assigned_store ); + gtk_tree_sortable_set_sort_column_id( sortable, TAG_COLUMN, GTK_SORT_ASCENDING ); + + auto renderer = ui::CellRendererText(ui::New); + + g_TextureBrowser.m_assigned_tree = ui::TreeView(ui::TreeModel::from(g_TextureBrowser.m_assigned_store._handle)); + g_TextureBrowser.m_assigned_store.unref(); + g_TextureBrowser.m_assigned_tree.connect( "row-activated", (GCallback) TextureBrowser_removeTags, NULL ); + gtk_tree_view_set_headers_visible(g_TextureBrowser.m_assigned_tree, FALSE ); + + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_assigned_tree ); + gtk_tree_selection_set_mode( selection, GTK_SELECTION_MULTIPLE ); + + auto column = ui::TreeViewColumn( "", renderer, {{"text", TAG_COLUMN}} ); + gtk_tree_view_append_column(g_TextureBrowser.m_assigned_tree, column ); + g_TextureBrowser.m_assigned_tree.show(); - frame_table.attach(m_lbl_assigned, {0, 1, 0, 1}, {GTK_EXPAND, GTK_SHRINK}); - frame_table.attach(m_lbl_unassigned, {2, 3, 0, 1}, {GTK_EXPAND, GTK_SHRINK}); + scrolled_win.show(); + gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( scrolled_win ), g_TextureBrowser.m_assigned_tree ); - m_lbl_assigned.show(); - m_lbl_unassigned.show(); - } - } else { // no tag support, show the texture tree only - vbox.pack_start(g_TextureBrowser.m_scr_win_tree, TRUE, TRUE, 0); - } + frame_table.attach(scrolled_win, {0, 1, 1, 3}, {GTK_FILL, GTK_FILL}); + } + { // available tag list + ui::Widget scrolled_win = ui::ScrolledWindow(ui::New); + gtk_container_set_border_width( GTK_CONTAINER( scrolled_win ), 0 ); + gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scrolled_win ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS ); - // TODO do we need this? - //gtk_container_set_focus_chain(GTK_CONTAINER(hbox_table), NULL); - - return table; -} + g_TextureBrowser.m_available_store = ui::ListStore::from(gtk_list_store_new( N_COLUMNS, G_TYPE_STRING )); + auto sortable = GTK_TREE_SORTABLE( g_TextureBrowser.m_available_store ); + gtk_tree_sortable_set_sort_column_id( sortable, TAG_COLUMN, GTK_SORT_ASCENDING ); -void TextureBrowser_destroyWindow() -{ - GlobalShaderSystem().setActiveShadersChangedNotify(Callback()); + auto renderer = ui::CellRendererText(ui::New); - g_signal_handler_disconnect(G_OBJECT(g_TextureBrowser.m_gl_widget), g_TextureBrowser.m_sizeHandler); - g_signal_handler_disconnect(G_OBJECT(g_TextureBrowser.m_gl_widget), g_TextureBrowser.m_exposeHandler); + g_TextureBrowser.m_available_tree = ui::TreeView(ui::TreeModel::from(g_TextureBrowser.m_available_store._handle)); + g_TextureBrowser.m_available_store.unref(); + g_TextureBrowser.m_available_tree.connect( "row-activated", (GCallback) TextureBrowser_assignTags, NULL ); + gtk_tree_view_set_headers_visible(g_TextureBrowser.m_available_tree, FALSE ); - g_TextureBrowser.m_gl_widget.unref(); -} + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree ); + gtk_tree_selection_set_mode( selection, GTK_SELECTION_MULTIPLE ); -const Vector3 &TextureBrowser_getBackgroundColour(TextureBrowser &textureBrowser) -{ - return textureBrowser.color_textureback; -} + auto column = ui::TreeViewColumn( "", renderer, {{"text", TAG_COLUMN}} ); + gtk_tree_view_append_column(g_TextureBrowser.m_available_tree, column ); + g_TextureBrowser.m_available_tree.show(); -void TextureBrowser_setBackgroundColour(TextureBrowser &textureBrowser, const Vector3 &colour) -{ - textureBrowser.color_textureback = colour; - TextureBrowser_queueDraw(textureBrowser); -} + scrolled_win.show(); + gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( scrolled_win ), g_TextureBrowser.m_available_tree ); -void TextureBrowser_selectionHelper(ui::TreeModel model, ui::TreePath path, GtkTreeIter *iter, GSList **selected) -{ - g_assert(selected != NULL); + frame_table.attach(scrolled_win, {2, 3, 1, 3}, {GTK_FILL, GTK_FILL}); + } + { // tag arrow buttons + auto m_btn_left = ui::Button(ui::New); + auto m_btn_right = ui::Button(ui::New); + auto m_arrow_left = ui::Widget::from(gtk_arrow_new( GTK_ARROW_LEFT, GTK_SHADOW_OUT )); + auto m_arrow_right = ui::Widget::from(gtk_arrow_new( GTK_ARROW_RIGHT, GTK_SHADOW_OUT )); + m_btn_left.add(m_arrow_left); + m_btn_right.add(m_arrow_right); - gchar *name; - gtk_tree_model_get(model, iter, TAG_COLUMN, &name, -1); - *selected = g_slist_append(*selected, name); -} + // workaround. the size of the tag frame depends of the requested size of the arrow buttons. + m_arrow_left.dimensions(-1, 68); + m_arrow_right.dimensions(-1, 68); -void TextureBrowser_shaderInfo() -{ - const char *name = TextureBrowser_GetSelectedShader(g_TextureBrowser); - IShader *shader = QERApp_Shader_ForName(name); + frame_table.attach(m_btn_left, {1, 2, 1, 2}, {GTK_SHRINK, GTK_EXPAND}); + frame_table.attach(m_btn_right, {1, 2, 2, 3}, {GTK_SHRINK, GTK_EXPAND}); - DoShaderInfoDlg(name, shader->getShaderFileName(), "Shader Info"); + m_btn_left.connect( "clicked", G_CALLBACK( TextureBrowser_assignTags ), NULL ); + m_btn_right.connect( "clicked", G_CALLBACK( TextureBrowser_removeTags ), NULL ); - shader->DecRef(); -} + m_btn_left.show(); + m_btn_right.show(); + m_arrow_left.show(); + m_arrow_right.show(); + } + { // tag fram labels + ui::Widget m_lbl_assigned = ui::Label( "Assigned" ); + ui::Widget m_lbl_unassigned = ui::Label( "Available" ); -void TextureBrowser_addTag() -{ - CopiedString tag; + frame_table.attach(m_lbl_assigned, {0, 1, 0, 1}, {GTK_EXPAND, GTK_SHRINK}); + frame_table.attach(m_lbl_unassigned, {2, 3, 0, 1}, {GTK_EXPAND, GTK_SHRINK}); + + m_lbl_assigned.show(); + m_lbl_unassigned.show(); + } + } + else { // no tag support, show the texture tree only + vbox.pack_start( g_TextureBrowser.m_scr_win_tree, TRUE, TRUE, 0 ); + } - EMessageBoxReturn result = DoShaderTagDlg(&tag, "Add shader tag"); + // TODO do we need this? + //gtk_container_set_focus_chain(GTK_CONTAINER(hbox_table), NULL); - if (result == eIDOK && !tag.empty()) { - GtkTreeIter iter; - g_TextureBrowser.m_all_tags.insert(tag.c_str()); - gtk_list_store_append(g_TextureBrowser.m_available_store, &iter); - gtk_list_store_set(g_TextureBrowser.m_available_store, &iter, TAG_COLUMN, tag.c_str(), -1); + return table; +} + +void TextureBrowser_destroyWindow(){ + GlobalShaderSystem().setActiveShadersChangedNotify( Callback() ); - // Select the currently added tag in the available list - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree); - gtk_tree_selection_select_iter(selection, &iter); + g_signal_handler_disconnect( G_OBJECT( g_TextureBrowser.m_gl_widget ), g_TextureBrowser.m_sizeHandler ); + g_signal_handler_disconnect( G_OBJECT( g_TextureBrowser.m_gl_widget ), g_TextureBrowser.m_exposeHandler ); - g_TextureBrowser.m_all_tags_list.append(TAG_COLUMN, tag.c_str()); - } + g_TextureBrowser.m_gl_widget.unref(); } -void TextureBrowser_renameTag() -{ - /* WORKAROUND: The tag treeview is set to GTK_SELECTION_MULTIPLE. Because - gtk_tree_selection_get_selected() doesn't work with GTK_SELECTION_MULTIPLE, - we need to count the number of selected rows first and use - gtk_tree_selection_selected_foreach() then to go through the list of selected - rows (which always containins a single row). - */ +const Vector3& TextureBrowser_getBackgroundColour( TextureBrowser& textureBrowser ){ + return textureBrowser.color_textureback; +} + +void TextureBrowser_setBackgroundColour( TextureBrowser& textureBrowser, const Vector3& colour ){ + textureBrowser.color_textureback = colour; + TextureBrowser_queueDraw( textureBrowser ); +} - GSList *selected = NULL; +void TextureBrowser_selectionHelper( ui::TreeModel model, ui::TreePath path, GtkTreeIter* iter, GSList** selected ){ + g_assert( selected != NULL ); - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags); - gtk_tree_selection_selected_foreach(selection, GtkTreeSelectionForeachFunc(TextureBrowser_selectionHelper), - &selected); + gchar* name; + gtk_tree_model_get( model, iter, TAG_COLUMN, &name, -1 ); + *selected = g_slist_append( *selected, name ); +} - if (g_slist_length(selected) == 1) { // we only rename a single tag - CopiedString newTag; - EMessageBoxReturn result = DoShaderTagDlg(&newTag, "Rename shader tag"); +void TextureBrowser_shaderInfo(){ + const char* name = TextureBrowser_GetSelectedShader( g_TextureBrowser ); + IShader* shader = QERApp_Shader_ForName( name ); - if (result == eIDOK && !newTag.empty()) { - GtkTreeIter iterList; - gchar *rowTag; - gchar *oldTag = (char *) selected->data; + DoShaderInfoDlg( name, shader->getShaderFileName(), "Shader Info" ); - bool row = gtk_tree_model_get_iter_first(g_TextureBrowser.m_all_tags_list, &iterList) != 0; + shader->DecRef(); +} - while (row) { - gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iterList, TAG_COLUMN, &rowTag, -1); +void TextureBrowser_addTag(){ + CopiedString tag; - if (strcmp(rowTag, oldTag) == 0) { - gtk_list_store_set(g_TextureBrowser.m_all_tags_list, &iterList, TAG_COLUMN, newTag.c_str(), -1); - } - row = gtk_tree_model_iter_next(g_TextureBrowser.m_all_tags_list, &iterList) != 0; - } + EMessageBoxReturn result = DoShaderTagDlg( &tag, "Add shader tag" ); - TagBuilder.RenameShaderTag(oldTag, newTag.c_str()); + if ( result == eIDOK && !tag.empty() ) { + GtkTreeIter iter; + g_TextureBrowser.m_all_tags.insert( tag.c_str() ); + gtk_list_store_append( g_TextureBrowser.m_available_store, &iter ); + gtk_list_store_set( g_TextureBrowser.m_available_store, &iter, TAG_COLUMN, tag.c_str(), -1 ); - g_TextureBrowser.m_all_tags.erase((CopiedString) oldTag); - g_TextureBrowser.m_all_tags.insert(newTag); + // Select the currently added tag in the available list + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree ); + gtk_tree_selection_select_iter( selection, &iter ); - BuildStoreAssignedTags(g_TextureBrowser.m_assigned_store, g_TextureBrowser.shader.c_str(), - &g_TextureBrowser); - BuildStoreAvailableTags(g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, - g_TextureBrowser.m_all_tags, &g_TextureBrowser); - } - } else { - ui::alert(g_TextureBrowser.m_parent, "Select a single tag for renaming."); - } + g_TextureBrowser.m_all_tags_list.append(TAG_COLUMN, tag.c_str()); + } } -void TextureBrowser_deleteTag() -{ - GSList *selected = NULL; +void TextureBrowser_renameTag(){ + /* WORKAROUND: The tag treeview is set to GTK_SELECTION_MULTIPLE. Because + gtk_tree_selection_get_selected() doesn't work with GTK_SELECTION_MULTIPLE, + we need to count the number of selected rows first and use + gtk_tree_selection_selected_foreach() then to go through the list of selected + rows (which always containins a single row). + */ - auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags); - gtk_tree_selection_selected_foreach(selection, GtkTreeSelectionForeachFunc(TextureBrowser_selectionHelper), - &selected); + GSList* selected = NULL; - if (g_slist_length(selected) == 1) { // we only delete a single tag - auto result = ui::alert(g_TextureBrowser.m_parent, "Are you sure you want to delete the selected tag?", - "Delete Tag", ui::alert_type::YESNO, ui::alert_icon::Question); + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags ); + gtk_tree_selection_selected_foreach( selection, GtkTreeSelectionForeachFunc( TextureBrowser_selectionHelper ), &selected ); - if (result == ui::alert_response::YES) { - GtkTreeIter iterSelected; - gchar *rowTag; + if ( g_slist_length( selected ) == 1 ) { // we only rename a single tag + CopiedString newTag; + EMessageBoxReturn result = DoShaderTagDlg( &newTag, "Rename shader tag" ); - gchar *tagSelected = (char *) selected->data; + if ( result == eIDOK && !newTag.empty() ) { + GtkTreeIter iterList; + gchar* rowTag; + gchar* oldTag = (char*)selected->data; + + bool row = gtk_tree_model_get_iter_first(g_TextureBrowser.m_all_tags_list, &iterList ) != 0; + + while ( row ) + { + gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iterList, TAG_COLUMN, &rowTag, -1 ); + + if ( strcmp( rowTag, oldTag ) == 0 ) { + gtk_list_store_set( g_TextureBrowser.m_all_tags_list, &iterList, TAG_COLUMN, newTag.c_str(), -1 ); + } + row = gtk_tree_model_iter_next(g_TextureBrowser.m_all_tags_list, &iterList ) != 0; + } - bool row = gtk_tree_model_get_iter_first(g_TextureBrowser.m_all_tags_list, &iterSelected) != 0; + TagBuilder.RenameShaderTag( oldTag, newTag.c_str() ); + + g_TextureBrowser.m_all_tags.erase( (CopiedString)oldTag ); + g_TextureBrowser.m_all_tags.insert( newTag ); + + BuildStoreAssignedTags( g_TextureBrowser.m_assigned_store, g_TextureBrowser.shader.c_str(), &g_TextureBrowser ); + BuildStoreAvailableTags( g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, g_TextureBrowser.m_all_tags, &g_TextureBrowser ); + } + } + else + { + ui::alert( g_TextureBrowser.m_parent, "Select a single tag for renaming." ); + } +} + +void TextureBrowser_deleteTag(){ + GSList* selected = NULL; + + auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags ); + gtk_tree_selection_selected_foreach( selection, GtkTreeSelectionForeachFunc( TextureBrowser_selectionHelper ), &selected ); + + if ( g_slist_length( selected ) == 1 ) { // we only delete a single tag + auto result = ui::alert( g_TextureBrowser.m_parent, "Are you sure you want to delete the selected tag?", "Delete Tag", ui::alert_type::YESNO, ui::alert_icon::Question ); + + if ( result == ui::alert_response::YES ) { + GtkTreeIter iterSelected; + gchar *rowTag; + + gchar* tagSelected = (char*)selected->data; + + bool row = gtk_tree_model_get_iter_first(g_TextureBrowser.m_all_tags_list, &iterSelected ) != 0; + + while ( row ) + { + gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iterSelected, TAG_COLUMN, &rowTag, -1 ); + + if ( strcmp( rowTag, tagSelected ) == 0 ) { + gtk_list_store_remove( g_TextureBrowser.m_all_tags_list, &iterSelected ); + break; + } + row = gtk_tree_model_iter_next(g_TextureBrowser.m_all_tags_list, &iterSelected ) != 0; + } + + TagBuilder.DeleteTag( tagSelected ); + g_TextureBrowser.m_all_tags.erase( (CopiedString)tagSelected ); + + BuildStoreAssignedTags( g_TextureBrowser.m_assigned_store, g_TextureBrowser.shader.c_str(), &g_TextureBrowser ); + BuildStoreAvailableTags( g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, g_TextureBrowser.m_all_tags, &g_TextureBrowser ); + } + } + else { + ui::alert( g_TextureBrowser.m_parent, "Select a single tag for deletion." ); + } +} + +void TextureBrowser_copyTag(){ + g_TextureBrowser.m_copied_tags.clear(); + TagBuilder.GetShaderTags( g_TextureBrowser.shader.c_str(), g_TextureBrowser.m_copied_tags ); +} + +void TextureBrowser_pasteTag(){ + IShader* ishader = QERApp_Shader_ForName( g_TextureBrowser.shader.c_str() ); + CopiedString shader = g_TextureBrowser.shader.c_str(); + + if ( !TagBuilder.CheckShaderTag( shader.c_str() ) ) { + CopiedString shaderFile = ishader->getShaderFileName(); + if ( shaderFile.empty() ) { + // it's a texture + TagBuilder.AddShaderNode( shader.c_str(), CUSTOM, TEXTURE ); + } + else + { + // it's a shader + TagBuilder.AddShaderNode( shader.c_str(), CUSTOM, SHADER ); + } + + for ( size_t i = 0; i < g_TextureBrowser.m_copied_tags.size(); ++i ) + { + TagBuilder.AddShaderTag( shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str(), TAG ); + } + } + else + { + for ( size_t i = 0; i < g_TextureBrowser.m_copied_tags.size(); ++i ) + { + if ( !TagBuilder.CheckShaderTag( shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str() ) ) { + // the tag doesn't exist - let's add it + TagBuilder.AddShaderTag( shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str(), TAG ); + } + } + } + + ishader->DecRef(); + + TagBuilder.SaveXmlDoc(); + BuildStoreAssignedTags( g_TextureBrowser.m_assigned_store, shader.c_str(), &g_TextureBrowser ); + BuildStoreAvailableTags( g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, g_TextureBrowser.m_all_tags, &g_TextureBrowser ); +} + +void TextureBrowser_RefreshShaders(){ + ScopeDisableScreenUpdates disableScreenUpdates( "Processing...", "Loading Shaders" ); + GlobalShaderSystem().refresh(); + UpdateAllWindows(); + auto selection = gtk_tree_view_get_selection(GlobalTextureBrowser().m_treeViewTree); + GtkTreeModel* model = NULL; + GtkTreeIter iter; + if ( gtk_tree_selection_get_selected (selection, &model, &iter) ) + { + gchar dirName[1024]; - while (row) { - gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iterSelected, TAG_COLUMN, &rowTag, -1); + gchar* buffer; + gtk_tree_model_get( model, &iter, 0, &buffer, -1 ); + strcpy( dirName, buffer ); + g_free( buffer ); + if ( !TextureBrowser_showWads() ) { + strcat( dirName, "/" ); + } + TextureBrowser_ShowDirectory( GlobalTextureBrowser(), dirName ); + TextureBrowser_queueDraw( GlobalTextureBrowser() ); + } +} - if (strcmp(rowTag, tagSelected) == 0) { - gtk_list_store_remove(g_TextureBrowser.m_all_tags_list, &iterSelected); - break; - } - row = gtk_tree_model_iter_next(g_TextureBrowser.m_all_tags_list, &iterSelected) != 0; - } +void TextureBrowser_ToggleShowShaders(){ + g_TextureBrowser.m_showShaders ^= 1; + g_TextureBrowser.m_showshaders_item.update(); + TextureBrowser_queueDraw( g_TextureBrowser ); +} - TagBuilder.DeleteTag(tagSelected); - g_TextureBrowser.m_all_tags.erase((CopiedString) tagSelected); +void TextureBrowser_ToggleShowShaderListOnly(){ + g_TextureBrowser_shaderlistOnly ^= 1; + g_TextureBrowser.m_showshaderlistonly_item.update(); - BuildStoreAssignedTags(g_TextureBrowser.m_assigned_store, g_TextureBrowser.shader.c_str(), - &g_TextureBrowser); - BuildStoreAvailableTags(g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, - g_TextureBrowser.m_all_tags, &g_TextureBrowser); - } - } else { - ui::alert(g_TextureBrowser.m_parent, "Select a single tag for deletion."); - } + TextureBrowser_constructTreeStore(); } -void TextureBrowser_copyTag() -{ - g_TextureBrowser.m_copied_tags.clear(); - TagBuilder.GetShaderTags(g_TextureBrowser.shader.c_str(), g_TextureBrowser.m_copied_tags); +void TextureBrowser_showAll(){ + g_TextureBrowser_currentDirectory = ""; + g_TextureBrowser.m_searchedTags = false; + TextureBrowser_heightChanged( g_TextureBrowser ); + TextureBrowser_updateTitle(); } -void TextureBrowser_pasteTag() -{ - IShader *ishader = QERApp_Shader_ForName(g_TextureBrowser.shader.c_str()); - CopiedString shader = g_TextureBrowser.shader.c_str(); - - if (!TagBuilder.CheckShaderTag(shader.c_str())) { - CopiedString shaderFile = ishader->getShaderFileName(); - if (shaderFile.empty()) { - // it's a texture - TagBuilder.AddShaderNode(shader.c_str(), CUSTOM, TEXTURE); - } else { - // it's a shader - TagBuilder.AddShaderNode(shader.c_str(), CUSTOM, SHADER); - } - - for (size_t i = 0; i < g_TextureBrowser.m_copied_tags.size(); ++i) { - TagBuilder.AddShaderTag(shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str(), TAG); - } - } else { - for (size_t i = 0; i < g_TextureBrowser.m_copied_tags.size(); ++i) { - if (!TagBuilder.CheckShaderTag(shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str())) { - // the tag doesn't exist - let's add it - TagBuilder.AddShaderTag(shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str(), TAG); - } - } - } - - ishader->DecRef(); - - TagBuilder.SaveXmlDoc(); - BuildStoreAssignedTags(g_TextureBrowser.m_assigned_store, shader.c_str(), &g_TextureBrowser); - BuildStoreAvailableTags(g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, - g_TextureBrowser.m_all_tags, &g_TextureBrowser); -} - -void TextureBrowser_RefreshShaders() -{ - ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Loading Shaders"); - GlobalShaderSystem().refresh(); - UpdateAllWindows(); - auto selection = gtk_tree_view_get_selection(GlobalTextureBrowser().m_treeViewTree); - GtkTreeModel *model = NULL; - GtkTreeIter iter; - if (gtk_tree_selection_get_selected(selection, &model, &iter)) { - gchar dirName[1024]; - - gchar *buffer; - gtk_tree_model_get(model, &iter, 0, &buffer, -1); - strcpy(dirName, buffer); - g_free(buffer); - if (!TextureBrowser_showWads()) { - strcat(dirName, "/"); - } - TextureBrowser_ShowDirectory(GlobalTextureBrowser(), dirName); - TextureBrowser_queueDraw(GlobalTextureBrowser()); - } -} - -void TextureBrowser_ToggleShowShaders() -{ - g_TextureBrowser.m_showShaders ^= 1; - g_TextureBrowser.m_showshaders_item.update(); - TextureBrowser_queueDraw(g_TextureBrowser); -} +void TextureBrowser_showUntagged(){ + auto result = ui::alert( g_TextureBrowser.m_parent, "WARNING! This function might need a lot of memory and time. Are you sure you want to use it?", "Show Untagged", ui::alert_type::YESNO, ui::alert_icon::Warning ); -void TextureBrowser_ToggleShowShaderListOnly() -{ - g_TextureBrowser_shaderlistOnly ^= 1; - g_TextureBrowser.m_showshaderlistonly_item.update(); + if ( result == ui::alert_response::YES ) { + g_TextureBrowser.m_found_shaders.clear(); + TagBuilder.GetUntagged( g_TextureBrowser.m_found_shaders ); + std::set::iterator iter; - TextureBrowser_constructTreeStore(); -} + ScopeDisableScreenUpdates disableScreenUpdates( "Searching untagged textures...", "Loading Textures" ); -void TextureBrowser_showAll() -{ - g_TextureBrowser_currentDirectory = ""; - g_TextureBrowser.m_searchedTags = false; - TextureBrowser_heightChanged(g_TextureBrowser); - TextureBrowser_updateTitle(); + for ( iter = g_TextureBrowser.m_found_shaders.begin(); iter != g_TextureBrowser.m_found_shaders.end(); iter++ ) + { + std::string path = ( *iter ).c_str(); + size_t pos = path.find_last_of( "/", path.size() ); + std::string name = path.substr( pos + 1, path.size() ); + path = path.substr( 0, pos + 1 ); + TextureDirectory_loadTexture( path.c_str(), name.c_str() ); + globalErrorStream() << path.c_str() << name.c_str() << "\n"; + } + + g_TextureBrowser_currentDirectory = "Untagged"; + TextureBrowser_queueDraw( GlobalTextureBrowser() ); + TextureBrowser_heightChanged( g_TextureBrowser ); + TextureBrowser_updateTitle(); + } } -void TextureBrowser_showUntagged() -{ - auto result = ui::alert(g_TextureBrowser.m_parent, - "WARNING! This function might need a lot of memory and time. Are you sure you want to use it?", - "Show Untagged", ui::alert_type::YESNO, ui::alert_icon::Warning); - - if (result == ui::alert_response::YES) { - g_TextureBrowser.m_found_shaders.clear(); - TagBuilder.GetUntagged(g_TextureBrowser.m_found_shaders); - std::set::iterator iter; - - ScopeDisableScreenUpdates disableScreenUpdates("Searching untagged textures...", "Loading Textures"); - - for (iter = g_TextureBrowser.m_found_shaders.begin(); iter != g_TextureBrowser.m_found_shaders.end(); iter++) { - std::string path = (*iter).c_str(); - size_t pos = path.find_last_of("/", path.size()); - std::string name = path.substr(pos + 1, path.size()); - path = path.substr(0, pos + 1); - TextureDirectory_loadTexture(path.c_str(), name.c_str()); - globalErrorStream() << path.c_str() << name.c_str() << "\n"; - } - - g_TextureBrowser_currentDirectory = "Untagged"; - TextureBrowser_queueDraw(GlobalTextureBrowser()); - TextureBrowser_heightChanged(g_TextureBrowser); - TextureBrowser_updateTitle(); - } -} - -void TextureBrowser_FixedSize() -{ - g_TextureBrowser_fixedSize ^= 1; - GlobalTextureBrowser().m_fixedsize_item.update(); - TextureBrowser_activeShadersChanged(GlobalTextureBrowser()); +void TextureBrowser_FixedSize(){ + g_TextureBrowser_fixedSize ^= 1; + GlobalTextureBrowser().m_fixedsize_item.update(); + TextureBrowser_activeShadersChanged( GlobalTextureBrowser() ); } -void TextureBrowser_FilterMissing() -{ - g_TextureBrowser_filterMissing ^= 1; - GlobalTextureBrowser().m_filternotex_item.update(); - TextureBrowser_activeShadersChanged(GlobalTextureBrowser()); - TextureBrowser_RefreshShaders(); +void TextureBrowser_FilterMissing(){ + g_TextureBrowser_filterMissing ^= 1; + GlobalTextureBrowser().m_filternotex_item.update(); + TextureBrowser_activeShadersChanged( GlobalTextureBrowser() ); + TextureBrowser_RefreshShaders(); } -void TextureBrowser_FilterFallback() -{ - g_TextureBrowser_filterFallback ^= 1; - GlobalTextureBrowser().m_hidenotex_item.update(); - TextureBrowser_activeShadersChanged(GlobalTextureBrowser()); - TextureBrowser_RefreshShaders(); +void TextureBrowser_FilterFallback(){ + g_TextureBrowser_filterFallback ^= 1; + GlobalTextureBrowser().m_hidenotex_item.update(); + TextureBrowser_activeShadersChanged( GlobalTextureBrowser() ); + TextureBrowser_RefreshShaders(); } -void TextureBrowser_EnableAlpha() -{ - g_TextureBrowser_enableAlpha ^= 1; - GlobalTextureBrowser().m_enablealpha_item.update(); - TextureBrowser_activeShadersChanged(GlobalTextureBrowser()); +void TextureBrowser_EnableAlpha(){ + g_TextureBrowser_enableAlpha ^= 1; + GlobalTextureBrowser().m_enablealpha_item.update(); + TextureBrowser_activeShadersChanged( GlobalTextureBrowser() ); } -void TextureBrowser_exportTitle(const Callback &importer) -{ - StringOutputStream buffer(64); - buffer << "Textures: "; - if (!string_empty(g_TextureBrowser_currentDirectory.c_str())) { - buffer << g_TextureBrowser_currentDirectory.c_str(); - } else { - buffer << "all"; - } - importer(buffer.c_str()); +void TextureBrowser_exportTitle( const Callback & importer ){ + StringOutputStream buffer( 64 ); + buffer << "Textures: "; + if ( !string_empty( g_TextureBrowser_currentDirectory.c_str() ) ) { + buffer << g_TextureBrowser_currentDirectory.c_str(); + } + else + { + buffer << "all"; + } + importer( buffer.c_str() ); } struct TextureScale { - static void Export(const TextureBrowser &self, const Callback &returnz) - { - switch (self.m_textureScale) { - case 10: - returnz(0); - break; - case 25: - returnz(1); - break; - case 50: - returnz(2); - break; - case 100: - returnz(3); - break; - case 200: - returnz(4); - break; - } - } - - static void Import(TextureBrowser &self, int value) - { - switch (value) { - case 0: - TextureBrowser_setScale(self, 10); - break; - case 1: - TextureBrowser_setScale(self, 25); - break; - case 2: - TextureBrowser_setScale(self, 50); - break; - case 3: - TextureBrowser_setScale(self, 100); - break; - case 4: - TextureBrowser_setScale(self, 200); - break; - } - } + static void Export(const TextureBrowser &self, const Callback &returnz) { + switch (self.m_textureScale) { + case 10: + returnz(0); + break; + case 25: + returnz(1); + break; + case 50: + returnz(2); + break; + case 100: + returnz(3); + break; + case 200: + returnz(4); + break; + } + } + + static void Import(TextureBrowser &self, int value) { + switch (value) { + case 0: + TextureBrowser_setScale(self, 10); + break; + case 1: + TextureBrowser_setScale(self, 25); + break; + case 2: + TextureBrowser_setScale(self, 50); + break; + case 3: + TextureBrowser_setScale(self, 100); + break; + case 4: + TextureBrowser_setScale(self, 200); + break; + } + } }; struct UniformTextureSize { - static void Export(const TextureBrowser &self, const Callback &returnz) - { - returnz(g_TextureBrowser.m_uniformTextureSize); - } - - static void Import(TextureBrowser &self, int value) - { - if (value > 16) { - TextureBrowser_setUniformSize(self, value); - } - } + static void Export(const TextureBrowser &self, const Callback &returnz) { + returnz(g_TextureBrowser.m_uniformTextureSize); + } + + static void Import(TextureBrowser &self, int value) { + if (value > 16) + TextureBrowser_setUniformSize(self, value); + } }; -void TextureBrowser_constructPreferences(PreferencesPage &page) -{ - page.appendCheckBox( - "", "Texture scrollbar", - make_property(GlobalTextureBrowser()) - ); - { - const char *texture_scale[] = {"10%", "25%", "50%", "100%", "200%"}; - page.appendCombo( - "Texture Thumbnail Scale", - STRING_ARRAY_RANGE(texture_scale), - make_property(GlobalTextureBrowser()) - ); - } - page.appendSpinner( - "Texture Thumbnail Size", - GlobalTextureBrowser().m_uniformTextureSize, - GlobalTextureBrowser().m_uniformTextureSize, - 16, 8192 - ); - page.appendEntry("Mousewheel Increment", GlobalTextureBrowser().m_mouseWheelScrollIncrement); - { - const char *startup_shaders[] = {"None", TextureBrowser_getComonShadersName()}; - page.appendCombo("Load Shaders at Startup", reinterpret_cast( GlobalTextureBrowser().m_startupShaders ), - STRING_ARRAY_RANGE(startup_shaders)); - } -} - -void TextureBrowser_constructPage(PreferenceGroup &group) -{ - PreferencesPage page(group.createPage("Texture Browser", "Texture Browser Preferences")); - TextureBrowser_constructPreferences(page); -} - -void TextureBrowser_registerPreferencesPage() -{ - PreferencesDialog_addSettingsPage(makeCallbackF(TextureBrowser_constructPage)); +void TextureBrowser_constructPreferences( PreferencesPage& page ){ + page.appendCheckBox( + "", "Texture scrollbar", + make_property(GlobalTextureBrowser()) + ); + { + const char* texture_scale[] = { "10%", "25%", "50%", "100%", "200%" }; + page.appendCombo( + "Texture Thumbnail Scale", + STRING_ARRAY_RANGE( texture_scale ), + make_property(GlobalTextureBrowser()) + ); + } + page.appendSpinner( + "Texture Thumbnail Size", + GlobalTextureBrowser().m_uniformTextureSize, + GlobalTextureBrowser().m_uniformTextureSize, + 16, 8192 + ); + page.appendEntry( "Mousewheel Increment", GlobalTextureBrowser().m_mouseWheelScrollIncrement ); + { + const char* startup_shaders[] = { "None", TextureBrowser_getComonShadersName() }; + page.appendCombo( "Load Shaders at Startup", reinterpret_cast( GlobalTextureBrowser().m_startupShaders ), STRING_ARRAY_RANGE( startup_shaders ) ); + } +} +void TextureBrowser_constructPage( PreferenceGroup& group ){ + PreferencesPage page( group.createPage( "Texture Browser", "Texture Browser Preferences" ) ); + TextureBrowser_constructPreferences( page ); +} + +void TextureBrowser_registerPreferencesPage(){ + PreferencesDialog_addSettingsPage( makeCallbackF(TextureBrowser_constructPage) ); } @@ -2759,69 +2654,52 @@ void TextureBrowser_registerPreferencesPage() #include "stringio.h" -void TextureClipboard_textureSelected(const char *shader); +void TextureClipboard_textureSelected( const char* shader ); -void TextureBrowser_Construct() -{ - GlobalCommands_insert("ShaderInfo", makeCallbackF(TextureBrowser_shaderInfo)); - GlobalCommands_insert("ShowUntagged", makeCallbackF(TextureBrowser_showUntagged)); - GlobalCommands_insert("AddTag", makeCallbackF(TextureBrowser_addTag)); - GlobalCommands_insert("RenameTag", makeCallbackF(TextureBrowser_renameTag)); - GlobalCommands_insert("DeleteTag", makeCallbackF(TextureBrowser_deleteTag)); - GlobalCommands_insert("CopyTag", makeCallbackF(TextureBrowser_copyTag)); - GlobalCommands_insert("PasteTag", makeCallbackF(TextureBrowser_pasteTag)); - GlobalCommands_insert("RefreshShaders", makeCallbackF(VFS_Refresh)); - GlobalToggles_insert("ShowInUse", makeCallbackF(TextureBrowser_ToggleHideUnused), - ToggleItem::AddCallbackCaller(g_TextureBrowser.m_hideunused_item), Accelerator('U')); - GlobalCommands_insert("ShowAllTextures", makeCallbackF(TextureBrowser_showAll), - Accelerator('A', (GdkModifierType) GDK_CONTROL_MASK)); - GlobalCommands_insert("ToggleTextures", makeCallbackF(TextureBrowser_toggleShow), Accelerator('T')); - GlobalToggles_insert("ToggleShowShaders", makeCallbackF(TextureBrowser_ToggleShowShaders), - ToggleItem::AddCallbackCaller(g_TextureBrowser.m_showshaders_item)); - GlobalToggles_insert("ToggleShowShaderlistOnly", makeCallbackF(TextureBrowser_ToggleShowShaderListOnly), - ToggleItem::AddCallbackCaller(g_TextureBrowser.m_showshaderlistonly_item)); - GlobalToggles_insert("FixedSize", makeCallbackF(TextureBrowser_FixedSize), - ToggleItem::AddCallbackCaller(g_TextureBrowser.m_fixedsize_item)); - GlobalToggles_insert("FilterMissing", makeCallbackF(TextureBrowser_FilterMissing), - ToggleItem::AddCallbackCaller(g_TextureBrowser.m_filternotex_item)); - GlobalToggles_insert("FilterFallback", makeCallbackF(TextureBrowser_FilterFallback), - ToggleItem::AddCallbackCaller(g_TextureBrowser.m_hidenotex_item)); - GlobalToggles_insert("EnableAlpha", makeCallbackF(TextureBrowser_EnableAlpha), - ToggleItem::AddCallbackCaller(g_TextureBrowser.m_enablealpha_item)); - - GlobalPreferenceSystem().registerPreference("TextureScale", make_property_string(g_TextureBrowser)); - GlobalPreferenceSystem().registerPreference("UniformTextureSize", - make_property_string(g_TextureBrowser)); - GlobalPreferenceSystem().registerPreference("TextureScrollbar", make_property_string( - GlobalTextureBrowser())); - GlobalPreferenceSystem().registerPreference("ShowShaders", - make_property_string(GlobalTextureBrowser().m_showShaders)); - GlobalPreferenceSystem().registerPreference("ShowShaderlistOnly", - make_property_string(g_TextureBrowser_shaderlistOnly)); - GlobalPreferenceSystem().registerPreference("FixedSize", make_property_string(g_TextureBrowser_fixedSize)); - GlobalPreferenceSystem().registerPreference("FilterMissing", make_property_string(g_TextureBrowser_filterMissing)); - GlobalPreferenceSystem().registerPreference("EnableAlpha", make_property_string(g_TextureBrowser_enableAlpha)); - GlobalPreferenceSystem().registerPreference("LoadShaders", make_property_string( - reinterpret_cast( GlobalTextureBrowser().m_startupShaders ))); - GlobalPreferenceSystem().registerPreference("WheelMouseInc", make_property_string( - GlobalTextureBrowser().m_mouseWheelScrollIncrement)); - GlobalPreferenceSystem().registerPreference("SI_Colors0", - make_property_string(GlobalTextureBrowser().color_textureback)); - - g_TextureBrowser.shader = texdef_name_default(); - - Textures_setModeChangedNotify(ReferenceCaller(g_TextureBrowser)); - - TextureBrowser_registerPreferencesPage(); - - GlobalShaderSystem().attach(g_ShadersObserver); - - TextureBrowser_textureSelected = TextureClipboard_textureSelected; -} - -void TextureBrowser_Destroy() -{ - GlobalShaderSystem().detach(g_ShadersObserver); +void TextureBrowser_Construct(){ + GlobalCommands_insert( "ShaderInfo", makeCallbackF(TextureBrowser_shaderInfo) ); + GlobalCommands_insert( "ShowUntagged", makeCallbackF(TextureBrowser_showUntagged) ); + GlobalCommands_insert( "AddTag", makeCallbackF(TextureBrowser_addTag) ); + GlobalCommands_insert( "RenameTag", makeCallbackF(TextureBrowser_renameTag) ); + GlobalCommands_insert( "DeleteTag", makeCallbackF(TextureBrowser_deleteTag) ); + GlobalCommands_insert( "CopyTag", makeCallbackF(TextureBrowser_copyTag) ); + GlobalCommands_insert( "PasteTag", makeCallbackF(TextureBrowser_pasteTag) ); + GlobalCommands_insert( "RefreshShaders", makeCallbackF(VFS_Refresh) ); + GlobalToggles_insert( "ShowInUse", makeCallbackF(TextureBrowser_ToggleHideUnused), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_hideunused_item ), Accelerator( 'U' ) ); + GlobalCommands_insert( "ShowAllTextures", makeCallbackF(TextureBrowser_showAll), Accelerator( 'A', (GdkModifierType)GDK_CONTROL_MASK ) ); + GlobalCommands_insert( "ToggleTextures", makeCallbackF(TextureBrowser_toggleShow), Accelerator( 'T' ) ); + GlobalToggles_insert( "ToggleShowShaders", makeCallbackF(TextureBrowser_ToggleShowShaders), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_showshaders_item ) ); + GlobalToggles_insert( "ToggleShowShaderlistOnly", makeCallbackF(TextureBrowser_ToggleShowShaderListOnly), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_showshaderlistonly_item ) ); + GlobalToggles_insert( "FixedSize", makeCallbackF(TextureBrowser_FixedSize), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_fixedsize_item ) ); + GlobalToggles_insert( "FilterMissing", makeCallbackF(TextureBrowser_FilterMissing), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_filternotex_item ) ); + GlobalToggles_insert( "FilterFallback", makeCallbackF(TextureBrowser_FilterFallback), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_hidenotex_item ) ); + GlobalToggles_insert( "EnableAlpha", makeCallbackF(TextureBrowser_EnableAlpha), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_enablealpha_item ) ); + + GlobalPreferenceSystem().registerPreference( "TextureScale", make_property_string(g_TextureBrowser) ); + GlobalPreferenceSystem().registerPreference( "UniformTextureSize", make_property_string(g_TextureBrowser) ); + GlobalPreferenceSystem().registerPreference( "TextureScrollbar", make_property_string(GlobalTextureBrowser())); + GlobalPreferenceSystem().registerPreference( "ShowShaders", make_property_string( GlobalTextureBrowser().m_showShaders ) ); + GlobalPreferenceSystem().registerPreference( "ShowShaderlistOnly", make_property_string( g_TextureBrowser_shaderlistOnly ) ); + GlobalPreferenceSystem().registerPreference( "FixedSize", make_property_string( g_TextureBrowser_fixedSize ) ); + GlobalPreferenceSystem().registerPreference( "FilterMissing", make_property_string( g_TextureBrowser_filterMissing ) ); + GlobalPreferenceSystem().registerPreference( "EnableAlpha", make_property_string( g_TextureBrowser_enableAlpha ) ); + GlobalPreferenceSystem().registerPreference( "LoadShaders", make_property_string( reinterpret_cast( GlobalTextureBrowser().m_startupShaders ) ) ); + GlobalPreferenceSystem().registerPreference( "WheelMouseInc", make_property_string( GlobalTextureBrowser().m_mouseWheelScrollIncrement ) ); + GlobalPreferenceSystem().registerPreference( "SI_Colors0", make_property_string( GlobalTextureBrowser().color_textureback ) ); + + g_TextureBrowser.shader = texdef_name_default(); + + Textures_setModeChangedNotify( ReferenceCaller( g_TextureBrowser ) ); + + TextureBrowser_registerPreferencesPage(); + + GlobalShaderSystem().attach( g_ShadersObserver ); + + TextureBrowser_textureSelected = TextureClipboard_textureSelected; +} + +void TextureBrowser_Destroy(){ + GlobalShaderSystem().detach( g_ShadersObserver ); - Textures_setModeChangedNotify(Callback()); + Textures_setModeChangedNotify( Callback() ); } -- 2.39.2