Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
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.
2026-06-24 21:28:16 -05:00

812 lines
15 KiB
C++

// EdGUIObject.cpp: implementation of the EdGUIObject class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MW4GameEd2.h"
#include "EdGUIObject.h"
#include "ObjPanelDlg.h"
#include "DrawInfo.h"
#include "GuiObjPanel.h"
#include "TNPanel.h"
#include "GuiObjectList.h"
#include "ObjManListCtrl.h"
#include "UndoManager.h"
#include "NameManager.h"
#include "GameInterface.h"
#include "ObjProps.h"
#include "DrawInfo.h"
void BaseEdObject::RotateBy(UnitQuaternion &rot)
{
UnitQuaternion new_mat;
new_mat.Multiply(rot,RotQuat);
SetRot(new_mat);
}
void BaseEdObject::RotateAround(Point3D &pnt,UnitQuaternion &vct)
{
LinearMatrix4D m1,m2;
m1.Multiply(GetMat(),LinearMatrix4D(Point3D(-pnt.x,-pnt.y,-pnt.z)));
m2.Multiply(m1,LinearMatrix4D(vct));
m1.Multiply(m2,LinearMatrix4D(pnt));
SetMat(m1);
}
LinearMatrix4D BaseEdObject::GetMat()
{
LinearMatrix4D mat(RotQuat);
mat.BuildTranslation(Pos);
return mat;
}
void BaseEdObject::SetMat(const LinearMatrix4D &mat)
{
RotQuat=mat;
Pos=mat;
UpdateMat();
}
void BaseEdObject::Copy( BaseEdObject &obj)
{
RotQuat=obj.RotQuat;
Pos=obj.Pos;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
EdGUIObject::EdGUIObject(CString name,Point3D l)
{
LineCount=0;
LineList=NULL;
HoverElevation=0.0f;
SetPos(l);
ScreenDiv=100;
RadiusSqu=0.0f;
Selected=false;
Visual=true;
Hidden=false;
InMap=false;
Frozen=false;
DrawPen=DrawInfo::HelperPen;
SelPen=DrawInfo::SelectPen;
Parent=NULL;
ReferenceCount=0;
// TestData
LineCount=0;
LineList=NULL;
SetName(name);
}
void EdGUIObject::SetPen(DrawInfo &dinf)
{
if(IsSelected())
dinf.SetPen(SelPen);
else
dinf.SetPen(DrawPen);
}
void EdGUIObject::BuildRadius()
{
if(!IsVisual()) return;
int cl;
Scalar gdist=0,dist=0;
Point3D p1,p2,loc;
loc=GetPos();
for(cl=0;cl<GetLineCount();cl++)
{
GetLine(0,&p1,&p2);
dist=(p1.x-loc.x)*(p1.x-loc.x)+(p1.z-loc.z)*(p1.z-loc.z);
gdist=dist>gdist?dist:gdist;
dist=(p2.x-loc.x)*(p2.x-loc.x)+(p2.z-loc.z)*(p2.z-loc.z);
gdist=dist>gdist?dist:gdist;
}
RadiusSqu=gdist;
}
bool EdGUIObject::InRadius( Point3D &pnt)
{
if(IsHidden()) return false;
Point3D loc=GetPos();
Scalar dist=(pnt.x-loc.x)*(pnt.x-loc.x)+(pnt.z-loc.z)*(pnt.z-loc.z);
return dist<=RadiusSqu;
}
EdGUIObject::~EdGUIObject()
{
// Verify(ReferenceCount==0);
NameManager::Instance->RemoveString(Name);
if(LineList)
delete LineList;
}
void EdGUIObject::GetLine(int idx,Point3D *start,Point3D *end)
{
Verify(idx<LineCount);
LinearMatrix4D mat=GetMat();
*start=LineList[idx].Begin;
*start*=mat;
start->y=0.0f;
*end=LineList[idx].End;
*end*=mat;
end->y=0.0f;
}
Scalar EdGUIObject::GetRadius()
{
return (Scalar)sqrt(RadiusSqu);
}
bool EdGUIObject::InsideBox( Point3D &tl, Point3D &br)
{
if(IsHidden()) return false;
Scalar rad=GetRadius();
Point3D loc=GetPos();
if(tl.x<br.x && tl.z<br.z)
{
return (
tl.x<=(loc.x-rad) && tl.z<=(loc.z-rad) &&
br.x>=(loc.x+rad) && br.z>=(loc.z+rad)
);
}
else
{
return (
br.x<=(loc.x-rad) && br.z<=(loc.z-rad) &&
tl.x>=(loc.x+rad) && tl.z>=(loc.z+rad)
);
}
}
bool EdGUIObject::IntersectsBox( Point3D &tl, Point3D &br)
{
if(IsHidden()) return false;
Scalar rad=GetRadius();
Point3D loc=GetPos();
if(tl.x<br.x && tl.z<br.z)
{
return !( (loc.z+rad)<tl.z || (loc.z-rad)>br.z || (loc.x+rad)<tl.x || (loc.x-rad)>br.x) ;
}
else
{
return !( (loc.z+rad)<br.z || (loc.z-rad)>tl.z || (loc.x+rad)<br.x || (loc.x-rad)>tl.x) ;
}
}
bool EdGUIObject::InDisplayRegion(DrawInfo &dinf)
{
Point3D tl,br;
dinf.vinf.GetViewLimits(&tl,&br);
return IntersectsBox(tl,br);
}
EdGUIObject *EdGUIObject::Clone()
{
EdGUIObject *obj=new EdGUIObject;
obj->Copy(*this);
return obj;
}
void EdGUIObject::Copy( EdGUIObject &obj)
{
BaseEdObject::Copy(obj);
LineCount=obj.LineCount;
Selected=obj.Selected;
RadiusSqu=obj.RadiusSqu;
SetName(obj.Name);
if(LineList) {delete LineList; LineList=NULL;}
if(LineCount>0)
LineList=new GUILine[LineCount];
for(int i=0;i<LineCount;i++) LineList[i]=obj.LineList[i];
Parent=NULL;
HoverElevation=obj.HoverElevation;
SnapToGround=obj.SnapToGround;
Modified=true;
Visual=obj.Visual;
Hidden=false;
InMap=false;
DrawPen=obj.DrawPen;
SelPen=obj.SelPen;
ScreenDiv=obj.ScreenDiv;
ReferenceCount=0;
}
void EdGUIObject::Draw(DrawInfo &dinf)
{
if(IsHidden() || !InDisplayRegion(dinf)) return;
SetPen(dinf);
int i;
Point3D w_start,w_end;
for(i=0;i<GetLineCount();i++)
{
GetLine(i,&w_start,&w_end);
dinf.GetDC()->MoveTo(dinf.vinf.DataToScreen(w_start));
dinf.GetDC()->LineTo(dinf.vinf.DataToScreen(w_end));
}
}
void EdGUIObject::DrawTag(DrawInfo &dinf, unsigned long tag_flags)
{
if(IsHidden() || !InDisplayRegion(dinf)) return;
SetPen(dinf);
CPoint sloc;
TEXTMETRIC tm;
dinf.GetDC()->GetTextMetrics(&tm);
CSize tsize=dinf.GetDC()->GetTextExtent(GetName());
bool xrev=false;;
sloc=dinf.vinf.DataToScreen(GetPos());
CRect textrect;
dinf.GetDC()->MoveTo(sloc);
sloc.x+=dinf.vinf.GetClientSize().cx/20;
if((sloc.x+tsize.cx)>dinf.vinf.GetClientSize().cx)
{
sloc.x-=dinf.vinf.GetClientSize().cx/10;
xrev=true;
}
sloc.y-=dinf.vinf.GetClientSize().cy/20;
if(sloc.y<0) sloc.y+=dinf.vinf.GetClientSize().cy/10;
dinf.GetDC()->LineTo(sloc);
if(xrev)
sloc.x-=dinf.vinf.GetClientSize().cx/40;
else
sloc.x+=dinf.vinf.GetClientSize().cx/40;
dinf.GetDC()->LineTo(sloc);
if(xrev)
sloc.x-=tsize.cx;
sloc.y-=tm.tmHeight/2;
textrect.left=sloc.x;
textrect.top=sloc.y;
textrect.right=textrect.left+200;
textrect.bottom=textrect.top+tm.tmHeight*5;
// dinf.GetDC()->DrawText(gobj->GetName(),&textrect,DT_LEFT);
CString org_tag(GetTag(tag_flags));
int y=sloc.y;
int lastloc=0,nlloc=org_tag.Find('\n',lastloc);
while (nlloc > 0)
{
dinf.GetDC()->ExtTextOut(sloc.x,y,NULL,NULL,org_tag.Mid(lastloc,nlloc-lastloc),NULL);
lastloc=nlloc+1;
y += 16;
nlloc=org_tag.Find('\n',lastloc);
}
}
int EdGUIObject::DeSelect(Point3D &pnt)
{
if(IsHidden() || IsMultiZone() ) return 0;
if(InRadius(pnt)) DeSelect();
return IsSelected()?1:0;
}
int EdGUIObject::SelectionDepth(Point3D &pnt)
{
if(IsHidden()) return 0;
return (InRadius(pnt) && IsSelected())?1:0;
}
int EdGUIObject::ObjectDepth(Point3D &pnt)
{
if(IsHidden()) return 0;
return InRadius(pnt)?1:0;
}
int EdGUIObject::Select(Point3D &pnt)
{
if(IsHidden()) return 0;
if(InRadius(pnt))
{
Select();
return IsSelected()?1:0;
}
else
return 0;
}
int EdGUIObject::ToggleSelect(Point3D &pnt)
{
if(IsHidden()) return 0;
if(InRadius(pnt)) ToggleSelect();
return IsSelected()?1:0;
}
int EdGUIObject::Select(Point3D &topleft,Point3D &bottomright)
{
if(IsHidden()) return 0;
if(InsideBox(topleft,bottomright)) Select();
return IsSelected()?1:0;
}
int EdGUIObject::AddToList(CObjManListCtrl *list,unsigned long tag_flags)
{
if(IsHidden()) return -1;
LVITEM lvitm;
int ret;
ZeroMemory(&lvitm,sizeof(lvitm));
lvitm.mask=LVIF_IMAGE|LVIF_PARAM|LVIF_TEXT;
lvitm.iItem=list->GetItemCount();
lvitm.iSubItem=0;
lvitm.pszText=GetName().GetBuffer(0);
lvitm.iImage=GetUnSelIcon();
lvitm.lParam=(DWORD)this;
ret=list->InsertItem(&lvitm);
ZeroMemory(&lvitm,sizeof(lvitm));
lvitm.mask=LVIF_TEXT;
lvitm.iItem=ret;
CString str;
if(tag_flags&TAG_TYPE)
{
lvitm.iSubItem=list->GetColWithID(TAGI_TYPE);
str=GetTypeName();
lvitm.pszText=str.GetBuffer(0);
list->SetItem(&lvitm);
}
if(tag_flags&TAG_HOVER_ELEVATION)
{
lvitm.iSubItem=list->GetColWithID(TAGI_HOVER_ELEVATION);
str.Format("%0.2fm",GetHoverElevation());
lvitm.pszText=str.GetBuffer(0);
list->SetItem(&lvitm);
}
if(tag_flags&TAG_MODIFIED)
{
lvitm.iSubItem=list->GetColWithID(TAGI_MODIFIED);
str.Format("%s",IsModified()?"Yes":"No");
lvitm.pszText=str.GetBuffer(0);
list->SetItem(&lvitm);
}
list->SetItemState(ret,IsSelected()?LVIS_SELECTED:0,LVIS_SELECTED);
return ret;
}
void EdGUIObject::DrawSelectedObjects(DrawInfo &dinf,bool drawTags, unsigned long tag_flags)
{
if(IsHidden()) return ;
if(IsSelected())
{
Draw(dinf);
if(drawTags) DrawTag(dinf,tag_flags);
}
}
void EdGUIObject::DrawUnSelectedObjects(DrawInfo &dinf,bool drawTags, unsigned long tag_flags)
{
if(IsHidden()) return ;
if(!IsSelected())
{
Draw(dinf);
if(drawTags) DrawTag(dinf,tag_flags);
}
}
void EdGUIObject::OffsetSelection(Point3D &vct)
{
if(IsHidden() || !IsSelected()) return;
OffsetBy(vct);
}
void EdGUIObject::OffsetBy( Point3D &pnt)
{
if(!IsHidden())
{
if(GetSnapToGround()) HoverElevation+=pnt.y;
BaseEdObject::OffsetBy(pnt);
}
}
void EdGUIObject::RotateSelection(UnitQuaternion &vct)
{
if(IsHidden() || !IsSelected()) return;
RotateBy(vct);
}
bool EdGUIObject::GetSelectionExtents(Point3D *tl,Point3D *br)
{
if(IsSelected())
{
GetExtents(tl,br);
return true;
}
else
return false;
}
void EdGUIObject::GetExtents(Point3D *tl,Point3D *br)
{
Scalar rad=GetRadius();
*br=*tl=GetPos();
tl->x-=rad;
tl->y-=rad;
tl->z-=rad;
br->x+=rad;
br->y+=rad;
br->z+=rad;
}
void EdGUIObject::RotateSelectionAround(Point3D &pnt,UnitQuaternion &vct)
{
if(IsSelected()) RotateAround(pnt,vct);
}
int EdGUIObject::GetScreenRadius(ViewWindowInfo &vinf)
{
if(IsVisual())
{
Point3D pnt(GetRadius(),0.0f,0.0f);
CPoint spnt=vinf.DataToScreen(pnt);
return spnt.x;
}
else
{
CSize csz;
int size,rad;
csz=vinf.GetClientSize();
size=csz.cx>csz.cy?csz.cx:csz.cy;
rad=size/ScreenDiv;
// Calulate Object Radius Based on how it was drawn;
float oval;
CPoint spnt;
Point3D gpnt;
spnt.x=spnt.y=0;
gpnt=vinf.ScreenToData(spnt);
oval=gpnt.x;
spnt.x=rad;
gpnt=vinf.ScreenToData(spnt);
RadiusSqu=(float)fabs(gpnt.x-oval);
RadiusSqu*=RadiusSqu;
return rad;
}
}
bool EdGUIObject::SelectNext(Point3D &pnt,bool found)
{
if(!InRadius(pnt)) return false;
if(found)
{
if(!IsSelected()) {Select(); return true;}
}
else
if(IsSelected()) {DeSelect(); return true;}
return false;
}
EdGUIObject *EdGUIObject::SelectClosestInternal(Point3D &pnt,Scalar *crat)
{
if(IsHidden() || IsSelected()) return false;
Point3D loc=GetPos();
Scalar dist=(pnt.x-loc.x)*(pnt.x-loc.x)+(pnt.z-loc.z)*(pnt.z-loc.z);
if(dist<=RadiusSqu)
{ // If inside
Scalar mycrat=1.0f-(dist/RadiusSqu);
if(mycrat>*crat)
{ // Closer than the Other
*crat=mycrat;
return this;
}
}
return NULL;
}
bool EdGUIObject::SelectClosest(Point3D &pnt)
{
Scalar crat=-1.0f;
EdGUIObject *gobj=SelectClosestInternal(pnt,&crat);
if(gobj) {gobj->Select(); return true;}
return false;
}
void EdGUIObject::UpdateMat()
{
if(SnapToGround)
{
Point3D trans=GetPos();
trans.y=ComputeTerrainElevation(trans.x,trans.z)+HoverElevation;
SetPosNoUpdate(trans);
}
BaseEdObject::UpdateMat();
Modify();
}
void EdGUIObject::SaveTextInfo(NotationFile *not_file)
{
if((HoverElevation==0.0f) && GetSnapToGround() && ((GUIObjectList *)GetMyMission()==Parent)) return ;
Page *page=not_file->SetPage((char *)(LPCSTR)GetName());
page->SetEntry("HoverElevation",HoverElevation);
page->SetEntry("SnapToGround",GetSnapToGround());
page->SetEntry("Type","Helper");
}
void EdGUIObject::AddPanel(CObjPanelDlg *pnl,UndoCommand **cmd)
{
pnl->AddPanel(new CTNPanel(this,cmd,pnl));
pnl->AddPanel(new GUIObjPanel(this,cmd,pnl));
}
void EdGUIObject::SetInfo(Page *page)
{
page->GetEntry("HoverElevation",&HoverElevation);
page->GetEntry("SnapToGround",&SnapToGround);
}
CString EdGUIObject::GetTag(unsigned long tag_flags)
{
CString rv,ns;
if ((tag_flags & TAG_NAME) > 0)
{
rv += GetName();
rv += "\n";
}
if ((tag_flags & TAG_HOVER_ELEVATION) > 0)
{
ns.Format("Hover: %.2f\n",HoverElevation);
rv+=ns;
}
if ((tag_flags & TAG_MODIFIED) > 0)
{
if (IsModified() == true)
{
rv += "**MODIFIED**\n";
}
else
{
rv += "Not Modified\n";
}
}
return rv;
}
void EdGUIObject::MoveToGroup(EdGUIObject *gobj)
{
Verify(Parent!=NULL);
GUIObjectList *group=Parent->PlaceInGroup(this);
if(group!=NULL)
group->MoveToGroup(gobj);
}
void EdGUIObject::CopySelectionToList(GUIObjectList *list)
{
if(IsSelected())
{
EdGUIObject *gobj=Clone();
if(gobj)
{
list->AddObject(gobj);
gobj->RemoveFromMap();
}
}
}
void EdGUIObject::SetName( CString &name)
{
CString tnme=name;
for(int i=0;i<tnme.GetLength();i++)
if(!isdigit(tnme[i]) && !isalpha(tnme[i]) && tnme[i]==' ' && tnme[i]=='_')
{
tnme.SetAt(i,'_');
}
if(tnme.Compare(Name))
{
if(Name!="" && !NameManager::Instance->IsUnique(Name)) NameManager::Instance->RemoveString(Name);
Name=NameManager::Instance->MakeUnique(tnme);
Modify();
}
}
ObjectManager *EdGUIObject::GetMyMission()
{
if(Parent) return Parent->GetMyMission();
return NULL;
}
void EdGUIObject::SnapObjectToGround(bool overrideflag)
{
if(SnapToGround || overrideflag)
{
bool oldsnap=SnapToGround;
SnapToGround=true;
UpdateMat();
SnapToGround=oldsnap;
}
}
void EdGUIObject::GetMultiProps(CObjProps *props)
{
props->SetModTagFrom(this);
}
void EdGUIObject::SetMultiProps(CObjProps *props,UndoCommand **cmd)
{
props->SetData(this,cmd);
}
void EdGUIObject::SavePos(UndoCommand **cmd)
{
MoveCommand *mcom=new MoveCommand(this);
if(*cmd==NULL) *cmd=mcom; else (*cmd)->Attach(mcom);
}
void EdGUIObject::SaveRot(UndoCommand **cmd)
{
RotateCommand *mcom=new RotateCommand(this);
if(*cmd==NULL) *cmd=mcom; else (*cmd)->Attach(mcom);
}
void EdGUIObject::SaveGroup(UndoCommand **cmd)
{
GroupCommand *mcom=new GroupCommand(this);
if(*cmd==NULL) *cmd=mcom; else (*cmd)->Attach(mcom);
}
void EdGUIObject::SavePosIfSelected(UndoCommand **cmd)
{
if(IsSelected() && !IsHidden())
{
SavePos(cmd);
}
}
void EdGUIObject::SaveRotIfSelected(UndoCommand **cmd)
{
if(IsSelected() && !IsHidden())
{
SaveRot(cmd);
}
}
bool EdGUIObject::UnGroupSelected(UndoCommand **cmd)
{
if(IsSelected())
{
Verify(Parent!=NULL);
SaveGroup(cmd);
GUIObjectList *par=GetParent();
GUIObjectList *grand_par=par->GetParent();
if(grand_par!=NULL)
{
par->RemoveObject(this);
grand_par->AddObject(this);
}
return true;
}
return false;
}
void EdGUIObject::SetSnapToGround(bool snap,bool preservepos)
{
if(preservepos)
{
Point3D pos=GetPos();
HoverElevation=pos.y;
}
SnapToGround=snap;
UpdateMat();
}
EdGUIObject *EdGUIObject::GetObjectByName(CString name)
{
if(!name.CompareNoCase(GetName())) return this;
return NULL;
}
// Helper Functions
int _cdecl CompareGUIObjs(const void *elem1, const void *elem2)
{
EdGUIObject *obj1,*obj2;
obj1=*((EdGUIObject **)elem1);
obj2=*((EdGUIObject **)elem2);
return obj1->GetName().CompareNoCase(obj2->GetName());
}