/*******************/ /*** Layer Thing ***/ /*******************/ #include "stdafx.h" #include <Vector3.h> #include <gl\gl.h> #include <gl\glu.h> #include "GLEnabledView.h" #include "MapEdit.h" #include "MapEditDoc.h" #include "MapEditView.h" #include "MainFrm.h" #include "Core.h" #include "Layer.h" #include "LayerThing.h" #include "Utils.h" #include "Export.h" /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ CLayerThing::CLayerThing(sLayerDef &Def) { InitLayer(Def); } /*****************************************************************************/ CLayerThing::~CLayerThing() { ThingBank->CleanUp(); delete ThingBank; } /*****************************************************************************/ void CLayerThing::InitLayer(sLayerDef &Def) { CLayer::InitLayer(Def); Mode=MouseModeNormal; Cursor.XY.resize(1); Cursor.ElemID=-1; CurrentDefThing=-1; CurrentThing=-1; CurrentThingPoint=0; DrawPoints=true; } /*****************************************************************************/ void CLayerThing::Load(CFile *File,int Version) { int i,ListSize; File->Read(&Mode,sizeof(MouseMode)); File->Read(&CurrentDefThing,sizeof(int)); File->Read(&CurrentThing,sizeof(int)); File->Read(&CurrentThingPoint,sizeof(int)); File->Read(&ListSize,sizeof(int)); ThingList.resize(ListSize); // Load Data for (i=0;i<ListSize;i++) { sLayerThing &ThisThing=ThingList[i]; LoadThing(File,Version,ThisThing); if (Version<9) { LoadOldThing(File,ThisThing); } else { if (Version==9) { sLayerThingDataV9 V9Data; File->Read(&V9Data,sizeof(sLayerThingDataV9)); ThisThing.Data.WaypointCount=V9Data.WaypointCount; ThisThing.Data.Flip=0; ThisThing.Data.Angle=0; ThisThing.Data.RESERVE=V9Data.RESERVE; } else { File->Read(&ThisThing.Data,sizeof(sLayerThingData)); } } } LoadThingNames(File,Version); } /*****************************************************************************/ void CLayerThing::LoadThing(CFile *File,int Version,sLayerThing &ThisThing) { int i,ListSize; File->Read(&ListSize,sizeof(int)); ThisThing.XY.resize(ListSize); for (i=0 ;i<ListSize; i++) { CPoint &ThisPoint=ThisThing.XY[i]; File->Read(&ThisPoint,sizeof(CPoint)); } } /*****************************************************************************/ void CLayerThing::LoadThingNames(CFile *File,int Version) { int i,ListSize=ThingList.size(); for (i=0;i<ListSize;i++) { char c=1; sLayerThing &ThisThing=ThingList[i]; GString &ThisName=ThisThing.Name; while (c) { File->Read(&c,1); ThisName.Append(c); } // Update Gfx ID int Idx=FindDefThing(ThisName); ThisThing.ElemID=DefList[Idx].ElemID; } } /*****************************************************************************/ void CLayerThing::Save(CFile *File) { int i,ListSize=ThingList.size(); // Always Save current version File->Write(&Mode,sizeof(MouseMode)); File->Write(&CurrentDefThing,sizeof(int)); File->Write(&CurrentThing,sizeof(int)); File->Write(&CurrentThingPoint,sizeof(int)); File->Write(&ListSize,sizeof(int)); for (i=0;i<ListSize; i++) { sLayerThing &ThisThing=ThingList[i]; SaveThing(File,ThisThing); File->Write(&ThisThing.Data,sizeof(sLayerThingData)); } SaveThingNames(File); } /*****************************************************************************/ void CLayerThing::SaveThing(CFile *File,sLayerThing &ThisThing) { int i,ListSize=ThisThing.XY.size(); File->Write(&ListSize,sizeof(int)); for (i=0 ;i<ListSize; i++) { CPoint &ThisPoint=ThisThing.XY[i]; File->Write(&ThisPoint,sizeof(CPoint)); } } /*****************************************************************************/ void CLayerThing::SaveThingNames(CFile *File) { int i,ListSize=ThingList.size(); for (i=0; i<ListSize; i++) { char Txt[256]; sprintf(Txt,ThingList[i].Name); File->Write(Txt,strlen(Txt)+1); } } /*****************************************************************************/ void CLayerThing::InitSubView(CCore *Core) { } /*****************************************************************************/ void CLayerThing::LoadThingScript(const char *Filename) { GString ExecPath; GString ScriptName; GetExecPath(ExecPath); ScriptName=ExecPath+Filename; ThingScript.LoadAndImport(ScriptName); int i,ListSize=ThingScript.GetGroupCount(); DefList.resize(ListSize); for (i=0; i<ListSize; i++) { sLayerThing &ThisDef=DefList[i]; char *Name=ThingScript.GetGroupName(i); char *Gfx=ThingScript.GetStr(Name,"gfx"); memset(&ThisDef.Data,0,sizeof(sLayerThingData)); ThisDef.Name=Name; ThisDef.Data.WaypointCount=ThingScript.GetInt(Name,"WayPoints"); ThisDef.Data.Flip=0; ThisDef.Data.Angle=0; LoadDefThing(Name,ThisDef); ThisDef.XY.resize(1); TRACE2("%s\t\t%s\n",Name,Gfx); if (Gfx) { char Filename[512]; GFName::makeabsolute(ExecPath,Gfx,Filename); ThisDef.ElemID=ThingBank->AddSet(Filename); } } } /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ void CLayerThing::Render(CCore *Core,Vector3 &CamPos,bool Is3d) { Vector3 ThisCam=Core->OffsetCam(CamPos,GetScaleFactor()); int i,ListSize=ThingList.size(); for (i=0; i<ListSize; i++) { RenderThing(Core,ThisCam,ThingList[i],Is3d,i==CurrentThing); } } /*****************************************************************************/ void CLayerThing::RenderThing(CCore *Core,Vector3 &ThisCam,sLayerThing &ThisThing,bool Render3d,bool Selected) { float ZoomW=Core->GetZoomW(); float ZoomH=Core->GetZoomH(); Vector3 &Scale=Core->GetScaleVector(); Vector3 ScrOfs(ZoomW/2,ZoomH/2,0); if (Render3d) { ScrOfs.z=-4.0f; } glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glScalef(Scale.x,Scale.y,Scale.z); glTranslatef(-ThisCam.x,ThisCam.y,0); // Set scroll offset glTranslatef(-ScrOfs.x,ScrOfs.y,0); // Bring to top left corner int ListSize=ThisThing.XY.size(); for (int i=0;i<ListSize; i++) { // Render Thing glPushMatrix(); glTranslatef(ThisThing.XY[i].x,-ThisThing.XY[i].y,0); // Set Pos if (i==0) { glColor4f(1,1,1,1); // Set default Color glEnable(GL_DEPTH_TEST); glTranslatef(0,0,ScrOfs.z); glPushMatrix(); glRotatef(ThisThing.Data.Angle,0,0,1); ThingBank->RenderElem(ThisThing.ElemID,0,ThisThing.Data.Flip,Render3d); glPopMatrix(); glDisable(GL_DEPTH_TEST); glTranslatef(0,0,-ScrOfs.z); if (Selected) glColor4f(1,1,0,0.8f); else glColor4f(1,1,0,0.5f); if (DrawPoints) Core->RenderNumber(i); } else { if (Selected) glColor4f(1,1,1,1); // Set default Color else glColor4f(1,1,1,0.5); if (DrawPoints) Core->RenderNumber(i); } glPopMatrix(); } glPopMatrix(); } /*****************************************************************************/ /*** Gui *********************************************************************/ /*****************************************************************************/ void CLayerThing::GUIInit(CCore *Core) { } /*****************************************************************************/ void CLayerThing::GUIKill(CCore *Core) { } /*****************************************************************************/ void CLayerThing::GUIUpdate(CCore *Core) { } /*****************************************************************************/ void CLayerThing::GUIChanged(CCore *Core) { } /*****************************************************************************/ void CLayerThing::GUIThingUpdateList(CComboBox &List,bool OnlySel) { int i,ListSize; if (!OnlySel) { // Setup ThingList ListSize=ThingList.size(); List.ResetContent(); for (i=0; i<ListSize; i++) { List.AddString(ThingList[i].Name); } } List.SetCurSel(CurrentThing); } /*****************************************************************************/ void CLayerThing::GUIThingPointUpdateList(CListBox &List,bool OnlySel) { int i,ListSize; if (!OnlySel) { // Setup ThingPointList List.ResetContent(); if (CurrentThing==-1) return; sLayerThing &ThisThing=ThingList[CurrentThing]; ListSize=ThisThing.XY.size(); for (i=0; i<ListSize; i++) { CPoint &ThisPoint=ThisThing.XY[i]; CString Str; Str.Format("%i: %i, %i",i,ThisPoint.x,ThisPoint.y); List.AddString(Str); } } List.SetCurSel(CurrentThingPoint); } /*****************************************************************************/ /*** Functions ***************************************************************/ /*****************************************************************************/ bool CLayerThing::LButtonControl(CCore *Core,UINT nFlags, CPoint &CursorPos,bool DownFlag) { bool Ret=false; if (!DownFlag) return(false); switch(Mode) { case MouseModeNormal: SelectThing(CursorPos); break; case MouseModeNew: GUIChanged(Core); AddThing(CursorPos); break; case MouseModePoints: AddThingPoint(CursorPos); break; default: break; } return(true); } /*****************************************************************************/ bool CLayerThing::RButtonControl(CCore *Core,UINT nFlags, CPoint &CursorPos,bool DownFlag) { Cancel(); return(true); } /*****************************************************************************/ bool CLayerThing::MouseMove(CCore *Core,UINT nFlags, CPoint &CursorPos) { bool Ret=false; if (CurrentThing!=-1) { if (nFlags & MK_LBUTTON) // Drag { UpdatePos(CursorPos,CurrentThing,CurrentThingPoint,(nFlags & MK_CONTROL)!=0); Ret=true; } else if (nFlags & MK_RBUTTON) // Cancel { Cancel(); Ret=true; } } return(Ret); } /*****************************************************************************/ void CLayerThing::Cancel() { switch(Mode) { case MouseModeNormal: CurrentThing=-1; case MouseModeNew: case MouseModePoints: Mode=MouseModeNormal; CurrentThingPoint=0; GUIThingDefClear(); GUIThingUpdate(); GUIThingPointUpdate(); break; default: break; } } /*****************************************************************************/ bool CLayerThing::Command(int CmdMsg,CCore *Core,int Param0,int Param1) { bool Ret=false; switch(CmdMsg) { case CmdMsg_MirrorX: if (CanMirror()) if (CurrentThing!=-1) { ThingList[CurrentThing].Data.Flip^=PC_TILE_FLAG_MIRROR_X; } break; case CmdMsg_MirrorY: if (CanMirror()) if (CurrentThing!=-1) { ThingList[CurrentThing].Data.Flip^=PC_TILE_FLAG_MIRROR_Y; } break; case CmdMsg_Rotate: if (CanRotate()) if (CurrentThing!=-1) { ThingList[CurrentThing].Data.Angle+=90; if (ThingList[CurrentThing].Data.Angle>359) { ThingList[CurrentThing].Data.Angle=0; } } break; case CmdMsg_ThingListDelete: DeleteThing(); break; case CmdMsg_ThingListGoto: GotoThing(Core); break; case CmdMsg_ThingListSelect: CurrentDefThing=Param0; SetCursor(DefList[CurrentDefThing].Name); Mode=MouseModeNew; break; case CmdMsg_ThingLevelSelect: SelectThing(Param0); break; case CmdMsg_ThingPosSelect: CurrentThingPoint=Param0; GUIThingPointUpdate(); break; case CmdMsg_ThingPosUp: MovePoint(-1); break; case CmdMsg_ThingPosDown: MovePoint(+1); break; case CmdMsg_ThingPosDelete: DeletePoint(); break; default: break; } return(Ret); } /*****************************************************************************/ int CLayerThing::FindDefThing(const char *Name) { int i,ListSize=DefList.size(); for (i=0; i<ListSize; i++) { if (DefList[i]==Name) return(i); } return(-1); } /*****************************************************************************/ void CLayerThing::SetCursor(const char *Name) { int Idx=FindDefThing(Name); if (Idx==-1) return; Cursor=DefList[Idx]; } /*****************************************************************************/ void CLayerThing::RenderCursor(CCore *Core,Vector3 &CamPos,bool Is3d) { Vector3 ThisCam=Core->OffsetCam(CamPos,GetScaleFactor()); CPoint &CursPos=Core->GetCursorPos(); Cursor.XY[0]=CursPos; if (CursPos.x<0 || CursPos.y<0) return; if (Mode!=MouseModeNew) return; if (Cursor.ElemID==-1) return; RenderThing(Core,ThisCam,Cursor,Is3d,true); } /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ int CLayerThing::CheckThing(CPoint &Pos) { CList<int> List; int Idx=-1,i,ListSize=ThingList.size(); int StartIdx=0; // Build List Of XY Matches for (i=0; i<ListSize; i++) { sLayerThing &ThisThing=ThingList[i]; if (ThisThing.XY[0]==Pos) { if (i==CurrentThing) StartIdx=List.size(); List.push_back(i); } } ListSize=List.size(); if (ListSize) { StartIdx=(StartIdx+1)%ListSize; Idx=List[StartIdx]; } return(Idx); } /*****************************************************************************/ void CLayerThing::AddThing(CPoint &Pos) { if (Pos.x==-1 || Pos.y==-1) return; // Off Map? CurrentThing=SelectThing(Pos); if (CurrentThing!=-1) return; CurrentThing=ThingList.size(); ThingList.resize(CurrentThing+1); sLayerThing &ThisThing=ThingList[CurrentThing]; ThisThing=Cursor; SetThingParams(ThisThing); SelectThing(CurrentThing); GUIThingDefClear(); } /*****************************************************************************/ int CLayerThing::SelectThing(CPoint &Pos) { if (Pos.x==-1 || Pos.y==-1) return(-1); // Off Map? SelectThing(CheckThing(Pos)); return(CurrentThing); } /*****************************************************************************/ int CLayerThing::SelectThing(int Idx) { CurrentThing=Idx; CurrentThingPoint=0; if (CurrentThing!=-1) { Mode=MouseModePoints; GUIThingUpdate(); GUIThingPointUpdate(); } return(CurrentThing); } /*****************************************************************************/ void CLayerThing::DeleteThing() { if (!ThingList.size()) return; ThingList.erase(CurrentThing); CurrentThing--; GUIThingUpdate(); } /*****************************************************************************/ void CLayerThing::GotoThing(CCore *Core) { if (CurrentThing==-1) return; sLayerThing &ThisThing=ThingList[CurrentThing]; Core->SetCamPos(ThisThing.XY[0]); } /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ int CLayerThing::CheckThingPoint(CPoint &Pos) { CList<int> List; sLayerThing &ThisThing=ThingList[CurrentThing]; int Idx=-1,i,ListSize=ThisThing.XY.size(); int StartIdx=0; // Build List Of XY Matches for (i=0; i<ListSize; i++) { if (ThisThing.XY[i]==Pos) { if (i==CurrentThing) StartIdx=List.size(); List.push_back(i); } } ListSize=List.size(); if (ListSize) { StartIdx=(StartIdx+1)%ListSize; Idx=List[StartIdx]; } return(Idx); } /*****************************************************************************/ void CLayerThing::AddThingPoint(CPoint &Pos) { TRACE1("ADDTHINGPOINT %i\n",CurrentThingPoint); if (Pos.x==-1 || Pos.y==-1) return; // Off Map? CurrentThingPoint=SelectThingPoint(Pos); if (CurrentThingPoint!=-1) { GUIThingPointUpdate(true); return; } sLayerThing &ThisThing=ThingList[CurrentThing]; int PntCount=ThisThing.XY.size(); if (PntCount<ThisThing.Data.WaypointCount+1) { CurrentThingPoint=ThisThing.XY.size(); ThisThing.XY.resize(CurrentThingPoint+1); ThisThing.XY[CurrentThingPoint]=Pos; TRACE0("Add Point\n"); GUIThingPointUpdate(); } } /*****************************************************************************/ int CLayerThing::SelectThingPoint(CPoint &Pos) { if (Pos.x==-1 || Pos.y==-1) return(-1); // Off Map? CurrentThingPoint=CheckThingPoint(Pos); return(CurrentThingPoint); } /*****************************************************************************/ void CLayerThing::UpdatePos(CPoint &Pos,int Thing,int PosIdx,bool Recurs) { if (Pos.x==-1 || Pos.y==-1) return; // Off Map? sLayerThing &ThisThing=ThingList[Thing]; CPoint dPos=Pos-ThisThing.XY[PosIdx]; int StartIdx=PosIdx,EndIdx=ThisThing.XY.size(); if (!dPos.x && !dPos.y) return; if (!Recurs) { StartIdx=PosIdx; EndIdx=StartIdx+1; } for (int i=StartIdx; i<EndIdx; i++) { ThisThing.XY[i]+=dPos; } GUIThingPointUpdate(); } /*****************************************************************************/ void CLayerThing::MovePoint(int Dir) { if (CurrentThing==-1) return; int NewPos=CurrentThingPoint+Dir; sLayerThing &ThisThing=ThingList[CurrentThing]; if (NewPos<0 || NewPos>=ThisThing.XY.size()) return; CPoint Tmp=ThisThing.XY[CurrentThingPoint]; ThisThing.XY[CurrentThingPoint]=ThisThing.XY[NewPos]; ThisThing.XY[NewPos]=Tmp; CurrentThingPoint=NewPos; GUIThingPointUpdate(); } /*****************************************************************************/ void CLayerThing::DeletePoint() { if (!CurrentThingPoint) return; if (CurrentThing==-1) return; sLayerThing &ThisThing=ThingList[CurrentThing]; ThisThing.XY.erase(CurrentThingPoint); CurrentThingPoint--; if (CurrentThingPoint<0) CurrentThingPoint=0; GUIThingPointUpdate(); } /*****************************************************************************/ int CLayerThing::GetWidth() { return(theApp.GetCurrent()->GetMapWidth()); } /*****************************************************************************/ int CLayerThing::GetHeight() { return(theApp.GetCurrent()->GetMapHeight()); } /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ void CLayerThing::Export(CCore *Core,CExport &Exp) { int i,ListSize=ThingList.size(); Exp.ExportLayerHeader(LayerDef); Exp.Write(&ListSize,sizeof(int)); for (i=0;i<ListSize; i++) { ExportThing(Core,Exp,ThingList[i]); } ExportThingNames(Exp); } /*****************************************************************************/ void CLayerThing::ExportThing(CCore *Core,CExport &Exp,sLayerThing &ThisThing) { int i,ListSize=ThisThing.XY.size(); sLayerThingData OutThing=ThisThing.Data; OutThing.WaypointCount=ListSize; ExportThingData(Core,Exp,ThisThing,OutThing); Exp.Write(&OutThing,sizeof(sLayerThingData)); // Point List for (i=0 ;i<ListSize; i++) { Exp.Write(&ThisThing.XY[i],sizeof(CPoint)); } } /*****************************************************************************/ void CLayerThing::ExportThingNames(CExport &Exp) { int i,ListSize=ThingList.size(); for (i=0; i<ListSize; i++) { char Txt[256]; sprintf(Txt,ThingList[i].Name); Exp.Write(Txt,strlen(Txt)+1); } }