/*********************/ /*** Elem Stuph ***/ /*********************/ #include "stdafx.h" #include <Vector3.h> #include <gl\gl.h> #include <gl\glu.h> #include "GLEnabledView.h" #include <Vector> #include <GFName.hpp> #include "Core.h" #include "TexCache.h" #include "Elem.h" #include "GinTex.h" #include "utils.h" #include "MapEdit.h" #include "MapEditDoc.h" #include "MapEditView.h" #include "MainFrm.h" #include "GUITileBank.h" const Vector3 DefOfs(+0.5f,0,+4.0f); int CElem::BlankID=-1; int CElem::InvalidID=-1; bool CElem::DefTexFlag=false; /*****************************************************************************/ // All Elems MUST run from 0,0 -> /*****************************************************************************/ const float ElemBrowserGap=0.2f; const float ElemBrowserX0=0-ElemBrowserGap/2; const float ElemBrowserX1=1+ElemBrowserGap/2; const float ElemBrowserY0=0-ElemBrowserGap/2; const float ElemBrowserY1=1+ElemBrowserGap/2; /*****************************************************************************/ const float XFlipMtx[]= { -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, }; const float YFlipMtx[]= { 1, 0, 0, 0, 0,-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, }; /*****************************************************************************/ CElem::CElem(int Width,int Height) { ElemWidth=Width; ElemHeight=Height; UnitWidth=ElemWidth/UnitSize; UnitHeight=ElemHeight/UnitSize; ElemID=-1; int AW=AlignSize(ElemWidth); int AH=AlignSize(ElemHeight); ElemRGB=0; ElemRGB=(u8*)MemAlloc(AW*AH*3); memset(ElemRGB,0,AW*AH*3); Type=ElemType2d; TexXOfs=0; TexYOfs=0; BlankFlag=true; } /*****************************************************************************/ // 3d Elem (From Gin File) CElem::CElem(CCore *Core,const char *Filename,CScene &ThisScene,int Node) { CNode &ThisNode=ThisScene.GetNode(Node); CTexCache &TexCache=Core->GetTexCache(); GFName Path=Filename; SetPath=Path.Drive(); SetPath+=Path.Dir(); SetPath.Append('\\'); Type=ElemType3d; TexXOfs=-1; TexYOfs=-1; ElemRGB=0; Ofs.Zero(); Build3dElem(TexCache,ThisScene,Node); Calc3dSize(); Build3dDrawList(TexCache,DrawList[ElemType3d]); Ofs.Zero(); Create2dTexture(TexCache,Path.File(),Node); Build2dDrawList(TexCache,DrawList[ElemType2d]); BlankFlag=false; // if (!ValidFlag) SetInvalid(); } /*****************************************************************************/ // 2d Elem (From Bmp File) // 0,0 1,0 1,1 0,1 CElem::CElem(CCore *Core,const char *Filename,int TexID,int XOfs,int YOfs,int Width,int Height,int CentreMode) { CTexCache &TexCache=Core->GetTexCache(); GFName Path=Filename; ElemWidth=Width; ElemHeight=Height; UnitWidth=ElemWidth/UnitSize; UnitHeight=ElemHeight/UnitSize; ElemRGB=0; Type=ElemType2d; TexXOfs=XOfs; TexYOfs=YOfs; Ofs.Zero(); if (CentreMode & CentreModeL) { // Nothing to do, already there } if (CentreMode & CentreModeR) { Ofs.x-=UnitWidth; } if (CentreMode & CentreModeT) { Ofs.y-=UnitHeight; } if (CentreMode & CentreModeB) { // Nothing to do, already there } if (CentreMode & CentreModeLR) { Ofs.x-=(UnitWidth-1.0f)/2; } if (CentreMode & CentreModeTB) { Ofs.y-=(UnitHeight-1.0f)/2; } Build2dElem(Core,Path.File(),TexID); Build3dDrawList(TexCache,DrawList[ElemType3d]); Create2dTexture(TexCache,Path.File(),TexID); Build2dDrawList(TexCache,DrawList[ElemType2d]); BlankFlag=false; if (!ValidFlag) SetInvalid(); } /*****************************************************************************/ void CElem::CleanUp() { if (ElemRGB) MemFree(ElemRGB); ElemRGB=0; } /*****************************************************************************/ void CElem::SetBlank() { for (int i=0; i<ElemTypeMax; i++) DrawList[i]=BlankID; } /*****************************************************************************/ void CElem::SetInvalid() { Purge(); // Clear whatever is already there for (int i=0; i<ElemTypeMax; i++) DrawList[i]=InvalidID; } /*****************************************************************************/ void CElem::Build2dElem(CCore *Core,const char *Filename,int TexID) { float X0=0; float X1=+UnitWidth; float Y0=0; float Y1=+UnitHeight; Vector3 P0(X0,Y0,0); Vector3 P1(X1,Y0,0); Vector3 P2(X0,Y1,0); Vector3 P3(X1,Y1,0); int ListSize=TriList.size(); TriList.resize(ListSize+2); sTriFace &Tri0=TriList[ListSize+0]; sTriFace &Tri1=TriList[ListSize+1]; CTexCache &TexCache=Core->GetTexCache(); sTex &ThisTex=TexCache.GetTex(TexID); int CountW=ThisTex.OldW/ElemWidth; int CountH=ThisTex.OldH/ElemHeight; float dU=ThisTex.ScaleU/(float)CountW; float dV=ThisTex.ScaleV/(float)CountH; dU=(1.0f/CountW); dV=(1.0f/CountH); // dU=ThisTex.ScaleU; // dV=ThisTex.ScaleV; float u0=(TexXOfs*dU); float u1=u0+dU; float v1=1.0-(TexYOfs*dV); float v0=v1-dV; Tri0.Mat=TexID; Tri0.vtx[0]=P0; Tri0.vtx[1]=P1; Tri0.vtx[2]=P2; Tri0.uvs[0].u=u0; Tri0.uvs[0].v=v0; Tri0.uvs[1].u=u1; Tri0.uvs[1].v=v0; Tri0.uvs[2].u=u0; Tri0.uvs[2].v=v1; Tri1.Mat=TexID; Tri1.vtx[0]=P1; Tri1.vtx[1]=P2; Tri1.vtx[2]=P3; Tri1.uvs[0].u=u1; Tri1.uvs[0].v=v0; Tri1.uvs[1].u=u0; Tri1.uvs[1].v=v1; Tri1.uvs[2].u=u1; Tri1.uvs[2].v=v1; } /*****************************************************************************/ void CElem::Build3dElem(CTexCache &TexCache,CScene &ThisScene,int Node) { CNode &ThisNode=ThisScene.GetNode(Node); CNode &ParentNode=ThisScene.GetNode(ThisNode.ParentIdx); int ChildCount=ThisNode.GetPruneChildCount(); std::vector<sGinTri> const &NodeTriList=ThisNode.GetTris(); std::vector<Vector3>const &NodeVtxList=ThisNode.GetPts(); std::vector<sUVTri> const &NodeUVList=ThisNode.GetUVTris(); std::vector<int> const &NodeTriMat=ThisNode.GetTriMaterial(); std::vector<GString> const &SceneTexList=ThisScene.GetTexList(); std::vector<int> const &SceneUsedMatList=ThisScene.GetUsedMaterialIdx(); std::vector<Material> const &SceneMatList=ThisScene.GetMaterials(); int TexCount=SceneTexList.size(); int TriCount=NodeTriList.size(); int ListSize=TriList.size(); TriList.resize(ListSize+TriCount); for (int T=0; T<TriCount; T++) { sGinTri const &ThisTri=NodeTriList[T]; sUVTri const &ThisUV=NodeUVList[T]; sTriFace &Tri=TriList[ListSize+T]; int ThisMat=NodeTriMat[T]; int TexID,TexFlags; // Sort Textures - Only add the ones that are used :o) TexID=SceneUsedMatList[ThisMat]; if (TexID<0 || TexID>=TexCount) { CString mexstr; mexstr.Format("Invalid TexId\n Wanted %i only have %i Id's for %s\nThis is gonna hurt!\n Dont ask me about this error, ask Kev.\n This MUST be fixed.",TexID,TexCount-1,ThisNode.Name); AfxMessageBox(mexstr,MB_OK | MB_ICONEXCLAMATION); TexID=0; } // else { TexFlags=SceneMatList[TexID].Flags; GString ThisName; GString TexName=SceneTexList[TexID]; ThisName=SetPath+TexName; // TRACE2("%i !%s!\n",TexID,ThisName); TexID=TexCache.ProcessTexture(ThisName); } // Sort Rest of Tri info Matrix4x4 TransMtx; TransMtx.Identity(); if (ParentNode.GetTris().size() || !ThisNode.ParentIdx) { TransMtx=ThisNode.Mtx; TransMtx.Invert(); } for (int p=0; p<3; p++) { Tri.vtx[p]=TransMtx*NodeVtxList[ThisTri.p[p]]; Tri.uvs[p].u=ThisUV.p[p].u; Tri.uvs[p].v=ThisUV.p[p].v; Tri.Mat=TexID; Tri.Flags=TexFlags; } } for (int Child=0; Child<ChildCount; Child++) Build3dElem(TexCache,ThisScene,ThisNode.PruneChildList[Child]); } /*****************************************************************************/ void CElem::Calc3dSize() { int i,ListSize=TriList.size(); Vector3 Min(+32000,+32000,+32000); Vector3 Max(-32000,-32000,-32000); Vector3 Mid; for (i=0; i<ListSize; i++) { sTriFace &Tri=TriList[i]; for (int p=0; p<3; p++) { if (Min.x>Tri.vtx[p].x) Min.x=Tri.vtx[p].x; if (Min.y>Tri.vtx[p].y) Min.y=Tri.vtx[p].y; if (Min.z>Tri.vtx[p].z) Min.z=Tri.vtx[p].z; if (Max.x<Tri.vtx[p].x) Max.x=Tri.vtx[p].x; if (Max.y<Tri.vtx[p].y) Max.y=Tri.vtx[p].y; if (Max.z<Tri.vtx[p].z) Max.z=Tri.vtx[p].z; } } UnitWidth=round(Max.x-Min.x); UnitHeight=round(Max.y-Min.y); if (UnitWidth<1) UnitWidth=1; if (UnitHeight<1) UnitHeight=1; ElemWidth=UnitWidth*UnitSize; ElemHeight=UnitHeight*UnitSize; Min.z=0; Ofs=DefOfs; // Ofs.x=+0.5f; Ofs.y=0; Ofs.z=+4.0f; } /*****************************************************************************/ void CElem::Build2dDrawList(CTexCache &TexCache,GLint &List) { float X0=Ofs.x; float X1=Ofs.x+UnitWidth; float Y0=Ofs.y; float Y1=Ofs.y+UnitHeight; float Z=Ofs.z; sTex &Tex=TexCache.GetTex(ElemID); float u0=0; float u1=1.0f;//Tex.ScaleU; float v0=0; float v1=1.0f;//Tex.ScaleU; List=glGenLists(1); glNewList(List,GL_COMPILE); TexID=Tex.TexID; glBindTexture(GL_TEXTURE_2D, Tex.TexID); glBegin (GL_QUADS); glTexCoord2f(u0,v0); glVertex3f(X0,Y0,Z); glTexCoord2f(u1,v0); glVertex3f(X1,Y0,Z); glTexCoord2f(u1,v1); glVertex3f(X1,Y1,Z); glTexCoord2f(u0,v1); glVertex3f(X0,Y1,Z); glEnd(); glEndList(); } /*****************************************************************************/ // Build OpenGL display lists, sorted by material (luckily by gin!!) void CElem::Build3dDrawList(CTexCache &TexCache,GLint &List) { int TriCount=TriList.size(); int LastMat=-1,ThisMat; float ScaleU,ScaleV; List=glGenLists(1); glNewList(List,GL_COMPILE); for (int T=0; T<TriCount; T++) { sTriFace &ThisTri=TriList[T]; ThisMat=ThisTri.Mat; if (!T || ThisMat!=LastMat) // First Tri or new material { if (T) glEnd(); // Not first tri, so end previous mat set glBindTexture(GL_TEXTURE_2D, TexCache.GetTexGLId(ThisMat)); glBegin (GL_TRIANGLES); LastMat=ThisMat; sTex &Tex=TexCache.GetTex(ThisMat); ScaleU=Tex.ScaleU; ScaleV=Tex.ScaleV; } for (int p=0; p<3; p++) { Vector3 &ThisVtx=ThisTri.vtx[p]; float u=ThisTri.uvs[p].u*ScaleU; float v=ThisTri.uvs[p].v*ScaleV; glTexCoord2f(u,v); glVertex3f( (ThisVtx.x+Ofs.x), (ThisVtx.y+Ofs.y), -(ThisVtx.z+Ofs.z)); // Neg Z (cos openGL) } } glEnd(); glEndList(); } /*****************************************************************************/ struct sColTab { u8 R,G,B; }; sColTab ColTable[]= { {255,255,255}, // PC_TILE_COLLISION_NORMAL: {255, 0, 0}, // PC_TILE_COLLISION_DAMAGE: { 0,255, 0}, // PC_TILE_COLLISION_SLIPPERY: {255, 0,255}, // PC_TILE_COLLISION_ELECTRIC: {200,127,180}, // PC_TILE_COLLISION_DESTRUCTABLE_WALL: { 0,127,255}, // PC_TILE_COLLISION_SOAK_UP: { 0,255,255}, // PC_TILE_COLLISION_SOLID: {200, 0, 0}, // PC_TILE_COLLISION_DEATH_FALL: {127,200,180}, // PC_TILE_COLLISION_DESTRUCTABLE_FLOOR: {255,127,127}, // PC_TILE_COLLISION_DEATH_INSTANT: { 0,127, 0}, // PC_TILE_COLLISION_MOVE_LEFT: { 0,127,127}, // PC_TILE_COLLISION_MOVE_RIGHT: { 0, 0,255}, // PC_TILE_COLLISION_DEATH_LIQUID: }; void CElem::Render(int Flags,bool Render3d) { if (BlankFlag) { glCallList(BlankID); return; } glPushMatrix(); if (Flags & PC_TILE_FLAG_MIRROR_X) { glTranslatef(1,0,0); glMultMatrixf(XFlipMtx); } if (Flags & PC_TILE_FLAG_MIRROR_Y) { glTranslatef(0,1,0); glMultMatrixf(YFlipMtx); } int ColFlags=Flags >> PC_TILE_FLAG_COLLISION_SHIFT; if (ColFlags) { sColTab &ThisCol=ColTable[ColFlags]; glColor4ub(ThisCol.R,ThisCol.G,ThisCol.B,127); } glEnable(GL_TEXTURE_2D); if (Render3d) { glEnable(GL_DEPTH_TEST); glCallList(DrawList[ElemType3d]); glDisable(GL_DEPTH_TEST); } else { glCallList(DrawList[ElemType2d]); } glDisable(GL_TEXTURE_2D); glPopMatrix(); } /*****************************************************************************/ void CElem::Purge() { for (int i=0; i<ElemTypeMax; i++) glDeleteLists(DrawList[i],1); CleanUp(); // TriList.clear(); } /*****************************************************************************/ // Only created for the tile browser, should NEVER appear in main view void CElem::CreateDefaultTileGfx() { float X0=0; float X1=1.0f; float Y0=0; float Y1=1.0f; DefTexFlag=true; // Blank if (BlankID==-1) { BlankID=glGenLists(1); glNewList(BlankID,GL_COMPILE); glBindTexture(GL_TEXTURE_2D, 0); glBegin(GL_LINES); glColor4f(1,1,1,1); glVertex3f( X0,Y0,0); glVertex3f( X1,Y0,0); glVertex3f( X0,Y1,0); glVertex3f( X1,Y1,0); glVertex3f( X0,Y0,0); glVertex3f( X0,Y1,0); glVertex3f( X1,Y0,0); glVertex3f( X1,Y1,0); glEnd(); glEndList(); } // Invalid if (InvalidID==-1) { InvalidID=glGenLists(1); glNewList(InvalidID,GL_COMPILE); glBindTexture(GL_TEXTURE_2D, 0); glBegin(GL_LINES); glColor4f(1,1,1,1); glVertex3f( X0,Y0,0); glVertex3f( X1,Y1,0); glVertex3f( X1,Y0,0); glVertex3f( X0,Y1,0); glEnd(); glEndList(); } } /*****************************************************************************/ void CElem::RenderElem4Texture(sRGBData &RGBData) { float W=UnitWidth; float H=UnitHeight; glClearColor(1,0,1,1 ); // glClearColor(1,1,1,1 ); glPushAttrib(GL_VIEWPORT_BIT); glViewport(0,0,RGBData.TexW,RGBData.TexH); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, W, 0, H, -16.0f, +16.0f); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslatef(-Ofs.x,-Ofs.y,-Ofs.z); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen glColor3f(1,1,1); glEnable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); glCallList(DrawList[ElemType3d]); glDisable(GL_DEPTH_TEST); glDisable(GL_TEXTURE_2D); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); glReadPixels(0,0,RGBData.TexW,RGBData.TexH,GL_RGB, GL_UNSIGNED_BYTE,RGBData.RGB); glClearColor(0,0,0,1 ); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen } /*****************************************************************************/ // ID used to create unique textures within one set :o) void CElem::Create2dTexture(CTexCache &TexCache,const char *Filename,int ID) { sRGBData RGBData; char TexName[256]; sprintf(TexName,"_2dPc_%s_%03d",Filename,ID); int AW=AlignSize(ElemWidth); int AH=AlignSize(ElemHeight); ElemRGB=(u8*)MemAlloc(AW*AH*3); RGBData.TexW=AlignSize(ElemWidth); RGBData.TexH=AlignSize(ElemHeight); RGBData.ScaleU=1.0f; RGBData.ScaleV=1.0f; RGBData.RGB=ElemRGB; RenderElem4Texture(RGBData); ElemID=TexCache.ProcessTexture(TexName,&RGBData); ValidFlag=CheckHasData(RGBData); #ifdef _DEBUG if (0) { char Filename[256]; sprintf(Filename,"/x/%s.Tga",TexName); SaveTGA(Filename,ElemWidth,ElemHeight,ElemRGB); } #endif } /*****************************************************************************/ bool CElem::CheckHasData(sRGBData &RGBData) { u8 *Src=RGBData.RGB; int Size=RGBData.TexW*RGBData.TexH; while (Size--) { u8 R=*Src++; u8 G=*Src++; u8 B=*Src++; if (R!=255 || G!=0 || B!=255) return(true); } return(false); } /*****************************************************************************/ /*****************************************************************************/ /*** Elem Set ****************************************************************/ /*****************************************************************************/ /*****************************************************************************/ CElemSet::CElemSet(const char *_Filename,int Idx,int Width,int Height,bool CreateBlank,int Centre) { GFName FName=_Filename; Filename=_Filename; Name=FName.File(); MaxWidth=Width; MaxHeight=Height; CentreMode=Centre; Loaded=FALSE; SetNumber=Idx; if (CreateBlank) { ElemList.push_back(CElem(MaxWidth,MaxHeight)); // Insert Blank } } /*****************************************************************************/ CElemSet::~CElemSet() { } /*****************************************************************************/ void CElemSet::CleanUp() { int ListSize=ElemList.size(); for (int i=0; i<ListSize; i++) { ElemList[i].CleanUp(); } } /*****************************************************************************/ void CElemSet::Load(CCore *Core) { GFName FName=Filename; GString Ext=FName.Ext(); Ext.Upper(); if (!CElem::DefTexFlag) CElem::CreateDefaultTileGfx(); if (!ElemList.size()) { // ElemList[0].SetBlank(); } if (Ext=="GIN") Load3d(Core); else Load2d(Core); Loaded=TRUE; } /*****************************************************************************/ void CElemSet::Load2d(CCore *Core) { CTexCache &TexCache=Core->GetTexCache(); int TexID=TexCache.ProcessTexture(Filename); sTex &ThisTex=TexCache.GetTex(TexID); int Width,Height; if (MaxWidth==-1) MaxWidth=ThisTex.OldW; if (MaxHeight==-1) MaxHeight=ThisTex.OldH; Width=ThisTex.OldW/MaxWidth; Height=ThisTex.OldH/MaxHeight; for (int Y=0; Y<Height; Y++) { for (int X=0; X<Width; X++) { ElemList.push_back(CElem(Core,Filename,TexID,X,Y,MaxWidth,MaxHeight,CentreMode)); } } ElemBrowserWidth=Width; } /*****************************************************************************/ void CElemSet::Load3d(CCore *Core) { CScene Scene; Scene.Load(Filename); CNode &ThisNode=Scene.GetSceneNode(0); int ChildCount=ThisNode.GetPruneChildCount(); for (int Child=0; Child<ChildCount; Child++) { ElemList.push_back(CElem(Core,Filename,Scene,ThisNode.PruneChildList[Child])); } ElemBrowserWidth=DEF_ELEMBROWSWEWIDTH; } /*****************************************************************************/ void CElemSet::Purge() { int i,ListSize=ElemList.size(); for (i=0; i<ListSize; i++) { if (!ElemList[i].IsBlank()) { ElemList[i].Purge(); } } if (ElemList[0].IsBlank()) { ElemList.erase(1,ListSize); } else { ElemList.clear(); } Loaded=FALSE; } /*****************************************************************************/ CPoint CElemSet::GetElemPos(int ID) { if (ID==0) return(CPoint(-1,-1)); else return(IDToPoint(ID-1,ElemBrowserWidth)); } /*****************************************************************************/ bool CElemSet::IsValid(int No) { int ListSize=ElemList.size(); if (No>=ListSize) return(false); return(ElemList[No].IsValid()); } /*****************************************************************************/ /*****************************************************************************/ /*** Elem Bank ***************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ CElemBank::CElemBank(int W,int H,bool Blank,int Centre) { MaxWidth=W; MaxHeight=H; BlankFlag=Blank; CentreMode=Centre; LoadFlag=false; CurrentSet=0; LayerDef.VisibleFlag=true; } /*****************************************************************************/ CElemBank::~CElemBank() { } /*****************************************************************************/ void CElemBank::CleanUp() { int ListSize=SetList.size(); for (int i=0; i<ListSize; i++) { SetList[i].CleanUp(); } } /*****************************************************************************/ void CElemBank::Load(CFile *File,int Version) { int ListSize; GFName RootPath=File->GetFilePath(); GString FilePath; char FixPath[1024]; FilePath=RootPath.Drive(); FilePath+=RootPath.Dir(); FilePath.Append('\\'); FilePath.Upper(); if (Version>=5) { File->Read(&CurrentSet,sizeof(int)); } File->Read(&ListSize,sizeof(int)); // New Style rel storage for (int i=0;i<ListSize;i++) { char c=1; GString FullName;//=FilePath; while (c) { File->Read(&c,1); FullName.Append(c); } FullName.Upper(); GFName::makeabsolute(FilePath,FullName,FixPath); FullName=FixPath; _fullpath( FixPath, FullName, 1024); for (int z=0; z<strlen(FixPath); z++) {// Invalidate any long name short cackness if (FixPath[z]=='~') FixPath[z]='_'; } FullName=FixPath; CheckFilename(FullName); FullName.Upper(); AddSet(FullName); } } /*****************************************************************************/ void CElemBank::Save(CFile *File) { int ListSize=SetList.size(); GFName RootPath=File->GetFilePath(); GString SavePath; SavePath=RootPath.Drive(); SavePath+=RootPath.Dir(); SavePath.Append('\\'); SavePath.Upper(); File->Write(&CurrentSet,sizeof(int)); File->Write(&ListSize,sizeof(int)); for (int i=0; i<ListSize; i++) { char Filename[256+64]; RootPath.makerelative(SavePath,SetList[i].GetFilename(),Filename); File->Write(Filename,strlen(Filename)+1); } } /*****************************************************************************/ int CElemBank::AddSet(const char *Filename) { int ListSize=SetList.size(); CElemSet NewSet(Filename,ListSize,MaxWidth,MaxHeight,BlankFlag,CentreMode); int Idx=SetList.Add(NewSet); if (SetList.size()!=ListSize) LoadFlag=TRUE; return(Idx); } /*****************************************************************************/ void CElemBank::LoadAllSets(CCore *Core) { int ListSize=SetList.size(); if (!LoadFlag) return; for (int i=0;i<ListSize;i++) { CElemSet &ThisSet=SetList[i]; if (!ThisSet.IsLoaded()) ThisSet.Load(Core); } LoadFlag=false; } /*****************************************************************************/ void CElemBank::LoadNewSet(CCore *Core) { char BASED_CODE GinFilter[]= "All Tile Files (*.Gin; *.Bmp)|*.gin;*.Bmp|3d Tile Files (*.Gin)|*.Gin|2d Tile Files (*.Bmp)|*.Bmp|All Files (*.*)|*.*||"; CFileDialog Dlg(TRUE,"Gin",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,GinFilter); if (Dlg.DoModal()!=IDOK) return; char Filename[256]; sprintf(Filename,"%s",Dlg.GetPathName()); AddSet(Filename); } /*****************************************************************************/ void CElemBank::ReloadAllSets() { int ListSize=SetList.size(); for (int i=0; i<ListSize; i++) { SetList[i].Purge(); } LoadFlag=TRUE; } /*****************************************************************************/ void CElemBank::DeleteSet(int Set) { SetList.erase(Set); } /*****************************************************************************/ bool CElemBank::IsValid(int Set,int Elem) { if (Set<0 || Elem<0) return(false); if (Elem==0) return(true); if (Set>=SetList.size()) return(false); // if (Set>SetList.size()) return(false); ASSERT(Set<SetList.size()); return(SetList[Set].IsValid(Elem)); } /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ CPoint CElemBank::GetElemPos(int ID,int Width) { if (ID==0) return(CPoint(-1,-1)); else return(IDToPoint(ID-1,Width)); } /*****************************************************************************/ void CElemBank::RenderElem(int Set,int Elem,int Flags,bool Is3d) { if (IsValid(Set,Elem)) { SetList[Set].RenderElem(Elem,Flags,Is3d); } else { RenderInvalid(); } } /*****************************************************************************/ void CElemBank::RenderGrid(CCore *Core,Vector3 &CamPos,bool Active) { if (!GetSetCount()) return; CElemSet &ThisSet=SetList[CurrentSet]; int ListSize=ThisSet.GetCount(); int BrowserWidth=ThisSet.GetBrowserWidth(); int TileID=1; // Dont bother with blank, its sorted float Scale=CamPos.z/(float)BrowserWidth/2.0; if (!ListSize) return; glMatrixMode(GL_MODELVIEW); glPushMatrix(); while(TileID!=ListSize) { CPoint Pos=GetElemPos(TileID,BrowserWidth); float XPos=(float)Pos.x*(1+ElemBrowserGap); float YPos=(float)Pos.y*(1+ElemBrowserGap); glLoadIdentity(); glScalef(Scale,Scale,Scale); glTranslatef(-CamPos.x+XPos,CamPos.y-YPos,0); glBegin(GL_LINES); glColor3f(1,1,1); glVertex3f( ElemBrowserX0,ElemBrowserY0,0); glVertex3f( ElemBrowserX1,ElemBrowserY0,0); glVertex3f( ElemBrowserX0,ElemBrowserY1,0); glVertex3f( ElemBrowserX1,ElemBrowserY1,0); glVertex3f( ElemBrowserX0,ElemBrowserY0,0); glVertex3f( ElemBrowserX0,ElemBrowserY1,0); glVertex3f( ElemBrowserX1,ElemBrowserY0,0); glVertex3f( ElemBrowserX1,ElemBrowserY1,0); glEnd(); TileID++; } glPopMatrix(); } /*****************************************************************************/ void CElemBank::FindCursorPos(CCore *Core,Vector3 &CamPos,CPoint &MousePos) { if (!GetSetCount()) return; CElemSet &ThisSet=SetList[CurrentSet]; int ListSize=ThisSet.GetCount(); int BrowserWidth=ThisSet.GetBrowserWidth(); GLint Viewport[4]; GLuint SelectBuffer[SELECT_BUFFER_SIZE]; int HitCount; int TileID=0; float Scale=CamPos.z/(float)BrowserWidth/2.0; if (!ListSize) return; glGetIntegerv(GL_VIEWPORT, Viewport); glSelectBuffer (SELECT_BUFFER_SIZE, SelectBuffer ); glRenderMode (GL_SELECT); glInitNames(); glPushName(-1); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluPickMatrix( MousePos.x ,(Viewport[3]-MousePos.y),5.0,5.0,Viewport); Core->GetView()->SetupPersMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); while(TileID!=ListSize) { CPoint Pos=GetElemPos(TileID,BrowserWidth); float XPos=(float)Pos.x*(1+ElemBrowserGap); float YPos=(float)Pos.y*(1+ElemBrowserGap); glLoadIdentity(); glScalef(Scale,Scale,Scale); glTranslatef(-CamPos.x+XPos,CamPos.y-YPos,0); glLoadName (TileID); glBegin (GL_QUADS); BuildGLQuad(ElemBrowserX0,ElemBrowserX1,ElemBrowserY0,ElemBrowserY1,0); glEnd(); TileID++; } HitCount= glRenderMode (GL_RENDER); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); // Process hits GLuint *HitPtr=SelectBuffer; TileID=-2; if (HitCount) // Just take 1st { TileID=HitPtr[3]; } glMatrixMode(GL_MODELVIEW); // <-- Prevent arse GL assert CursorPos=TileID; } /*****************************************************************************/ /*** Gui *********************************************************************/ /*****************************************************************************/ void CElemBank::GUIInit(CCore *Core) { Core->GUIAdd(GUIElemList,IDD_ELEMLIST); } /*****************************************************************************/ void CElemBank::GUIKill(CCore *Core) { Core->GUIRemove(GUIElemList,IDD_ELEMLIST); } /*****************************************************************************/ void CElemBank::GUIUpdate(CCore *Core) { int ListSize=GetSetCount(); bool IsSubView=Core->IsSubView(); if (GUIElemList.m_List) { GUIElemList.m_List.ResetContent(); if (ListSize) { for (int i=0; i<ListSize; i++) { GUIElemList.m_List.AddString(GetSetName(i)); } GUIElemList.m_List.SetCurSel(CurrentSet); } else { IsSubView=FALSE; } GUIElemList.m_List.EnableWindow(IsSubView); } } /*****************************************************************************/ void CElemBank::GUIChanged(CCore *Core) { } /*****************************************************************************/