Files
firestorm/Gameleap/code/mw4/Tools/Max43DSPlugins/MaxControls/Indepos.cpp
T
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

754 lines
19 KiB
C++

/**********************************************************************
*<
FILE: indepos.cpp
DESCRIPTION: An independent X, Y, Z position controller
CREATED BY: Rolf Berteig
HISTORY: created 13 June 1995
*> Copyright (c) 1994, All Rights Reserved.
**********************************************************************/
#include "ctrl.h"
#define IPOS_CONTROL_CLASS_ID Class_ID(0x118f7e02,0xffee238a)
#define IPOS_CONTROL_CNAME GetString(IDS_RB_IPOS)
#define IPOINT3_CONTROL_CLASS_ID Class_ID(0x118f7e02,0xfeee238b)
#define IPOINT3_CONTROL_CNAME GetString(IDS_RB_IPOINT3)
#define ICOLOR_CONTROL_CLASS_ID Class_ID(0x118f7c01,0xfeee238a)
#define ICOLOR_CONTROL_CNAME GetString(IDS_RB_ICOLOR)
#define IPOS_X_REF 0
#define IPOS_Y_REF 1
#define IPOS_Z_REF 2
class IPosDlg;
static DWORD subColor[] = {PAINTCURVE_XCOLOR, PAINTCURVE_YCOLOR, PAINTCURVE_ZCOLOR};
class IndePosition : public Control {
public:
Control *posX;
Control *posY;
Control *posZ;
Point3 curval;
Interval ivalid;
static IPosDlg *dlg;
static IObjParam *ip;
static ULONG beginFlags;
static IndePosition *editControl; // The one being edited.
IndePosition(BOOL loading=FALSE);
IndePosition(const IndePosition &ctrl);
~IndePosition();
void Update(TimeValue t);
// Animatable methods
Class_ID ClassID() { return IPOS_CONTROL_CLASS_ID;}
SClass_ID SuperClassID() {return CTRL_POSITION_CLASS_ID;}
void GetClassName(TSTR& s) {s = IPOS_CONTROL_CNAME;}
void DeleteThis() {delete this;}
int IsKeyable() {return 1;}
int NumSubs() {return 3;}
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int SubNumToRefNum(int subNum) {return subNum;}
DWORD GetSubAnimCurveColor(int subNum) {return subColor[subNum];}
ParamDimension* GetParamDimension(int i) {return stdWorldDim;}
BOOL AssignController(Animatable *control,int subAnim);
void AddNewKey(TimeValue t,DWORD flags);
int NumKeys();
TimeValue GetKeyTime(int index);
void CopyKeysFromTime(TimeValue src,TimeValue dst,DWORD flags);
BOOL IsKeyAtTime(TimeValue t,DWORD flags);
BOOL GetNextKeyTime(TimeValue t,DWORD flags,TimeValue &nt);
void DeleteKeyAtTime(TimeValue t);
void BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev );
void EndEditParams( IObjParam *ip, ULONG flags,Animatable *next );
// Reference methods
int NumRefs() { return 3; };
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
RefResult NotifyRefChanged(Interval, RefTargetHandle, PartID&, RefMessage);
// Control methods
Control *GetXController() {return posX;}
Control *GetYController() {return posY;}
Control *GetZController() {return posZ;}
void Copy(Control *from);
RefTargetHandle Clone(RemapDir& remap);
BOOL IsLeaf() {return FALSE;}
void GetValue(TimeValue t, void *val, Interval &valid, GetSetMethod method);
void SetValue(TimeValue t, void *val, int commit, GetSetMethod method);
void CommitValue(TimeValue t);
void RestoreValue(TimeValue t);
};
IPosDlg *IndePosition::dlg = NULL;
IObjParam *IndePosition::ip = NULL;
ULONG IndePosition::beginFlags = 0;
IndePosition *IndePosition::editControl = NULL;
class IndePoint3 : public IndePosition {
public:
IndePoint3(BOOL loading=FALSE) : IndePosition(loading) {}
SClass_ID SuperClassID() {return CTRL_POINT3_CLASS_ID;}
Class_ID ClassID() { return IPOINT3_CONTROL_CLASS_ID;}
void GetClassName(TSTR& s) {s = IPOINT3_CONTROL_CNAME;}
void GetValue(TimeValue t, void *val, Interval &valid, GetSetMethod method);
RefTargetHandle Clone(RemapDir& remap);
};
class IndeColor : public IndePoint3 {
public:
IndeColor(BOOL loading=FALSE) : IndePoint3(loading) {}
SClass_ID SuperClassID() {return CTRL_POINT3_CLASS_ID;}
Class_ID ClassID() { return ICOLOR_CONTROL_CLASS_ID;}
void GetClassName(TSTR& s) {s = ICOLOR_CONTROL_CNAME;}
ParamDimension* GetParamDimension(int i) {return stdColor255Dim;}
RefTargetHandle Clone(RemapDir& remap);
};
class IPosClassDesc:public ClassDesc {
public:
int IsPublic() {return 1;}
void * Create(BOOL loading) {return new IndePosition(loading);}
const TCHAR * ClassName() {return IPOS_CONTROL_CNAME;}
SClass_ID SuperClassID() {return CTRL_POSITION_CLASS_ID;}
Class_ID ClassID() {return IPOS_CONTROL_CLASS_ID;}
const TCHAR* Category() {return _T("");}
};
static IPosClassDesc iposCD;
ClassDesc* GetIPosCtrlDesc() {return &iposCD;}
class IPoint3ClassDesc:public ClassDesc {
public:
int IsPublic() {return 1;}
void * Create(BOOL loading) {return new IndePoint3(loading);}
const TCHAR * ClassName() {return IPOINT3_CONTROL_CNAME;}
SClass_ID SuperClassID() {return CTRL_POINT3_CLASS_ID;}
Class_ID ClassID() {return IPOINT3_CONTROL_CLASS_ID;}
const TCHAR* Category() {return _T("");}
};
static IPoint3ClassDesc ipoint3CD;
ClassDesc* GetIPoint3CtrlDesc() {return &ipoint3CD;}
class IColorClassDesc:public ClassDesc {
public:
int IsPublic() {return 1;}
void * Create(BOOL loading) {return new IndeColor(loading);}
const TCHAR * ClassName() {return ICOLOR_CONTROL_CNAME;}
SClass_ID SuperClassID() {return CTRL_POINT3_CLASS_ID;}
Class_ID ClassID() {return ICOLOR_CONTROL_CLASS_ID;}
const TCHAR* Category() {return _T("");}
};
static IColorClassDesc icolorCD;
ClassDesc* GetIColorCtrlDesc() {return &icolorCD;}
static BOOL CALLBACK IPosParamDialogProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
static const int editButs[] = {IDC_IPOS_X,IDC_IPOS_Y,IDC_IPOS_Z};
#define EDIT_X 0
#define EDIT_Y 1
#define EDIT_Z 2
#define IPOS_BEGIN 1
#define IPOS_MIDDLE 2
#define IPOS_END 3
class IPosDlg {
public:
IndePosition *cont;
HWND hWnd;
IObjParam *ip;
ICustButton *iEdit[3];
static int cur;
IPosDlg(IndePosition *cont,IObjParam *ip);
~IPosDlg();
void Init();
void EndingEdit(IndePosition *next);
void BeginingEdit(IndePosition *cont,IObjParam *ip,IndePosition *prev);
void SetCur(int c,int code=IPOS_MIDDLE);
void WMCommand(int id, int notify, HWND hCtrl);
};
int IPosDlg::cur = EDIT_X;
IPosDlg::IPosDlg(IndePosition *cont,IObjParam *ip)
{
this->ip = ip;
this->cont = cont;
for (int i=0; i<3; i++) {
iEdit[i] = NULL;
}
TCHAR *name;
if (cont->ClassID()==IPOS_CONTROL_CLASS_ID)
name = GetString(IDS_RB_IPOSPARAMS);
else
if (cont->ClassID()==IPOINT3_CONTROL_CLASS_ID)
name = GetString(IDS_RB_IPOINT3PARAMS);
else name = GetString(IDS_RB_ICOLORPARAMS);
hWnd = ip->AddRollupPage(
hInstance,
MAKEINTRESOURCE(IDD_IPOS_PARAMS),
IPosParamDialogProc,
name,
(LPARAM)this);
ip->RegisterDlgWnd(hWnd);
SetCur(cur,IPOS_BEGIN);
UpdateWindow(hWnd);
}
IPosDlg::~IPosDlg()
{
SetCur(cur,IPOS_END);
for (int i=0; i<3; i++) {
ReleaseICustButton(iEdit[i]);
}
ip->UnRegisterDlgWnd(hWnd);
ip->DeleteRollupPage(hWnd);
hWnd = NULL;
}
void IPosDlg::EndingEdit(IndePosition *next)
{
switch (cur) {
case EDIT_X:
cont->posX->EndEditParams(ip,0,next->posX);
break;
case EDIT_Y:
cont->posY->EndEditParams(ip,0,next->posY);
break;
case EDIT_Z:
cont->posZ->EndEditParams(ip,0,next->posZ);
break;
}
cont = NULL;
ip = NULL;
}
void IPosDlg::BeginingEdit(IndePosition *cont,IObjParam *ip,IndePosition *prev)
{
this->ip = ip;
this->cont = cont;
switch (cur) {
case EDIT_X:
cont->posX->BeginEditParams(ip,BEGIN_EDIT_MOTION,prev->posX);
break;
case EDIT_Y:
cont->posY->BeginEditParams(ip,BEGIN_EDIT_MOTION,prev->posY);
break;
case EDIT_Z:
cont->posZ->BeginEditParams(ip,BEGIN_EDIT_MOTION,prev->posZ);
break;
}
UpdateWindow(hWnd);
}
void IPosDlg::Init()
{
for (int i=0; i<3; i++) {
iEdit[i] = GetICustButton(GetDlgItem(hWnd,editButs[i]));
iEdit[i]->SetType(CBT_CHECK);
}
iEdit[cur]->SetCheck(TRUE);
}
void IPosDlg::SetCur(int c,int code)
{
if (c==cur && code==IPOS_MIDDLE) return;
Control *prev = NULL, *next = NULL;
if (code!=IPOS_END) {
switch (c) {
case EDIT_X:
next = cont->posX;
break;
case EDIT_Y:
next = cont->posY;
break;
case EDIT_Z:
next = cont->posZ;
break;
}
}
if (code!=IPOS_BEGIN) {
switch (cur) {
case EDIT_X:
cont->posX->EndEditParams(ip,END_EDIT_REMOVEUI,next);
prev = cont->posX;
break;
case EDIT_Y:
cont->posY->EndEditParams(ip,END_EDIT_REMOVEUI,next);
prev = cont->posY;
break;
case EDIT_Z:
cont->posZ->EndEditParams(ip,END_EDIT_REMOVEUI,next);
prev = cont->posZ;
break;
}
}
cur = c;
if (code!=IPOS_END) {
switch (cur) {
case EDIT_X:
cont->posX->BeginEditParams(ip,BEGIN_EDIT_MOTION,prev);
break;
case EDIT_Y:
cont->posY->BeginEditParams(ip,BEGIN_EDIT_MOTION,prev);
break;
case EDIT_Z:
cont->posZ->BeginEditParams(ip,BEGIN_EDIT_MOTION,prev);
break;
}
}
}
void IPosDlg::WMCommand(int id, int notify, HWND hCtrl)
{
switch (id) {
case IDC_IPOS_X:
SetCur(0);
iEdit[0]->SetCheck(TRUE);
iEdit[1]->SetCheck(FALSE);
iEdit[2]->SetCheck(FALSE);
break;
case IDC_IPOS_Y:
SetCur(1);
iEdit[0]->SetCheck(FALSE);
iEdit[1]->SetCheck(TRUE);
iEdit[2]->SetCheck(FALSE);
break;
case IDC_IPOS_Z:
SetCur(2);
iEdit[0]->SetCheck(FALSE);
iEdit[1]->SetCheck(FALSE);
iEdit[2]->SetCheck(TRUE);
break;
}
}
static BOOL CALLBACK IPosParamDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
IPosDlg *dlg = (IPosDlg*)GetWindowLong(hDlg,GWL_USERDATA);
switch (message) {
case WM_INITDIALOG:
dlg = (IPosDlg*)lParam;
SetWindowLong(hDlg,GWL_USERDATA,lParam);
dlg->hWnd = hDlg;
dlg->Init();
break;
case WM_COMMAND:
dlg->WMCommand(LOWORD(wParam),HIWORD(wParam),(HWND)lParam);
break;
case WM_LBUTTONDOWN:case WM_LBUTTONUP: case WM_MOUSEMOVE:
dlg->ip->RollupMouseMessage(hDlg,message,wParam,lParam);
break;
default:
return FALSE;
}
return TRUE;
}
IndePosition::IndePosition(const IndePosition &ctrl)
{
posX = NULL;
posY = NULL;
posZ = NULL;
if (ctrl.posX) {
ReplaceReference(IPOS_X_REF,ctrl.posX);
} else {
ReplaceReference(IPOS_X_REF,NewDefaultFloatController());
}
if (ctrl.posY) {
ReplaceReference(IPOS_Y_REF,ctrl.posY);
} else {
ReplaceReference(IPOS_Y_REF,NewDefaultFloatController());
}
if (ctrl.posZ) {
ReplaceReference(IPOS_Z_REF,ctrl.posZ);
} else {
ReplaceReference(IPOS_Z_REF,NewDefaultFloatController());
}
curval = ctrl.curval;
ivalid = ctrl.ivalid;
}
IndePosition::IndePosition(BOOL loading)
{
posX = NULL;
posY = NULL;
posZ = NULL;
if (!loading) {
ReplaceReference(IPOS_X_REF,NewDefaultFloatController());
ReplaceReference(IPOS_Y_REF,NewDefaultFloatController());
ReplaceReference(IPOS_Z_REF,NewDefaultFloatController());
ivalid = FOREVER;
curval = Point3(0,0,0);
} else {
ivalid.SetEmpty();
}
}
RefTargetHandle IndePoint3::Clone(RemapDir& remap)
{
IndePoint3 *pos = new IndePoint3(TRUE);
pos->ReplaceReference(IPOS_X_REF, remap.CloneRef(posX));
pos->ReplaceReference(IPOS_Y_REF, remap.CloneRef(posY));
pos->ReplaceReference(IPOS_Z_REF, remap.CloneRef(posZ));
return pos;
}
RefTargetHandle IndeColor::Clone(RemapDir& remap)
{
IndeColor *pos = new IndeColor(TRUE);
pos->ReplaceReference(IPOS_X_REF, remap.CloneRef(posX));
pos->ReplaceReference(IPOS_Y_REF, remap.CloneRef(posY));
pos->ReplaceReference(IPOS_Z_REF, remap.CloneRef(posZ));
return pos;
}
RefTargetHandle IndePosition::Clone(RemapDir& remap)
{
IndePosition *pos = new IndePosition(TRUE);
pos->ReplaceReference(IPOS_X_REF, remap.CloneRef(posX));
pos->ReplaceReference(IPOS_Y_REF, remap.CloneRef(posY));
pos->ReplaceReference(IPOS_Z_REF, remap.CloneRef(posZ));
return pos;
}
IndePosition::~IndePosition()
{
DeleteAllRefsFromMe();
}
void IndePosition::Copy(Control *from)
{
if (from->ClassID()==ClassID()) {
IndePosition *ctrl = (IndePosition*)from;
ReplaceReference(IPOS_X_REF,ctrl->posX);
ReplaceReference(IPOS_Y_REF,ctrl->posY);
ReplaceReference(IPOS_Z_REF,ctrl->posZ);
curval = ctrl->curval;
ivalid = ctrl->ivalid;
} else {
Point3 v;
Interval iv;
int num;
if (num=from->NumKeys()) {
SuspendAnimate();
AnimateOn();
for (int i=0; i<num; i++) {
TimeValue t = from->GetKeyTime(i);
from->GetValue(t,&v,iv);
SetValue(t,&v,TRUE,CTRL_ABSOLUTE);
}
ResumeAnimate();
} else {
from->GetValue(0,&v,ivalid);
SetValue(0,&v,TRUE,CTRL_ABSOLUTE);
}
}
NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
}
void IndePosition::Update(TimeValue t)
{
if (!ivalid.InInterval(t)) {
ivalid = FOREVER;
if (posX) posX->GetValue(t,&curval.x,ivalid);
if (posY) posY->GetValue(t,&curval.y,ivalid);
if (posZ) posZ->GetValue(t,&curval.z,ivalid);
}
}
void IndePosition::SetValue(TimeValue t, void *val, int commit, GetSetMethod method)
{
Point3 *v = (Point3*)val;
if (posX) posX->SetValue(t,&v->x,commit,method);
if (posY) posY->SetValue(t,&v->y,commit,method);
if (posZ) posZ->SetValue(t,&v->z,commit,method);
ivalid.SetEmpty();
NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
}
void IndePosition::GetValue(TimeValue t, void *val, Interval &valid, GetSetMethod method)
{
Update(t);
valid &= ivalid;
if (method==CTRL_RELATIVE) {
Matrix3 *mat = (Matrix3*)val;
mat->PreTranslate(curval);
} else {
*((Point3*)val) = curval;
}
}
void IndePoint3::GetValue(TimeValue t, void *val, Interval &valid, GetSetMethod method)
{
Update(t);
valid &= ivalid;
if (method==CTRL_RELATIVE) {
*((Point3*)val) += curval;
} else {
*((Point3*)val) = curval;
}
}
void IndePosition::CommitValue(TimeValue t)
{
if (posX) posX->CommitValue(t);
if (posY) posY->CommitValue(t);
if (posZ) posZ->CommitValue(t);
}
void IndePosition::RestoreValue(TimeValue t)
{
if (posX) posX->RestoreValue(t);
if (posY) posY->RestoreValue(t);
if (posZ) posZ->RestoreValue(t);
}
RefTargetHandle IndePosition::GetReference(int i)
{
switch (i) {
case IPOS_X_REF: return posX;
case IPOS_Y_REF: return posY;
case IPOS_Z_REF: return posZ;
default: return NULL;
}
}
void IndePosition::SetReference(int i, RefTargetHandle rtarg)
{
switch (i) {
case IPOS_X_REF: posX = (Control*)rtarg; break;
case IPOS_Y_REF: posY = (Control*)rtarg; break;
case IPOS_Z_REF: posZ = (Control*)rtarg; break;
}
}
Animatable* IndePosition::SubAnim(int i)
{
return GetReference(i);
}
TSTR IndePosition::SubAnimName(int i)
{
if (ClassID()==IPOS_CONTROL_CLASS_ID) {
switch (i) {
case IPOS_X_REF: return GetString(IDS_RB_XPOSITION);
case IPOS_Y_REF: return GetString(IDS_RB_YPOSITION);
case IPOS_Z_REF: return GetString(IDS_RB_ZPOSITION);
default: return _T("");
}
} else
if (ClassID()==IPOINT3_CONTROL_CLASS_ID) {
switch (i) {
case IPOS_X_REF: return _T("X");
case IPOS_Y_REF: return _T("Y");
case IPOS_Z_REF: return _T("Z");
default: return _T("");
}
} else {
switch (i) {
case IPOS_X_REF: return _T("R");
case IPOS_Y_REF: return _T("G");
case IPOS_Z_REF: return _T("B");
default: return _T("");
}
}
}
RefResult IndePosition::NotifyRefChanged(
Interval iv,
RefTargetHandle hTarg,
PartID& partID,
RefMessage msg)
{
switch (msg) {
case REFMSG_CHANGE:
ivalid.SetEmpty();
break;
case REFMSG_TARGET_DELETED:
if (posX == hTarg) posX = NULL;
if (posY == hTarg) posY = NULL;
if (posZ == hTarg) posZ = NULL;
break;
case REFMSG_GET_CONTROL_DIM: {
ParamDimension **dim = (ParamDimension **)partID;
assert(dim);
*dim = stdWorldDim;
}
}
return REF_SUCCEED;
}
BOOL IndePosition::AssignController(Animatable *control,int subAnim)
{
switch (subAnim) {
case IPOS_X_REF:
ReplaceReference(IPOS_X_REF,(RefTargetHandle)control);
break;
case IPOS_Y_REF:
ReplaceReference(IPOS_Y_REF,(RefTargetHandle)control);
break;
case IPOS_Z_REF:
ReplaceReference(IPOS_Z_REF,(RefTargetHandle)control);
break;
}
NotifyDependents(FOREVER,0,REFMSG_CONTROLREF_CHANGE,TREE_VIEW_CLASS_ID,FALSE);
NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
return TRUE;
}
void IndePosition::AddNewKey(TimeValue t,DWORD flags)
{
if (posX) posX->AddNewKey(t,flags);
if (posY) posY->AddNewKey(t,flags);
if (posZ) posZ->AddNewKey(t,flags);
}
int IndePosition::NumKeys()
{
int num = 0;
if (posX) num += posX->NumKeys();
if (posY) num += posY->NumKeys();
if (posZ) num += posZ->NumKeys();
return num;
}
TimeValue IndePosition::GetKeyTime(int index)
{
int onum,num = 0;
if (posX) num += posX->NumKeys();
if (index < num) return posX->GetKeyTime(index);
onum = num;
if (posY) num += posY->NumKeys();
if (index < num) return posY->GetKeyTime(index-onum);
onum = num;
if (posZ) num += posZ->NumKeys();
if (index < num) return posZ->GetKeyTime(index-onum);
return 0;
}
void IndePosition::CopyKeysFromTime(TimeValue src,TimeValue dst,DWORD flags)
{
if (posX) posX->CopyKeysFromTime(src,dst,flags);
if (posY) posY->CopyKeysFromTime(src,dst,flags);
if (posZ) posZ->CopyKeysFromTime(src,dst,flags);
}
BOOL IndePosition::IsKeyAtTime(TimeValue t,DWORD flags)
{
if (posX && posX->IsKeyAtTime(t,flags)) return TRUE;
if (posY && posY->IsKeyAtTime(t,flags)) return TRUE;
if (posZ && posZ->IsKeyAtTime(t,flags)) return TRUE;
return FALSE;
}
void IndePosition::DeleteKeyAtTime(TimeValue t)
{
if (posX) posX->DeleteKeyAtTime(t);
if (posY) posY->DeleteKeyAtTime(t);
if (posZ) posZ->DeleteKeyAtTime(t);
}
BOOL IndePosition::GetNextKeyTime(TimeValue t,DWORD flags,TimeValue &nt)
{
TimeValue at,tnear;
BOOL tnearInit = FALSE;
if (posX && posX->GetNextKeyTime(t,flags,at)) {
if (!tnearInit) {
tnear = at;
tnearInit = TRUE;
} else
if (ABS(at-t) < ABS(tnear-t)) tnear = at;
}
if (posY && posY->GetNextKeyTime(t,flags,at)) {
if (!tnearInit) {
tnear = at;
tnearInit = TRUE;
} else
if (ABS(at-t) < ABS(tnear-t)) tnear = at;
}
if (posZ && posZ->GetNextKeyTime(t,flags,at)) {
if (!tnearInit) {
tnear = at;
tnearInit = TRUE;
} else
if (ABS(at-t) < ABS(tnear-t)) tnear = at;
}
if (tnearInit) {
nt = tnear;
return TRUE;
} else {
return FALSE;
}
}
void IndePosition::BeginEditParams(
IObjParam *ip, ULONG flags,Animatable *prev)
{
this->ip = ip;
if (dlg) {
dlg->BeginingEdit(this,ip,(IndePosition*)prev);
} else {
dlg = new IPosDlg(this,ip);
}
}
void IndePosition::EndEditParams(
IObjParam *ip, ULONG flags,Animatable *next)
{
IndePosition *cont=NULL;
if (next && next->ClassID()==ClassID()) {
cont = (IndePosition*)next;
}
if (dlg) {
if (cont) {
dlg->EndingEdit(cont);
} else {
delete dlg;
dlg = NULL;
}
}
}