Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
583 lines
10 KiB
C++
583 lines
10 KiB
C++
// GUIPath.cpp: implementation of the GUIPath class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "MW4GameEd2.h"
|
|
#include "GUINode.h"
|
|
#include "DrawInfo.h"
|
|
#include "GUIPath.h"
|
|
#include "GameInterface.h"
|
|
#include <MW4\Path.hpp>
|
|
#include <Adept\Entity.hpp>
|
|
#include <Adept\EntityClassData.hpp>
|
|
#include <Adept\Resource.hpp>
|
|
#include <Adept\Map.hpp>
|
|
|
|
using namespace Adept;
|
|
using namespace MechWarrior4;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Path
|
|
|
|
GUIPath::GUIPath(CString &name):GUIObjectList(name)
|
|
{
|
|
MyPath=NULL;
|
|
SetName(name);
|
|
Build();
|
|
|
|
AddToMap();
|
|
}
|
|
|
|
void GUIPath::Build()
|
|
{
|
|
Adept::Resource res((LPCSTR)"Misc\\Path\\Path.Instance");
|
|
res.LoadData();
|
|
Check_Object(Connection::Local);
|
|
ReplicatorID base_id = Connection::Local->GetNextReplicatorID();
|
|
MyPath = Cast_Object(Path*,Entity::CreateEntity(&res,&base_id));
|
|
Check_Object(MyPath);
|
|
MyPath->instanceName=(LPCSTR)GetName();
|
|
|
|
}
|
|
|
|
EdGUIObject *GUIPath::Clone()
|
|
{
|
|
GUIPath *obj=new GUIPath;
|
|
obj->Copy(*this);
|
|
return obj;
|
|
}
|
|
|
|
void GUIPath::Copy(GUIPath &obj)
|
|
{
|
|
GUIObjectList::Copy(obj);
|
|
|
|
if(MyPath)
|
|
{
|
|
RemoveFromMap();
|
|
delete Cast_Object(Stuff::Plug *,MyPath);
|
|
MyPath=NULL;
|
|
}
|
|
|
|
Build();
|
|
|
|
Check_Object(MyPath);
|
|
|
|
for(int i=0;i<GetObjectCount();i++)
|
|
{
|
|
MyPath->pathPoints.push_back(GetObject(i)->GetPos());
|
|
}
|
|
|
|
Verify(MyPath->pathPoints.size()==GetObjectCount());
|
|
|
|
}
|
|
|
|
GUIPath::GUIPath():GUIObjectList("Path")
|
|
{
|
|
MyPath=NULL;
|
|
InMap=false;
|
|
}
|
|
|
|
void GUIPath::AssociateTo(MechWarrior4::Path *path)
|
|
{
|
|
MyPath=path;
|
|
Check_Object(MyPath);
|
|
|
|
CString name=(char *)MyPath->instanceName;
|
|
InMap=true;
|
|
EdGUIObject::SetName(name);
|
|
CString node_name=GetName()+"Node";
|
|
|
|
int i,size=MyPath->pathPoints.size();
|
|
|
|
for(i=0;i<size;i++)
|
|
{
|
|
AddObject(new GUINode(node_name,MyPath->pathPoints[i]));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void GUIPath::SetName(CString &name)
|
|
{
|
|
EdGUIObject::SetName(name);
|
|
if(InMap && MyPath!=NULL)
|
|
{
|
|
Check_Object(MyPath);
|
|
RemoveEntityFromNameTable(MyPath);
|
|
MyPath->instanceName=(LPCSTR)GetName();
|
|
AddEntityToNameTable(MyPath);
|
|
}
|
|
|
|
for(int i=0;i<GetObjectCount();i++) GetObject(i)->SetName(GetName()+"Node");
|
|
}
|
|
|
|
|
|
EdGUIObject *GUIPath::AddNodeAtEnd(Point3D &pnt)
|
|
{
|
|
CString node_name=GetName()+"Node";
|
|
GUINode *ret;
|
|
AddObject(ret=new GUINode(node_name,pnt));
|
|
if(MyPath!=NULL)
|
|
{
|
|
Check_Object(MyPath);
|
|
MyPath->pathPoints.push_back(pnt);
|
|
Verify(MyPath->pathPoints.size()==GetObjectCount());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void GUIPath::Draw(DrawInfo &dinf)
|
|
{
|
|
if(IsHidden()) return;
|
|
SetPen(dinf);
|
|
|
|
if(GetObjectCount()>0)
|
|
{
|
|
dinf.GetDC()->MoveTo(dinf.vinf.DataToScreen(GetObject(0)->GetPos()));
|
|
for(int i=1;i<GetObjectCount();i++)
|
|
dinf.GetDC()->LineTo(dinf.vinf.DataToScreen(GetObject(i)->GetPos()));
|
|
}
|
|
|
|
GUIObjectList::Draw(dinf);
|
|
|
|
}
|
|
|
|
bool GUIPath::DeleteSelected(UndoCommand **delcom)
|
|
{
|
|
bool ret=GUIObjectList::DeleteSelected(delcom);
|
|
SyncData();
|
|
return ret;
|
|
}
|
|
|
|
EdGUIObject *GUIPath::InsertNodeAt(int idx,Point3D &pnt)
|
|
{
|
|
if(IsHidden()) return NULL;
|
|
GUINode *ret;
|
|
InsertObjectAt(idx,ret=new GUINode(GetName()+"Node",pnt));
|
|
return ret;
|
|
}
|
|
|
|
void GUIPath::InsertObjectAt(int idx,EdGUIObject *gobj)
|
|
{
|
|
GUIObjectList::InsertObjectAt(idx,gobj);
|
|
if(MyPath!=NULL)
|
|
{
|
|
Check_Object(MyPath);
|
|
MyPath->pathPoints.push_back(gobj->GetPos());
|
|
Verify(MyPath->pathPoints.size()==GetObjectCount());
|
|
SyncDataToNodes();
|
|
}
|
|
}
|
|
|
|
void GUIPath::SaveTextInfo(NotationFile *not_file)
|
|
{
|
|
Page *page=not_file->SetPage((char *)(LPCSTR)GetName());
|
|
page->SetEntry("Type","Path");
|
|
}
|
|
|
|
|
|
GUIPath::~GUIPath()
|
|
{
|
|
DeleteAllObjects();
|
|
|
|
if(MyPath)
|
|
{
|
|
RemoveFromMap();
|
|
delete Cast_Object(Stuff::Plug *,MyPath);
|
|
}
|
|
}
|
|
|
|
|
|
EdGUIObject *GUIPath::AddNodeIfSelected(Point3D &pnt,bool insert)
|
|
{
|
|
if(IsHidden()) return NULL;
|
|
if(!IsSelected()) return NULL;
|
|
|
|
if(GetObjectCount()<=1 || !insert)
|
|
{
|
|
return AddNodeAtEnd(pnt);
|
|
}
|
|
|
|
EdGUIObject *ret;
|
|
|
|
Point3D cp,np;
|
|
Scalar lowdist,d;
|
|
int lowpoint,i;
|
|
|
|
lowdist=(Scalar)sqrt(GetObject(0)->DistSquTo(pnt));
|
|
lowpoint=0;
|
|
|
|
|
|
np=GetObject(0)->GetPos();
|
|
|
|
for(i=1;i<GetObjectCount();i++)
|
|
{
|
|
cp=np;
|
|
np=GetObject(i)->GetPos();
|
|
d=DistToPoint(cp,np,pnt);
|
|
|
|
if(d<lowdist)
|
|
{
|
|
lowdist=d;
|
|
lowpoint=i;
|
|
}
|
|
}
|
|
|
|
d=(Scalar)sqrt(GetObject(GetObjectCount()-1)->DistSquTo(pnt));
|
|
|
|
if(d<=lowdist)
|
|
{
|
|
ret=AddNodeAtEnd(pnt);
|
|
}
|
|
else
|
|
{
|
|
ret=InsertNodeAt(lowpoint,pnt);
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
void GUIPath::SyncNodesToData()
|
|
{
|
|
Check_Object(MyPath);
|
|
int i,size=MyPath->pathPoints.size();
|
|
Verify(size==GetObjectCount());
|
|
|
|
GUINode *gobj;
|
|
for(i=0;i<size;i++)
|
|
{
|
|
gobj=(GUINode *)GetObject(i);
|
|
gobj->SetPos(MyPath->pathPoints[i]);
|
|
}
|
|
|
|
for(i=0;i<GetObjectCount();i++) GetObject(i)->SetName(GetName()+"Node");
|
|
|
|
}
|
|
|
|
void GUIPath::SyncDataToNodes()
|
|
{
|
|
Check_Object(MyPath);
|
|
int i,size=MyPath->pathPoints.size();
|
|
Verify(size==GetObjectCount());
|
|
|
|
GUINode *gobj;
|
|
for(i=0;i<size;i++)
|
|
{
|
|
gobj=(GUINode *)GetObject(i);
|
|
MyPath->pathPoints[i]=gobj->GetPos();
|
|
}
|
|
|
|
}
|
|
|
|
void GUIPath::OffsetSelection(Point3D &vct)
|
|
{
|
|
if(IsHidden()) return ;
|
|
GUIObjectList::OffsetSelection(vct);
|
|
SyncDataToNodes();
|
|
}
|
|
|
|
void GUIPath::RemoveObject(int idx)
|
|
{
|
|
GUIObjectList::RemoveObject(idx);
|
|
|
|
Check_Object(MyPath);
|
|
MyPath->ErasePoint(idx);
|
|
SyncDataToNodes();
|
|
}
|
|
|
|
void GUIPath::RemoveFromMap()
|
|
{
|
|
if(InMap)
|
|
RemoveEntityFromMap(MyPath);
|
|
GUIObjectList::RemoveFromMap();
|
|
}
|
|
|
|
void GUIPath::AddToMap()
|
|
{
|
|
if(!InMap)
|
|
AddEntityToMap(MyPath,GetMat());
|
|
GUIObjectList::AddToMap();
|
|
}
|
|
|
|
HTREEITEM GUIPath::AddToBranch(CTreeCtrl *tree,HTREEITEM itm)
|
|
{
|
|
return EdGUIObject::AddToBranch(tree,itm);
|
|
}
|
|
|
|
|
|
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Bound
|
|
|
|
GUIBound::GUIBound(CString name):GUIObjectList(name)
|
|
{
|
|
}
|
|
|
|
void GUIBound::SetBoundData(DynamicArrayOf<Stuff::Vector2DOf<Stuff::Scalar> > &BDat)
|
|
{
|
|
DeleteAllObjects();
|
|
MyBound=BDat;
|
|
|
|
int i;
|
|
Point3D pnt;
|
|
pnt.y=0.0f;
|
|
CString node_name=GetName()+"_Node";
|
|
|
|
for(i=0;i<MyBound.GetLength();i++)
|
|
{
|
|
pnt.x=MyBound[i].x;
|
|
pnt.z=MyBound[i].y;
|
|
AddObject(new GUINode(node_name,pnt));
|
|
}
|
|
}
|
|
|
|
bool GUIBound::DeleteSelected(UndoCommand **delcom)
|
|
{
|
|
if(GetObjectCount()<=3) return false;
|
|
bool ret=GUIObjectList::DeleteSelected(delcom);
|
|
SyncData();
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
void GUIBound::Draw(DrawInfo &dinf)
|
|
{
|
|
if(IsHidden()) return;
|
|
SetPen(dinf);
|
|
|
|
if(GetObjectCount()>0)
|
|
{
|
|
dinf.GetDC()->MoveTo(dinf.vinf.DataToScreen(GetObject(0)->GetPos()));
|
|
for(int i=1;i<GetObjectCount();i++)
|
|
dinf.GetDC()->LineTo(dinf.vinf.DataToScreen(GetObject(i)->GetPos()));
|
|
|
|
dinf.GetDC()->LineTo(dinf.vinf.DataToScreen(GetObject(0)->GetPos()));
|
|
}
|
|
|
|
GUIObjectList::Draw(dinf);
|
|
}
|
|
|
|
EdGUIObject *GUIBound::Clone()
|
|
{
|
|
GUIBound *obj=new GUIBound;
|
|
obj->Copy(*this);
|
|
return obj;
|
|
}
|
|
|
|
|
|
EdGUIObject *GUIBound::AddNodeIfSelected(Point3D &pnt,bool insert)
|
|
{
|
|
if(IsHidden()) return NULL;
|
|
if(!IsSelected()) return NULL;
|
|
|
|
Point3D cp,np;
|
|
Scalar lowdist,d;
|
|
int lowpoint,i;
|
|
|
|
cp=GetObject(0)->GetPos();
|
|
np=GetObject(1)->GetPos();
|
|
lowdist=DistToPoint(cp,np,pnt);
|
|
lowpoint=1;
|
|
|
|
for(i=2;i<GetObjectCount();i++)
|
|
{
|
|
cp=np;
|
|
np=GetObject(i)->GetPos();
|
|
d=DistToPoint(cp,np,pnt);
|
|
|
|
if(d<lowdist)
|
|
{
|
|
lowdist=d;
|
|
lowpoint=i;
|
|
}
|
|
}
|
|
|
|
cp=np;
|
|
np=GetObject(0)->GetPos();
|
|
d=DistToPoint(cp,np,pnt);
|
|
|
|
if(d<lowdist)
|
|
{
|
|
lowdist=d;
|
|
lowpoint=0;
|
|
}
|
|
|
|
|
|
return InsertNodeAt(lowpoint,pnt);
|
|
|
|
}
|
|
|
|
void GUIBound::RemoveObject(int idx)
|
|
{
|
|
GUIObjectList::RemoveObject(idx);
|
|
|
|
MyBound.SetLength(MyBound.GetLength()-1);
|
|
SyncDataToNodes();
|
|
}
|
|
|
|
|
|
EdGUIObject *GUIBound::InsertNodeAt(int idx,Point3D &pnt)
|
|
{
|
|
if(IsHidden()) return NULL;
|
|
GUINode *ret;
|
|
CString node_name=GetName()+"_Node";
|
|
InsertObjectAt(idx,ret=new GUINode(node_name,pnt));
|
|
return ret;
|
|
}
|
|
|
|
void GUIBound::OffsetSelection(Point3D &vct)
|
|
{
|
|
if(IsHidden()) return;
|
|
GUIObjectList::OffsetSelection(vct);
|
|
if(!IsConcave())
|
|
{
|
|
|
|
Point3D pnt2;
|
|
pnt2.x=-vct.x;
|
|
pnt2.y=-vct.y;
|
|
pnt2.z=-vct.z;
|
|
GUIObjectList::OffsetSelection(pnt2);
|
|
}
|
|
|
|
if(!IsConcave())
|
|
{
|
|
Point3D tl,br;
|
|
GetExtents(&tl,&br);
|
|
ResetTo(tl,br);
|
|
}
|
|
|
|
SyncDataToNodes();
|
|
}
|
|
|
|
bool GUIBound::IsConcave()
|
|
{
|
|
int i;
|
|
|
|
Point3D p1,p2,p3;
|
|
p1=GetObject(GetObjectCount()-1)->GetPos();
|
|
p2=GetObject(GetObjectCount()-2)->GetPos();
|
|
p2.y=p1.y=0;
|
|
|
|
Vector3D v1,v2,rvct;
|
|
int sign=-1;
|
|
|
|
for(i=0;i<GetObjectCount();i++)
|
|
{
|
|
p3=p2;
|
|
p2=p1;
|
|
p1=GetObject(i)->GetPos();
|
|
p1.y=0;
|
|
/*
|
|
p1.x/=(float)fabs(p1.x);
|
|
p2.x/=(float)fabs(p1.x);
|
|
p3.x/=(float)fabs(p1.x);
|
|
p1.y/=(float)fabs(p1.x);
|
|
p2.y/=(float)fabs(p1.x);
|
|
p3.y/=(float)fabs(p1.x);
|
|
*/
|
|
v1.Subtract(p3,p2);
|
|
v2.Subtract(p1,p2);
|
|
rvct.Cross(v1,v2);
|
|
|
|
if(rvct.y!=0.0f)
|
|
{
|
|
|
|
if(sign==-1)
|
|
{
|
|
sign=rvct.y>0?1:0;
|
|
}
|
|
|
|
if((sign==1 && rvct.y<0) || (sign==0 && rvct.y>0) )
|
|
return false;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
void GUIBound::SyncNodesToData()
|
|
{
|
|
int i,size=MyBound.GetLength();
|
|
Verify(size==GetObjectCount());
|
|
|
|
GUINode *gobj;
|
|
for(i=0;i<size;i++)
|
|
{
|
|
Point3D pnt;
|
|
pnt.y=0.0f;
|
|
pnt.x=MyBound[i].x;
|
|
pnt.z=MyBound[i].y;
|
|
gobj=(GUINode *)GetObject(i);
|
|
gobj->SetPos(pnt);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void GUIBound::SyncDataToNodes()
|
|
{
|
|
int i,size=MyBound.GetLength();
|
|
Verify(size==GetObjectCount());
|
|
|
|
Point3D pnt;
|
|
for(i=0;i<size;i++)
|
|
{
|
|
pnt=GetObject(i)->GetPos();
|
|
MyBound[i].x=pnt.x;
|
|
MyBound[i].y=pnt.z;
|
|
}
|
|
|
|
}
|
|
|
|
void GUIBound::ResetTo(Point3D tl,Point3D br)
|
|
{
|
|
MyBound.SetLength(4);
|
|
|
|
MyBound[0].x=tl.x;
|
|
MyBound[0].y=tl.z;
|
|
|
|
MyBound[3].x=br.x;
|
|
MyBound[3].y=tl.z;
|
|
|
|
MyBound[2].x=br.x;
|
|
MyBound[2].y=br.z;
|
|
|
|
MyBound[1].x=tl.x;
|
|
MyBound[1].y=br.z;
|
|
|
|
SetBoundData(MyBound);
|
|
}
|
|
|
|
|
|
void GUIBound::SaveTextInfo(NotationFile *not_file)
|
|
{
|
|
Page *page=not_file->SetPage((char *)(LPCSTR)GetName());
|
|
page->SetEntry("Type","Bound");
|
|
}
|
|
|
|
GUIBound::~GUIBound()
|
|
{
|
|
DeleteAllObjects();
|
|
}
|
|
|
|
void GUIBound::InsertObjectAt(int idx,EdGUIObject *gobj)
|
|
{
|
|
GUIObjectList::InsertObjectAt(idx,gobj);
|
|
MyBound.SetLength(MyBound.GetLength()+1);
|
|
SyncDataToNodes();
|
|
}
|
|
|
|
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>> Global Helper Functions
|
|
|
|
|