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.
2232 lines
60 KiB
C++
2232 lines
60 KiB
C++
/**********************************************************************
|
|
*<
|
|
FILE: exprctrl.cpp
|
|
|
|
DESCRIPTION: An expression-based controller
|
|
|
|
CREATED BY: Don Brittain
|
|
|
|
HISTORY: created 24 August 1995 (Windows 95 debut!)
|
|
|
|
*> Copyright (c) 1995, All Rights Reserved.
|
|
**********************************************************************/
|
|
|
|
#include "ctrl.h"
|
|
#include "expctrl.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
extern HINSTANCE hInstance;
|
|
|
|
int ExprControl::winX = -1;
|
|
int ExprControl::winY = -1;
|
|
|
|
ClassDesc* GetExprPosCtrlDesc() {return &exprPosCD;}
|
|
|
|
ClassDesc* GetExprP3CtrlDesc() {return &exprP3CD;}
|
|
|
|
ClassDesc* GetExprFloatCtrlDesc() {return &exprFloatCD;}
|
|
|
|
ClassDesc* GetExprScaleCtrlDesc() {return &exprScaleCD;}
|
|
|
|
ClassDesc* GetExprRotCtrlDesc() {return &exprRotCD;}
|
|
|
|
|
|
ExprControl::ExprControl(int t, ExprControl &ctrl)
|
|
{
|
|
int i, j, ct, slot;
|
|
TCHAR *cp;
|
|
|
|
type = t;
|
|
hParams = NULL;
|
|
hFixedFont = CreateFont(14,0,0,0,0,0,0,0,0,0,0,0, FIXED_PITCH | FF_MODERN, _T(""));
|
|
edbg = NULL;
|
|
|
|
range = ctrl.range;
|
|
curPosVal = ctrl.curPosVal;
|
|
curFloatVal = ctrl.curFloatVal;
|
|
ivalid = ctrl.ivalid;
|
|
sRegCt = vRegCt = 0;
|
|
desc = ctrl.desc;
|
|
ct = ctrl.expr.getVarCount(SCALAR_VAR);
|
|
for(i = 0; i < ct; i++) {
|
|
cp = ctrl.expr.getVarName(SCALAR_VAR, i);
|
|
updRegCt(slot = expr.defVar(SCALAR_VAR, cp), SCALAR_VAR);
|
|
if(slot == -1) // variable already defined
|
|
continue;
|
|
if(_tcscmp(cp, _T("T")) == 0)
|
|
timeSlots[EXPR_TICKS] = slot;
|
|
else if(_tcscmp(cp, _T("S")) == 0)
|
|
timeSlots[EXPR_SECS] = slot;
|
|
else if(_tcscmp(cp, _T("F")) == 0)
|
|
timeSlots[EXPR_FRAMES] = slot;
|
|
else if(_tcscmp(cp, _T("NT")) == 0)
|
|
timeSlots[EXPR_NTIME] = slot;
|
|
else {
|
|
dfnVar(SCALAR_VAR, cp, slot, ctrl.getVarOffset(SCALAR_VAR, j=i-4));
|
|
|
|
if(ctrl.sVars[j].refID < 0)
|
|
assignScalarValue(slot, ctrl.sVars[j].val);
|
|
else
|
|
assignController(SCALAR_VAR, slot-4, ctrl.refTab[ctrl.sVars[j].refID].client, ctrl.sVars[j].subNum);
|
|
}
|
|
}
|
|
ct = ctrl.expr.getVarCount(VECTOR_VAR);
|
|
for(i = 0; i < ct; i++) {
|
|
cp = ctrl.expr.getVarName(VECTOR_VAR, i);
|
|
updRegCt(slot = expr.defVar(VECTOR_VAR, cp), VECTOR_VAR);
|
|
dfnVar(VECTOR_VAR, cp, slot, ctrl.getVarOffset(VECTOR_VAR, i));
|
|
|
|
if(ctrl.vVars[i].refID < 0)
|
|
assignVectorValue(slot, ctrl.vVars[i].val);
|
|
else
|
|
assignController(VECTOR_VAR, slot, ctrl.refTab[ctrl.vVars[i].refID].client, ctrl.vVars[i].subNum);
|
|
}
|
|
cp = ctrl.expr.getExprStr();
|
|
expr.load(cp);
|
|
}
|
|
|
|
|
|
ExprControl::ExprControl(int t, BOOL loading)
|
|
{
|
|
type = t;
|
|
range.Set(GetAnimStart(), GetAnimEnd());
|
|
curPosVal = Point3(0,0,0);
|
|
curFloatVal = 0.0f;
|
|
ivalid.SetEmpty();
|
|
sRegCt = vRegCt = 0;
|
|
updRegCt(timeSlots[EXPR_TICKS] = expr.defVar(SCALAR_VAR, _T("T")), SCALAR_VAR);
|
|
updRegCt(timeSlots[EXPR_SECS] = expr.defVar(SCALAR_VAR, _T("S")), SCALAR_VAR);
|
|
updRegCt(timeSlots[EXPR_FRAMES] = expr.defVar(SCALAR_VAR, _T("F")), SCALAR_VAR);
|
|
updRegCt(timeSlots[EXPR_NTIME] = expr.defVar(SCALAR_VAR, _T("NT")), SCALAR_VAR);
|
|
switch(type = t) {
|
|
case EXPR_POS_CONTROL_CLASS_ID:
|
|
case EXPR_P3_CONTROL_CLASS_ID:
|
|
expr.load(_T("[ 0, 0, 0 ]"));
|
|
break;
|
|
case EXPR_SCALE_CONTROL_CLASS_ID:
|
|
expr.load(_T("[ 1, 1, 1 ]"));
|
|
break;
|
|
case EXPR_FLOAT_CONTROL_CLASS_ID:
|
|
expr.load(_T("0"));
|
|
break;
|
|
case EXPR_ROT_CONTROL_CLASS_ID:
|
|
expr.load(_T("{ [ 0, 0, 0 ], 0 }"));
|
|
break;
|
|
}
|
|
hParams = NULL;
|
|
hFixedFont = CreateFont(14,0,0,0,0,0,0,0,0,0,0,0, FIXED_PITCH | FF_MODERN, _T(""));
|
|
edbg = NULL;
|
|
}
|
|
|
|
ExprControl::~ExprControl()
|
|
{
|
|
deleteAllVars();
|
|
DeleteObject(hFixedFont);
|
|
if (hParams)
|
|
DestroyWindow(hParams);
|
|
DeleteAllRefsFromMe();
|
|
}
|
|
|
|
void ExprControl::updRegCt(int val, int type)
|
|
{
|
|
if(type == SCALAR_VAR) {
|
|
if(val+1 > sRegCt)
|
|
sRegCt = val+1;
|
|
}
|
|
else {
|
|
if(val+1 > vRegCt)
|
|
vRegCt = val+1;
|
|
}
|
|
}
|
|
|
|
BOOL ExprControl::dfnVar(int type, TCHAR *buf, int slot, int offset)
|
|
{
|
|
int i;
|
|
if(type == SCALAR_VAR) {
|
|
SVar sv;
|
|
sv.regNum = slot;
|
|
sv.offset = offset;
|
|
sv.refID = -1;
|
|
sv.val = 0.0f;
|
|
i = sVars.Append(1, &sv, 4);
|
|
sVars[i].name = buf;
|
|
}
|
|
else {
|
|
VVar vv;
|
|
// vv.name = buf;
|
|
vv.regNum = slot;
|
|
vv.offset = offset;
|
|
vv.refID = -1;
|
|
vv.val.x =
|
|
vv.val.y =
|
|
vv.val.z = 0.0f;
|
|
i = vVars.Append(1, &vv, 4);
|
|
vVars[i].name = buf;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void ExprControl::deleteAllVars()
|
|
{
|
|
int i, ct;
|
|
|
|
ct = sVars.Count();
|
|
for(i = 0; i < ct; i++)
|
|
delete sVars[i].name;
|
|
sVars.SetCount(0);
|
|
ct = vVars.Count();
|
|
for(i = 0; i < ct; i++)
|
|
delete vVars[i].name;
|
|
vVars.SetCount(0);
|
|
}
|
|
|
|
TCHAR *ExprControl::getVarName(int type, int i)
|
|
{
|
|
if(type == SCALAR_VAR) {
|
|
if(i < sVars.Count())
|
|
return sVars[i].name;
|
|
}
|
|
else {
|
|
if(i < vVars.Count())
|
|
return vVars[i].name;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int ExprControl::getVarOffset(int type, int i)
|
|
{
|
|
if(type == SCALAR_VAR) {
|
|
if(i < sVars.Count())
|
|
return sVars[i].offset;
|
|
}
|
|
else {
|
|
if(i < vVars.Count())
|
|
return vVars[i].offset;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int ExprControl::getRegNum(int type, int i)
|
|
{
|
|
if(type == SCALAR_VAR) {
|
|
if(i < sVars.Count())
|
|
return sVars[i].regNum;
|
|
}
|
|
else {
|
|
if(i < vVars.Count())
|
|
return vVars[i].regNum;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
float ExprControl::getScalarValue(int i)
|
|
{
|
|
if((i < sVars.Count()) && (sVars[i].refID < 0))
|
|
return sVars[i].val;
|
|
return 0.0f;
|
|
}
|
|
|
|
Point3 ExprControl::getVectorValue(int i)
|
|
{
|
|
if((i < vVars.Count()) && (vVars[i].refID < 0))
|
|
return vVars[i].val;
|
|
return Point3(0.0f, 0.0f, 0.0f);
|
|
}
|
|
|
|
BOOL ExprControl::assignScalarValue(int i, float val)
|
|
{
|
|
if(i < sVars.Count()) {
|
|
sVars[i].refID = -1;
|
|
sVars[i].val = val;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL ExprControl::assignVectorValue(int i, Point3 &val)
|
|
{
|
|
if(i < vVars.Count()) {
|
|
vVars[i].refID = -1;
|
|
vVars[i].val = val;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
class FloatFilter : public TrackViewFilter {
|
|
public:
|
|
BOOL proc(Animatable *anim, Animatable *client,int subNum)
|
|
{ return anim->SuperClassID() == CTRL_FLOAT_CLASS_ID; }
|
|
};
|
|
|
|
class VectorFilter : public TrackViewFilter {
|
|
public:
|
|
BOOL proc(Animatable *anim, Animatable *client,int subNum)
|
|
{ return anim->SuperClassID() == CTRL_POSITION_CLASS_ID ||
|
|
anim->SuperClassID() == CTRL_POINT3_CLASS_ID ||
|
|
anim->SuperClassID() == BASENODE_CLASS_ID; }
|
|
};
|
|
|
|
BOOL ExprControl::assignController(int type, int varIndex, ReferenceTarget *client, int subNum)
|
|
{
|
|
if (!client) return FALSE;
|
|
|
|
int i, ct;
|
|
|
|
ct = refTab.Count();
|
|
for(i = 0; i < ct; i++) {
|
|
if(refTab[i].client == client) {
|
|
refTab[i].refCt++;
|
|
break;
|
|
}
|
|
}
|
|
if(i >= ct) {
|
|
VarRef vr(client);
|
|
i = refTab.Append(1, &vr, 4);
|
|
if(MakeRefByID(FOREVER, StdControl::NumRefs()+i, client) != REF_SUCCEED) {
|
|
refTab.Delete(i, 1);
|
|
TSTR s = GetString(IDS_DB_CIRCULAR_DEPENDENCY);
|
|
MessageBox(hDlg, s, GetString(IDS_DB_CANT_ASSIGN),
|
|
MB_ICONEXCLAMATION | MB_SYSTEMMODAL | MB_OK);
|
|
return FALSE;
|
|
}
|
|
}
|
|
if(type == SCALAR_VAR) {
|
|
if(varIndex >= sVars.Count()) {
|
|
// should delete reference
|
|
return FALSE;
|
|
}
|
|
sVars[varIndex].refID = i;
|
|
sVars[varIndex].subNum = subNum;
|
|
return TRUE;
|
|
}
|
|
else if(type == VECTOR_VAR) {
|
|
if(varIndex >= vVars.Count()) {
|
|
// should delete reference
|
|
return FALSE;
|
|
}
|
|
vVars[varIndex].refID = i;
|
|
vVars[varIndex].subNum = subNum;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// This patch is here to convert number strings where the decimal point
|
|
// is a comma into numbers with a '.' for a decimal point.
|
|
// This is needed because the expression object only parses the '.' notation
|
|
|
|
TCHAR *UglyPatch(TCHAR *buf)
|
|
{
|
|
TCHAR *cp = buf;
|
|
while(*cp) {
|
|
if( *cp == _T(','))
|
|
*cp = _T('.');
|
|
else if (*cp == _T(';'))
|
|
*cp = _T(',');
|
|
cp++;
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
void ExprControl::Copy(Control *from)
|
|
{
|
|
int i, j, ct, slot;
|
|
TCHAR *cp;
|
|
TCHAR buf[256];
|
|
|
|
if (from->ClassID()==ClassID()) {
|
|
ExprControl *ctrl = (ExprControl*)from;
|
|
if(type != ctrl->type)
|
|
goto dropOut;
|
|
curPosVal = ctrl->curPosVal;
|
|
curFloatVal = ctrl->curFloatVal;
|
|
ivalid = ctrl->ivalid;
|
|
range = ctrl->range;
|
|
type = ctrl->type;
|
|
desc = ctrl->desc;
|
|
// sRegCt = vRegCt = 0;
|
|
ct = ctrl->expr.getVarCount(SCALAR_VAR);
|
|
for(i = 0; i < ct; i++) {
|
|
cp = ctrl->expr.getVarName(SCALAR_VAR, i);
|
|
updRegCt(slot = expr.defVar(SCALAR_VAR, cp), SCALAR_VAR);
|
|
if(slot == -1) // variable already defined
|
|
continue;
|
|
if(_tcscmp(cp, _T("T")) == 0)
|
|
timeSlots[EXPR_TICKS] = slot;
|
|
else if(_tcscmp(cp, _T("S")) == 0)
|
|
timeSlots[EXPR_SECS] = slot;
|
|
else if(_tcscmp(cp, _T("F")) == 0)
|
|
timeSlots[EXPR_FRAMES] = slot;
|
|
else if(_tcscmp(cp, _T("NT")) == 0)
|
|
timeSlots[EXPR_NTIME] = slot;
|
|
else {
|
|
dfnVar(SCALAR_VAR, cp, slot, ctrl->getVarOffset(SCALAR_VAR, j=i-4));
|
|
|
|
if(ctrl->sVars[j].refID < 0)
|
|
assignScalarValue(slot, ctrl->sVars[j].val);
|
|
else
|
|
assignController(SCALAR_VAR, slot-4, ctrl->refTab[ctrl->sVars[j].refID].client, ctrl->sVars[j].subNum);
|
|
}
|
|
}
|
|
ct = ctrl->expr.getVarCount(VECTOR_VAR);
|
|
for(i = 0; i < ct; i++) {
|
|
cp = ctrl->expr.getVarName(VECTOR_VAR, i);
|
|
updRegCt(slot = expr.defVar(VECTOR_VAR, cp), VECTOR_VAR);
|
|
dfnVar(VECTOR_VAR, cp, slot, ctrl->getVarOffset(VECTOR_VAR, i));
|
|
|
|
if(ctrl->vVars[i].refID < 0)
|
|
assignVectorValue(slot, ctrl->vVars[i].val);
|
|
else
|
|
assignController(VECTOR_VAR, slot, ctrl->refTab[ctrl->vVars[i].refID].client, ctrl->vVars[i].subNum);
|
|
}
|
|
expr.load(ctrl->expr.getExprStr());
|
|
}
|
|
else {
|
|
dropOut:
|
|
switch(type) {
|
|
case EXPR_POS_CONTROL_CLASS_ID:
|
|
case EXPR_P3_CONTROL_CLASS_ID:
|
|
from->GetValue(0,&curPosVal,ivalid);
|
|
_stprintf(buf, _T("[ %g; %g; %g ]"), curPosVal.x, curPosVal.y, curPosVal.z);
|
|
expr.load(UglyPatch(buf));
|
|
break;
|
|
case EXPR_FLOAT_CONTROL_CLASS_ID:
|
|
from->GetValue(0,&curFloatVal,ivalid);
|
|
_stprintf(buf, _T("%g"), curFloatVal);
|
|
expr.load(UglyPatch(buf));
|
|
break;
|
|
// should deal with SCALE and ROT types, but punt for now...
|
|
}
|
|
}
|
|
NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
|
|
}
|
|
|
|
|
|
/*
|
|
class FindNodeDEP : public DependentEnumProc {
|
|
public:
|
|
INode *node;
|
|
FindNodeDEP() {node=NULL;}
|
|
int proc(ReferenceMaker *rmaker) {
|
|
if (rmaker->SuperClassID()==BASENODE_CLASS_ID) {
|
|
node = (INode*)rmaker;
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
};
|
|
class FindPRSDEP : public DependentEnumProc {
|
|
public:
|
|
Control *cont;
|
|
FindPRSDEP() {cont=NULL;}
|
|
int proc(ReferenceMaker *rmaker) {
|
|
if (rmaker->SuperClassID()==CTRL_MATRIX3_CLASS_ID) {
|
|
cont = (Control*)rmaker;
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
};
|
|
|
|
void ExprControl::GetAbsoluteControlValue(
|
|
Control *c,TimeValue t,Point3 *pt,Interval &iv)
|
|
{
|
|
FindPRSDEP dep1;
|
|
FindNodeDEP dep2;
|
|
c->EnumDependents(&dep1);
|
|
if (dep1.cont) dep1.cont->EnumDependents(&dep2);
|
|
if (dep2.node) {
|
|
Matrix3 tm = dep2.node->GetNodeTM(t,&iv);
|
|
*pt = tm.GetTrans();
|
|
} else {
|
|
c->GetValue(t, pt, iv);
|
|
}
|
|
}
|
|
*/
|
|
|
|
void ExprControl::GetAbsoluteControlValue(
|
|
INode *node,TimeValue t,Point3 *pt,Interval &iv)
|
|
{
|
|
Matrix3 tm = node->GetNodeTM(t,&iv);
|
|
*pt = tm.GetTrans();
|
|
}
|
|
|
|
void ExprControl::GetValueLocalTime(TimeValue t, void *val, Interval &valid, GetSetMethod method)
|
|
{
|
|
int i;
|
|
float *sregs = new float[sRegCt];
|
|
Point3 *vregs = new Point3[vRegCt];
|
|
ivalid.SetInstant(t);
|
|
valid &= ivalid;
|
|
|
|
// Limit to in range
|
|
if (t<range.Start()) t = range.Start();
|
|
if (t>range.End()) t = range.End();
|
|
|
|
switch(type) {
|
|
case EXPR_POS_CONTROL_CLASS_ID:
|
|
case EXPR_P3_CONTROL_CLASS_ID:
|
|
case EXPR_SCALE_CONTROL_CLASS_ID:
|
|
if(expr.getExprType() == VECTOR_EXPR) {
|
|
sregs[timeSlots[EXPR_TICKS]] = (float)t;
|
|
sregs[timeSlots[EXPR_SECS]] = (float)t/4800.0f;
|
|
sregs[timeSlots[EXPR_FRAMES]] = (float)t/GetTicksPerFrame();
|
|
sregs[timeSlots[EXPR_NTIME]] = (float)(t-range.Start()) / (float)(range.End()-range.Start());
|
|
for(i = 0; i < sVars.Count(); i++) {
|
|
if(sVars[i].refID < 0)
|
|
sregs[sVars[i].regNum] = sVars[i].val;
|
|
else {
|
|
Control *c;
|
|
Interval iv;
|
|
c = (Control *)refTab[sVars[i].refID].client->SubAnim(sVars[i].subNum);
|
|
c->GetValue(t+sVars[i].offset, &sregs[sVars[i].regNum], iv);
|
|
}
|
|
}
|
|
for(i = 0; i < vVars.Count(); i++) {
|
|
if(vVars[i].refID < 0 || !refTab[vVars[i].refID].client)
|
|
vregs[vVars[i].regNum] = vVars[i].val;
|
|
else {
|
|
Control *c;
|
|
Interval iv;
|
|
/*
|
|
<<<<<<< SourceSafe version
|
|
c = (Control *)refTab[vVars[i].refID].client->SubAnim(vVars[i].subNum);
|
|
c->GetValue(t+vVars[i].offset, &vregs[vVars[i].regNum], iv);
|
|
=======
|
|
*/
|
|
// Rolf: check vVars[i].absPos
|
|
if (vVars[i].subNum<0) {
|
|
GetAbsoluteControlValue(
|
|
(INode*)refTab[vVars[i].refID].client,t+vVars[i].offset,&vregs[vVars[i].regNum], iv);
|
|
} else {
|
|
c = (Control *)refTab[vVars[i].refID].client->SubAnim(vVars[i].subNum);
|
|
c->GetValue(t+vVars[i].offset, &vregs[vVars[i].regNum], iv);
|
|
}
|
|
//>>>>>>> Local version
|
|
}
|
|
}
|
|
if(expr.eval((float *)&curPosVal, sRegCt, sregs, vRegCt, vregs))
|
|
curPosVal = type == EXPR_SCALE_CONTROL_CLASS_ID ? Point3(1,1,1) : Point3(0,0,0);
|
|
}
|
|
else
|
|
curPosVal = type == EXPR_SCALE_CONTROL_CLASS_ID ? Point3(1,1,1) : Point3(0,0,0);
|
|
if (method==CTRL_RELATIVE) {
|
|
if(type == EXPR_POS_CONTROL_CLASS_ID) {
|
|
Matrix3 *mat = (Matrix3*)val;
|
|
// mat->SetTrans(mat->GetTrans()+curPosVal);
|
|
mat->PreTranslate(curPosVal); // DS 9/23/96
|
|
}
|
|
else if(type == EXPR_SCALE_CONTROL_CLASS_ID) {
|
|
Matrix3 *mat = (Matrix3*)val;
|
|
mat->Scale(curPosVal);
|
|
}
|
|
else {
|
|
Point3 *p = (Point3 *)val;
|
|
*p += curPosVal;
|
|
}
|
|
}
|
|
else {
|
|
if(type == EXPR_SCALE_CONTROL_CLASS_ID)
|
|
*((ScaleValue *)val) = ScaleValue(curPosVal);
|
|
else
|
|
*((Point3*)val) = curPosVal;
|
|
}
|
|
break;
|
|
case EXPR_FLOAT_CONTROL_CLASS_ID:
|
|
if(expr.getExprType() == SCALAR_EXPR) {
|
|
sregs[timeSlots[EXPR_TICKS]] = (float)t;
|
|
sregs[timeSlots[EXPR_SECS]] = (float)t/4800.0f;
|
|
sregs[timeSlots[EXPR_FRAMES]] = (float)t/GetTicksPerFrame();
|
|
sregs[timeSlots[EXPR_NTIME]] = (float)(t-range.Start()) / (float)(range.End()-range.Start());
|
|
for(i = 0; i < sVars.Count(); i++) {
|
|
if(sVars[i].refID < 0)
|
|
sregs[sVars[i].regNum] = sVars[i].val;
|
|
else {
|
|
Control *c;
|
|
Interval iv;
|
|
c = (Control *)refTab[sVars[i].refID].client->SubAnim(sVars[i].subNum);
|
|
if(c)
|
|
c->GetValue(t+sVars[i].offset, &sregs[sVars[i].regNum], iv);
|
|
else
|
|
sregs[sVars[i].regNum] = sVars[i].val;
|
|
}
|
|
}
|
|
for(i = 0; i < vVars.Count(); i++) {
|
|
if(vVars[i].refID < 0 || !refTab[vVars[i].refID].client)
|
|
vregs[vVars[i].regNum] = vVars[i].val;
|
|
else {
|
|
Control *c;
|
|
Interval iv;
|
|
/*
|
|
<<<<<<< SourceSafe version
|
|
c = (Control *)refTab[vVars[i].refID].client->SubAnim(vVars[i].subNum);
|
|
c->GetValue(t+vVars[i].offset, &vregs[vVars[i].regNum], iv);
|
|
=======
|
|
*/
|
|
if (vVars[i].subNum<0) {
|
|
GetAbsoluteControlValue(
|
|
(INode*)refTab[vVars[i].refID].client,t+vVars[i].offset,&vregs[vVars[i].regNum], iv);
|
|
} else {
|
|
c = (Control *)refTab[vVars[i].refID].client->SubAnim(vVars[i].subNum);
|
|
c->GetValue(t+vVars[i].offset, &vregs[vVars[i].regNum], iv);
|
|
}
|
|
//>>>>>>> Local version
|
|
}
|
|
}
|
|
if(expr.eval((float *)&curFloatVal, sRegCt, sregs, vRegCt, vregs))
|
|
curFloatVal = 0.0f;
|
|
}
|
|
else
|
|
curFloatVal = 0.0f;
|
|
if (method==CTRL_RELATIVE) {
|
|
*((float *)val) += curFloatVal;
|
|
}
|
|
else {
|
|
*((float *)val) = curFloatVal;
|
|
}
|
|
break;
|
|
}
|
|
delete [] sregs;
|
|
delete [] vregs;
|
|
}
|
|
|
|
void *ExprControl::CreateTempValue()
|
|
{
|
|
switch(type) {
|
|
case EXPR_POS_CONTROL_CLASS_ID:
|
|
case EXPR_P3_CONTROL_CLASS_ID:
|
|
return new Point3;
|
|
case EXPR_SCALE_CONTROL_CLASS_ID:
|
|
return new ScaleValue;
|
|
case EXPR_FLOAT_CONTROL_CLASS_ID:
|
|
return new float;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void ExprControl::DeleteTempValue(void *val)
|
|
{
|
|
switch(type) {
|
|
case EXPR_POS_CONTROL_CLASS_ID:
|
|
case EXPR_P3_CONTROL_CLASS_ID:
|
|
delete (Point3 *)val;
|
|
break;
|
|
case EXPR_SCALE_CONTROL_CLASS_ID:
|
|
delete (ScaleValue *)val;
|
|
break;
|
|
case EXPR_FLOAT_CONTROL_CLASS_ID:
|
|
delete (float *)val;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ExprControl::ApplyValue(void *val, void *delta)
|
|
{
|
|
Matrix3 *mat;
|
|
switch(type) {
|
|
case EXPR_POS_CONTROL_CLASS_ID:
|
|
mat = (Matrix3*)val;
|
|
// mat->SetTrans(mat->GetTrans()+*((Point3 *)delta));
|
|
mat->PreTranslate(*((Point3 *)delta)); //DS 9/23/96
|
|
break;
|
|
case EXPR_P3_CONTROL_CLASS_ID:
|
|
*((Point3 *)val) += *((Point3 *)delta);
|
|
break;
|
|
case EXPR_FLOAT_CONTROL_CLASS_ID:
|
|
*((float *)val) += *((float *)delta);
|
|
break;
|
|
case EXPR_SCALE_CONTROL_CLASS_ID:
|
|
Matrix3 *mat = (Matrix3*)val;
|
|
ScaleValue *s = (ScaleValue*)delta;
|
|
ApplyScaling(*mat,*s);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ExprControl::MultiplyValue(void *val, float m)
|
|
{
|
|
switch(type) {
|
|
case EXPR_POS_CONTROL_CLASS_ID:
|
|
case EXPR_P3_CONTROL_CLASS_ID:
|
|
*((Point3 *)val) *= m;
|
|
break;
|
|
case EXPR_SCALE_CONTROL_CLASS_ID:
|
|
*((ScaleValue *)val) *= m;
|
|
break;
|
|
case EXPR_FLOAT_CONTROL_CLASS_ID:
|
|
*((float *)val) *= m;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ExprControl::Extrapolate(Interval range,TimeValue t,void *val,Interval &valid,int etype)
|
|
{
|
|
if(type == EXPR_FLOAT_CONTROL_CLASS_ID) {
|
|
float fval0, fval1, fval2, res;
|
|
switch (etype) {
|
|
case ORT_LINEAR:
|
|
if (t<range.Start()) {
|
|
GetValueLocalTime(range.Start(),&fval0,valid);
|
|
GetValueLocalTime(range.Start()+1,&fval1,valid);
|
|
res = LinearExtrapolate(range.Start(),t,fval0,fval1,fval0);
|
|
}
|
|
else {
|
|
GetValueLocalTime(range.End()-1,&fval0,valid);
|
|
GetValueLocalTime(range.End(),&fval1,valid);
|
|
res = LinearExtrapolate(range.End(),t,fval0,fval1,fval1);
|
|
}
|
|
break;
|
|
|
|
case ORT_IDENTITY:
|
|
if (t<range.Start()) {
|
|
GetValueLocalTime(range.Start(),&fval0,valid);
|
|
res = IdentityExtrapolate(range.Start(),t,fval0);
|
|
}
|
|
else {
|
|
GetValueLocalTime(range.End(),&fval0,valid);
|
|
res = IdentityExtrapolate(range.End(),t,fval0);
|
|
}
|
|
break;
|
|
|
|
case ORT_RELATIVE_REPEAT:
|
|
GetValueLocalTime(range.Start(),&fval0,valid);
|
|
GetValueLocalTime(range.End(),&fval1,valid);
|
|
GetValueLocalTime(CycleTime(range,t),&fval2,valid);
|
|
res = RepeatExtrapolate(range,t,fval0,fval1,fval2);
|
|
break;
|
|
}
|
|
valid.Set(t,t);
|
|
*((float*)val) = res;
|
|
}
|
|
else if(type == EXPR_SCALE_CONTROL_CLASS_ID) {
|
|
ScaleValue val0, val1, val2, res;
|
|
switch (etype) {
|
|
case ORT_LINEAR:
|
|
if (t<range.Start()) {
|
|
GetValueLocalTime(range.Start(),&val0,valid);
|
|
GetValueLocalTime(range.Start()+1,&val1,valid);
|
|
res = LinearExtrapolate(range.Start(),t,val0,val1,val0);
|
|
}
|
|
else {
|
|
GetValueLocalTime(range.End()-1,&val0,valid);
|
|
GetValueLocalTime(range.End(),&val1,valid);
|
|
res = LinearExtrapolate(range.End(),t,val0,val1,val1);
|
|
}
|
|
break;
|
|
|
|
case ORT_IDENTITY:
|
|
if (t<range.Start()) {
|
|
GetValueLocalTime(range.Start(),&val0,valid);
|
|
res = IdentityExtrapolate(range.Start(),t,val0);
|
|
}
|
|
else {
|
|
GetValueLocalTime(range.End(),&val0,valid);
|
|
res = IdentityExtrapolate(range.End(),t,val0);
|
|
}
|
|
break;
|
|
|
|
case ORT_RELATIVE_REPEAT:
|
|
GetValueLocalTime(range.Start(),&val0,valid);
|
|
GetValueLocalTime(range.End(),&val1,valid);
|
|
GetValueLocalTime(CycleTime(range,t),&val2,valid);
|
|
res = RepeatExtrapolate(range,t,val0,val1,val2);
|
|
break;
|
|
}
|
|
valid.Set(t,t);
|
|
*((ScaleValue *)val) = res;
|
|
}
|
|
else {
|
|
Point3 val0, val1, val2, res;
|
|
switch (etype) {
|
|
case ORT_LINEAR:
|
|
if (t<range.Start()) {
|
|
GetValueLocalTime(range.Start(),&val0,valid);
|
|
GetValueLocalTime(range.Start()+1,&val1,valid);
|
|
res = LinearExtrapolate(range.Start(),t,val0,val1,val0);
|
|
}
|
|
else {
|
|
GetValueLocalTime(range.End()-1,&val0,valid);
|
|
GetValueLocalTime(range.End(),&val1,valid);
|
|
res = LinearExtrapolate(range.End(),t,val0,val1,val1);
|
|
}
|
|
break;
|
|
|
|
case ORT_IDENTITY:
|
|
if (t<range.Start()) {
|
|
GetValueLocalTime(range.Start(),&val0,valid);
|
|
res = IdentityExtrapolate(range.Start(),t,val0);
|
|
}
|
|
else {
|
|
GetValueLocalTime(range.End(),&val0,valid);
|
|
res = IdentityExtrapolate(range.End(),t,val0);
|
|
}
|
|
break;
|
|
|
|
case ORT_RELATIVE_REPEAT:
|
|
GetValueLocalTime(range.Start(),&val0,valid);
|
|
GetValueLocalTime(range.End(),&val1,valid);
|
|
GetValueLocalTime(CycleTime(range,t),&val2,valid);
|
|
res = RepeatExtrapolate(range,t,val0,val1,val2);
|
|
break;
|
|
}
|
|
valid.Set(t,t);
|
|
*((Point3 *)val) = res;
|
|
}
|
|
}
|
|
|
|
ReferenceTarget* ExprControl::GetReference(int i)
|
|
{
|
|
int num;
|
|
|
|
if(i < (num = StdControl::NumRefs()))
|
|
return StdControl::GetReference(i);
|
|
return (ReferenceTarget*)refTab[i-num].client;
|
|
}
|
|
|
|
void ExprControl::SetReference(int i, RefTargetHandle rtarg)
|
|
{
|
|
int num;
|
|
|
|
if(i < (num = StdControl::NumRefs()))
|
|
StdControl::SetReference(i, rtarg);
|
|
else
|
|
refTab[i-num].client = rtarg;
|
|
}
|
|
|
|
|
|
// RB: When the last reference to an expression controller is
|
|
// deleted its parameter dialog needs to be closed.
|
|
void ExprControl::RefDeleted()
|
|
{
|
|
if (hParams) {
|
|
int c=0;
|
|
RefListItem *ptr = GetRefList().first;
|
|
while (ptr) {
|
|
if (ptr->maker!=NULL) {
|
|
if (ptr->maker->SuperClassID()) c++;
|
|
}
|
|
ptr = ptr->next;
|
|
}
|
|
if (!c) DestroyWindow(hParams);
|
|
}
|
|
}
|
|
|
|
|
|
class ExprDelTargetRestore : public RestoreObj {
|
|
public:
|
|
ExprControl *ec;
|
|
SVarTab sVarsUndo;
|
|
VVarTab vVarsUndo;
|
|
VarRefTab refTabUndo;
|
|
SVarTab sVarsRedo;
|
|
VVarTab vVarsRedo;
|
|
VarRefTab refTabRedo;
|
|
ExprDelTargetRestore(ExprControl *ec)
|
|
{
|
|
this->ec=ec;
|
|
|
|
sVarsUndo.SetCount(ec->sVars.Count());
|
|
for(int i = 0; i < ec->sVars.Count(); i++) {
|
|
sVarsUndo[i].refID = ec->sVars[i].refID;
|
|
sVarsUndo[i].subNum = ec->sVars[i].subNum;
|
|
}
|
|
|
|
vVarsUndo.SetCount(ec->vVars.Count());
|
|
for(i = 0; i < ec->vVars.Count(); i++) {
|
|
vVarsUndo[i].refID = ec->vVars[i].refID;
|
|
vVarsUndo[i].subNum = ec->vVars[i].subNum;
|
|
}
|
|
|
|
refTabUndo.SetCount(ec->refTab.Count());
|
|
for (i = 0; i < ec->refTab.Count(); i++)
|
|
refTabUndo[i] = ec->refTab[i];
|
|
}
|
|
void Restore(int isUndo)
|
|
{
|
|
// save the undo data in the redo tables
|
|
sVarsRedo.SetCount(sVarsUndo.Count());
|
|
for(int i = 0; i < sVarsUndo.Count(); i++) {
|
|
sVarsRedo[i].refID = sVarsUndo[i].refID;
|
|
sVarsRedo[i].subNum = sVarsUndo[i].subNum;
|
|
}
|
|
|
|
vVarsRedo.SetCount(vVarsUndo.Count());
|
|
for(i = 0; i < vVarsUndo.Count(); i++) {
|
|
vVarsRedo[i].refID = vVarsUndo[i].refID;
|
|
vVarsRedo[i].subNum = vVarsUndo[i].subNum;
|
|
}
|
|
|
|
refTabRedo.SetCount(refTabUndo.Count());
|
|
for (i = 0; i < refTabUndo.Count(); i++)
|
|
refTabRedo[i] = refTabUndo[i];
|
|
|
|
// put the undo data back into the controller
|
|
for(i = 0; i < ec->sVars.Count(); i++) {
|
|
ec->sVars[i].refID = sVarsUndo[i].refID;
|
|
ec->sVars[i].subNum = sVarsUndo[i].subNum;
|
|
}
|
|
|
|
for(i = 0; i < ec->vVars.Count(); i++) {
|
|
ec->vVars[i].refID = vVarsUndo[i].refID;
|
|
ec->vVars[i].subNum = vVarsUndo[i].subNum;
|
|
}
|
|
|
|
for (i = 0; i < ec->refTab.Count(); i++)
|
|
ec->refTab[i] = refTabUndo[i];
|
|
|
|
ec->NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
|
|
}
|
|
void Redo()
|
|
{
|
|
// put the redo data back into the controller
|
|
for(int i = 0; i < ec->sVars.Count(); i++) {
|
|
ec->sVars[i].refID = sVarsRedo[i].refID;
|
|
ec->sVars[i].subNum = sVarsRedo[i].subNum;
|
|
}
|
|
|
|
for(i = 0; i < ec->vVars.Count(); i++) {
|
|
ec->vVars[i].refID = vVarsRedo[i].refID;
|
|
ec->vVars[i].subNum = vVarsRedo[i].subNum;
|
|
}
|
|
|
|
for (i = 0; i < ec->refTab.Count(); i++)
|
|
ec->refTab[i] = refTabRedo[i];
|
|
|
|
ec->NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
|
|
}
|
|
void EndHold() { }
|
|
};
|
|
|
|
RefResult ExprControl::NotifyRefChanged(
|
|
Interval iv,
|
|
RefTargetHandle hTarg,
|
|
PartID& partID,
|
|
RefMessage msg)
|
|
{
|
|
int i;
|
|
|
|
switch (msg) {
|
|
case REFMSG_CHANGE:
|
|
ivalid.SetEmpty();
|
|
if(edbg)
|
|
edbg->Update();
|
|
break;
|
|
|
|
// DS: 5-21-97 -- removed the REFMSG_REF_DELETED. This would cause problems
|
|
// when multiple Expr controls referenced the same thing. When one of the expr
|
|
// controls got deleted this message was sent to all the others, setting their
|
|
// refs to NULL even though the target still had backptr to them. This would cause
|
|
// crashes later.
|
|
// case REFMSG_REF_DELETED: // this is for when visibility tracks are deleted
|
|
|
|
case REFMSG_TARGET_DELETED: { // this is for when referenced nodes are deleted
|
|
if (theHold.Holding())
|
|
theHold.Put(new ExprDelTargetRestore(this));
|
|
// get rid of any scalar or vector variable references
|
|
for(i = 0; i < sVars.Count(); i++)
|
|
if(sVars[i].refID >= 0 && refTab[sVars[i].refID].client == hTarg)
|
|
sVars[i].refID = -1;
|
|
for(i = 0; i < vVars.Count(); i++)
|
|
if(vVars[i].refID >= 0 && refTab[vVars[i].refID].client == hTarg)
|
|
vVars[i].refID = -1;
|
|
// then get rid of the reference itself
|
|
for (i = 0; i < refTab.Count(); i++)
|
|
if (refTab[i].client == hTarg)
|
|
refTab[i].client = NULL;
|
|
break;
|
|
}
|
|
}
|
|
return REF_SUCCEED;
|
|
}
|
|
|
|
|
|
class ExprControlRestore : public RestoreObj {
|
|
public:
|
|
ExprControl *ec;
|
|
Interval undo, redo;
|
|
ExprControlRestore(ExprControl *ec) { this->ec=ec; undo=ec->range; }
|
|
void Restore(int isUndo)
|
|
{
|
|
redo = ec->range;
|
|
ec->range = undo;
|
|
ec->NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
|
|
}
|
|
void Redo()
|
|
{
|
|
ec->range = redo;
|
|
ec->NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
|
|
}
|
|
void EndHold() { ec->ClearAFlag(A_HELD); }
|
|
};
|
|
|
|
void ExprControl::Hold()
|
|
{
|
|
if (theHold.Holding() && !TestAFlag(A_HELD)) {
|
|
theHold.Put(new ExprControlRestore(this));
|
|
SetAFlag(A_HELD);
|
|
}
|
|
}
|
|
|
|
void ExprControl::MapKeys( TimeMap *map, DWORD flags )
|
|
{
|
|
Hold();
|
|
range.Set(map->map(range.Start()), map->map(range.End()));
|
|
NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
|
|
}
|
|
|
|
void ExprControl::EditTimeRange(Interval range,DWORD flags)
|
|
{
|
|
if(flags == EDITRANGE_LINKTOKEYS)
|
|
return;
|
|
this->range = range;
|
|
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
|
|
}
|
|
|
|
void ExprControl::BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev )
|
|
{
|
|
}
|
|
|
|
void ExprControl::EndEditParams( IObjParam *ip, ULONG flags,Animatable *next )
|
|
{
|
|
}
|
|
|
|
static void setupSpin(HWND hDlg, int spinID, int editID, float val)
|
|
{
|
|
ISpinnerControl *spin;
|
|
|
|
spin = GetISpinner(GetDlgItem(hDlg, spinID));
|
|
spin->SetLimits( (float)-9e30, (float)9e30, FALSE );
|
|
spin->SetScale( 1.0f );
|
|
spin->LinkToEdit( GetDlgItem(hDlg, editID), EDITTYPE_FLOAT );
|
|
spin->SetValue( val, FALSE );
|
|
ReleaseISpinner( spin );
|
|
}
|
|
|
|
static float getSpinVal(HWND hDlg, int spinID)
|
|
{
|
|
ISpinnerControl *spin = GetISpinner(GetDlgItem(hDlg, spinID));
|
|
float res = spin->GetFVal();
|
|
ReleaseISpinner(spin);
|
|
return res;
|
|
}
|
|
|
|
static BOOL CALLBACK ScalarAsgnDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
ExprControl *ec = (ExprControl *)GetWindowLong(hDlg, GWL_USERDATA);
|
|
|
|
switch (msg) {
|
|
case WM_INITDIALOG:
|
|
SetWindowLong(hDlg, GWL_USERDATA, lParam);
|
|
ec = (ExprControl *)lParam;
|
|
SetWindowText(hDlg, ec->getVarName(SCALAR_VAR, ec->curIndex));
|
|
setupSpin(hDlg, IDC_EXPR_CONST_SPIN, IDC_EXPR_CONST, ec->getScalarValue(ec->curIndex));
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDOK:
|
|
goto done;
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, FALSE);
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
done:
|
|
ec->assignScalarValue(ec->curIndex, getSpinVal(hDlg, IDC_EXPR_CONST_SPIN));
|
|
EndDialog(hDlg, TRUE);
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL CALLBACK VectorAsgnDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
Point3 pt;
|
|
ExprControl *ec = (ExprControl *)GetWindowLong(hDlg, GWL_USERDATA);
|
|
|
|
switch (msg) {
|
|
case WM_INITDIALOG:
|
|
SetWindowLong(hDlg, GWL_USERDATA, lParam);
|
|
ec = (ExprControl *)lParam;
|
|
SetWindowText(hDlg, ec->getVarName(VECTOR_VAR, ec->curIndex));
|
|
pt = ec->getVectorValue(ec->curIndex);
|
|
setupSpin(hDlg, IDC_VEC_X_SPIN, IDC_VEC_X, pt.x);
|
|
setupSpin(hDlg, IDC_VEC_Y_SPIN, IDC_VEC_Y, pt.y);
|
|
setupSpin(hDlg, IDC_VEC_Z_SPIN, IDC_VEC_Z, pt.z);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDOK:
|
|
goto done;
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, FALSE);
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
done:
|
|
pt.x = getSpinVal(hDlg, IDC_VEC_X_SPIN);
|
|
pt.y = getSpinVal(hDlg, IDC_VEC_Y_SPIN);
|
|
pt.z = getSpinVal(hDlg, IDC_VEC_Z_SPIN);
|
|
ec->assignVectorValue(ec->curIndex, pt);
|
|
EndDialog(hDlg, TRUE);
|
|
return FALSE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static int isEmpty(TCHAR *s)
|
|
{
|
|
int c;
|
|
while(c = *s) {
|
|
if(c != ' ' && c != '\t' && c != '\n' && c != '\r')
|
|
return FALSE;
|
|
s++;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static int updateExpr(HWND hDlg, ExprControl *ec)
|
|
{
|
|
TCHAR buf[4096];
|
|
int exprType;
|
|
GetDlgItemText(hDlg, IDC_EXPR_EDIT, buf, 4096);
|
|
if(ec->expr.load(buf)) {
|
|
if(isEmpty(buf)) {
|
|
switch(ec->type) {
|
|
case EXPR_POS_CONTROL_CLASS_ID:
|
|
case EXPR_P3_CONTROL_CLASS_ID:
|
|
_tcscpy(buf,_T("[ 0, 0, 0 ]"));
|
|
break;
|
|
case EXPR_SCALE_CONTROL_CLASS_ID:
|
|
_tcscpy(buf, _T("[ 1, 1, 1 ]"));
|
|
break;
|
|
case EXPR_FLOAT_CONTROL_CLASS_ID:
|
|
_tcscpy(buf, _T("0"));
|
|
break;
|
|
case EXPR_ROT_CONTROL_CLASS_ID:
|
|
_tcscpy(buf, _T("{ [ 0, 0, 0 ], 0 }"));
|
|
break;
|
|
}
|
|
SetDlgItemText(hDlg, IDC_EXPR_EDIT, buf);
|
|
ec->expr.load(buf);
|
|
}
|
|
else {
|
|
MessageBox(hDlg, ec->expr.getProgressStr(), GetString(IDS_DB_EXPR_PARSE_ERROR),
|
|
MB_ICONEXCLAMATION | MB_APPLMODAL | MB_OK);
|
|
return FALSE;
|
|
}
|
|
}
|
|
exprType = ec->expr.getExprType();
|
|
|
|
switch(ec->type) {
|
|
case EXPR_SCALE_CONTROL_CLASS_ID:
|
|
case EXPR_POS_CONTROL_CLASS_ID:
|
|
case EXPR_P3_CONTROL_CLASS_ID:
|
|
if(exprType != VECTOR_EXPR) {
|
|
TSTR s = GetString(IDS_DB_NEED_VECTOR);
|
|
MessageBox(hDlg, s, GetString(IDS_DB_EXPR_PARSE_ERROR),
|
|
MB_ICONEXCLAMATION | MB_APPLMODAL | MB_OK);
|
|
return FALSE;
|
|
}
|
|
break;
|
|
case EXPR_FLOAT_CONTROL_CLASS_ID:
|
|
if(exprType != SCALAR_EXPR) {
|
|
TSTR s = GetString(IDS_DB_NEED_SCALAR);
|
|
MessageBox(hDlg, s, GetString(IDS_DB_EXPR_PARSE_ERROR),
|
|
MB_ICONEXCLAMATION | MB_APPLMODAL | MB_OK);
|
|
return FALSE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
ec->NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
|
|
ec->ip->RedrawViews(ec->ip->GetTime());
|
|
return TRUE;
|
|
}
|
|
|
|
static void updateVarList(HWND hDlg, ExprControl *ec)
|
|
{
|
|
int i, ct;
|
|
|
|
ct = ec->getVarCount(SCALAR_VAR);
|
|
SendDlgItemMessage(hDlg, IDC_SCALAR_LIST, LB_RESETCONTENT, 0, 0);
|
|
for(i = 0; i < ct; i++)
|
|
SendDlgItemMessage(hDlg, IDC_SCALAR_LIST, LB_ADDSTRING, 0, (LPARAM)ec->getVarName(SCALAR_VAR, i));
|
|
|
|
ct = ec->getVarCount(VECTOR_VAR);
|
|
SendDlgItemMessage(hDlg, IDC_VECTOR_LIST, LB_RESETCONTENT, 0, 0);
|
|
for(i = 0; i < ct; i++)
|
|
SendDlgItemMessage(hDlg, IDC_VECTOR_LIST, LB_ADDSTRING, 0, (LPARAM)ec->getVarName(VECTOR_VAR, i));
|
|
}
|
|
|
|
#define XPR _T(".xpr")
|
|
|
|
static void FixExprFileExt(OPENFILENAME &ofn)
|
|
{
|
|
int l = _tcslen(ofn.lpstrFile);
|
|
int e = _tcslen(XPR);
|
|
if (e>l || _tcsicmp(ofn.lpstrFile+l-e, XPR))
|
|
_tcscat(ofn.lpstrFile,XPR);
|
|
}
|
|
|
|
static BOOL BrowseForExprFilename(TCHAR *name, TCHAR *dir, int save)
|
|
{
|
|
int tried = 0;
|
|
FilterList filterList;
|
|
HWND hWnd = GetActiveWindow();
|
|
static int filterIndex = 1;
|
|
OPENFILENAME ofn;
|
|
TCHAR fname[256];
|
|
|
|
_tcscpy(fname, name);
|
|
|
|
filterList.Append( GetString(IDS_DB_XPR_FILES) );
|
|
filterList.Append( _T("*.xpr"));
|
|
|
|
memset(&ofn, 0, sizeof(OPENFILENAME));
|
|
|
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
ofn.hwndOwner = hWnd;
|
|
ofn.hInstance = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE);
|
|
|
|
ofn.nFilterIndex = filterIndex;
|
|
ofn.lpstrFilter = filterList;
|
|
|
|
ofn.lpstrTitle = GetString(save ? IDS_DB_SAVE_EXPR : IDS_DB_LOAD_EXPR);
|
|
ofn.lpstrFile = fname;
|
|
ofn.nMaxFile = sizeof(fname) / sizeof(TCHAR);
|
|
|
|
if(dir && dir[0])
|
|
ofn.lpstrInitialDir = dir;
|
|
else
|
|
ofn.lpstrInitialDir = _T("");
|
|
|
|
ofn.Flags = OFN_HIDEREADONLY | (save ? OFN_OVERWRITEPROMPT : (OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST));
|
|
|
|
if(save) {
|
|
if(!GetSaveFileName(&ofn))
|
|
return FALSE;
|
|
}
|
|
else {
|
|
if(!GetOpenFileName(&ofn))
|
|
return FALSE;
|
|
}
|
|
FixExprFileExt(ofn); // add ".xpr" if absent
|
|
if(dir) {
|
|
_tcsncpy(dir, ofn.lpstrFile, ofn.nFileOffset-1);
|
|
dir[ofn.nFileOffset-1] = _T('\0');
|
|
}
|
|
_tcscpy(name, ofn.lpstrFile);
|
|
return TRUE;
|
|
}
|
|
|
|
static TCHAR exprDir[512];
|
|
|
|
static void SaveExpression(HWND hDlg, ExprControl *ec)
|
|
{
|
|
TCHAR buf[4096];
|
|
int i, ct;
|
|
FILE *fp;
|
|
|
|
if(!exprDir[0])
|
|
_tcscpy(exprDir, ec->ip->GetDir(APP_EXPRESSION_DIR));
|
|
buf[0] = _T('\0');
|
|
if(BrowseForExprFilename(buf, exprDir, TRUE)) {
|
|
if((fp = _tfopen(buf, _T("w"))) == NULL)
|
|
return;
|
|
GetDlgItemText(hDlg, IDC_EXPR_EDIT, buf, 4096);
|
|
_ftprintf(fp, _T("%s\n"), buf);
|
|
GetDlgItemText(hDlg, IDC_DESCRIPTION, buf, 4096);
|
|
if(buf[0]) {
|
|
TCHAR line[1024];
|
|
TCHAR *cp = buf;
|
|
int i;
|
|
for(i = 0; *cp; i++, cp++) {
|
|
line[i] = *cp;
|
|
if(*cp == _T('\r')) {
|
|
line[i] = 0;
|
|
_ftprintf(fp, _T("d: %s\n"), line);
|
|
line[0] = 0;
|
|
cp++; // skip over linefeed
|
|
i = -1; // reset i
|
|
}
|
|
}
|
|
if(line[0]) {
|
|
line[i] = 0;
|
|
_ftprintf(fp, _T("d: %s\n"), line);
|
|
}
|
|
}
|
|
ct = ec->getVarCount(SCALAR_VAR);
|
|
for(i = 0; i < ct; i++)
|
|
_ftprintf(fp, _T("s: %s:%d\n"), ec->getVarName(SCALAR_VAR, i), ec->sVars[i].offset);
|
|
ct = ec->getVarCount(VECTOR_VAR);
|
|
for(i = 0; i < ct; i++)
|
|
_ftprintf(fp, _T("v: %s:%d %d\n"), ec->getVarName(VECTOR_VAR, i), ec->vVars[i].offset);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
static void LoadExpression(HWND hDlg, ExprControl *ec)
|
|
{
|
|
TCHAR buf[4096];
|
|
TCHAR line[1024];
|
|
TCHAR desc[4096];
|
|
int slot, i, ct;
|
|
int type;
|
|
int offset;
|
|
TCHAR *cp;
|
|
FILE *fp;
|
|
|
|
if(!exprDir[0])
|
|
_tcscpy(exprDir, ec->ip->GetDir(APP_EXPRESSION_DIR));
|
|
buf[0] = _T('\0');
|
|
if(BrowseForExprFilename(buf, exprDir, FALSE)) {
|
|
if((fp = _tfopen(buf, _T("r"))) == NULL)
|
|
return;
|
|
desc[0] = _T('\0');
|
|
SetDlgItemText(hDlg, IDC_DESCRIPTION, _T("")); // empty-out description
|
|
ct = ec->sVars.Count(); // empty-out vars
|
|
for(i = 0; i < ct; i++) { // leave pre-defined scalars
|
|
ec->expr.deleteVar(ec->sVars[0].name);
|
|
delete ec->sVars[0].name;
|
|
ec->sVars.Delete(0, 1);
|
|
}
|
|
ct = ec->vVars.Count();
|
|
for(i = 0; i < ct; i++) {
|
|
ec->expr.deleteVar(ec->vVars[0].name);
|
|
delete ec->vVars[0].name;
|
|
ec->vVars.Delete(0, 1);
|
|
}
|
|
buf[0] = _T('\0');
|
|
while(_fgetts(line, 1024, fp) && (line[1] != _T(':')))
|
|
_tcscat(buf, line);
|
|
if(buf[_tcslen(buf) - 1] == _T('\n'))
|
|
buf[_tcslen(buf) - 1] = _T('\0');
|
|
SetDlgItemText(hDlg, IDC_EXPR_EDIT, buf);
|
|
if(line[1] == _T(':')) {
|
|
do {
|
|
if(line[_tcslen(line) - 1] == _T('\n'))
|
|
line[_tcslen(line) - 1] = _T('\0');
|
|
switch(line[0]) {
|
|
case _T('d'):
|
|
if(desc[0])
|
|
_tcscat(desc, _T("\r\n"));
|
|
_tcscat(desc, line+3);
|
|
break;
|
|
case _T('s'):
|
|
case _T('v'):
|
|
type = line[0] == _T('s') ? SCALAR_VAR : VECTOR_VAR;
|
|
offset = 0;
|
|
cp = line+3;
|
|
while(cp[offset] != _T('\n') && cp[offset] != ':')
|
|
offset++;
|
|
cp[offset++] = _T('\0');
|
|
ec->updRegCt(slot = ec->expr.defVar(type, cp), type);
|
|
if(slot >= 0)
|
|
ec->dfnVar(type, cp, slot, _ttoi(cp+offset));
|
|
break;
|
|
}
|
|
} while(_fgetts(line, 1024, fp));
|
|
}
|
|
SetDlgItemText(hDlg, IDC_DESCRIPTION, desc);
|
|
updateVarList(hDlg, ec);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL invalidName(TCHAR *buf)
|
|
{
|
|
if(buf[0] >= '0' && buf[0] <= '9')
|
|
return TRUE;
|
|
TCHAR *cp = buf;
|
|
while(*cp) {
|
|
if(!_istalnum(*cp))
|
|
return TRUE;
|
|
cp++;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static int fnListIDs[] = {
|
|
IDS_DB_FN_SIN,
|
|
IDS_DB_FN_NOISE,
|
|
IDS_DB_FN_IF,
|
|
IDS_DB_FN_VIF,
|
|
IDS_DB_FN_MIN,
|
|
IDS_DB_FN_MAX,
|
|
IDS_DB_FN_POW,
|
|
IDS_DB_FN_MOD,
|
|
IDS_DB_FN_DEGTORAD,
|
|
IDS_DB_FN_RADTODEG,
|
|
IDS_DB_FN_COS,
|
|
IDS_DB_FN_TAN,
|
|
IDS_DB_FN_ASIN,
|
|
IDS_DB_FN_ACOS,
|
|
IDS_DB_FN_ATAN,
|
|
IDS_DB_FN_SINH,
|
|
IDS_DB_FN_COSH,
|
|
IDS_DB_FN_TANH,
|
|
IDS_DB_FN_LN,
|
|
IDS_DB_FN_LOG,
|
|
IDS_DB_FN_EXP,
|
|
IDS_DB_FN_SQRT,
|
|
IDS_DB_FN_ABS,
|
|
IDS_DB_FN_CEIL,
|
|
IDS_DB_FN_FLOOR,
|
|
IDS_DB_FN_COMP,
|
|
IDS_DB_FN_UNIT,
|
|
IDS_DB_FN_LENGTH,
|
|
IDS_DB_FN_PI,
|
|
IDS_DB_FN_E,
|
|
IDS_DB_FN_TPS
|
|
};
|
|
|
|
BOOL CALLBACK functionListProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int i = 57;
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));
|
|
SendDlgItemMessage(hDlg, IDC_FUNC_LIST, LB_RESETCONTENT, 0, 0L);
|
|
SendDlgItemMessage(hDlg, IDC_FUNC_LIST, LB_SETTABSTOPS, 1, (LPARAM)&i);
|
|
for(i = 0; i < sizeof(fnListIDs) / sizeof(int); i++)
|
|
SendDlgItemMessage(hDlg, IDC_FUNC_LIST, LB_ADDSTRING, 0, (LPARAM)GetString(fnListIDs[i]));
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch(LOWORD(wParam)) {
|
|
case IDOK:
|
|
goto done;
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, FALSE);
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
done:
|
|
EndDialog(hDlg, TRUE);
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static BOOL CALLBACK ExprParamsWndProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int type, slot, i, ct;
|
|
Point3 pt;
|
|
TCHAR buf[4096], buf2[100];
|
|
TrackViewPick res;
|
|
ExprControl *ec = (ExprControl *)GetWindowLong(hDlg, GWL_USERDATA);
|
|
ISpinnerControl *spin;
|
|
|
|
switch (msg) {
|
|
case WM_INITDIALOG:
|
|
SetWindowLong(hDlg, GWL_USERDATA, lParam);
|
|
ec = (ExprControl *)lParam;
|
|
if (ec->winX!=-1 && ec->winY!=-1)
|
|
SetWindowPos(hDlg,NULL,ec->winX, ec->winY, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
|
|
ec->hDlg = hDlg;
|
|
spin = GetISpinner(GetDlgItem(hDlg, IDC_OFFSET_SPIN));
|
|
spin->SetLimits( -1000000, 1000000, FALSE );
|
|
spin->SetScale( 1.0f );
|
|
spin->LinkToEdit( GetDlgItem(hDlg, IDC_OFFSET), EDITTYPE_INT );
|
|
spin->SetValue( 0, FALSE );
|
|
ReleaseISpinner( spin );
|
|
SendDlgItemMessage(hDlg, IDC_EXPR_EDIT, WM_SETFONT, (WPARAM)ec->hFixedFont, TRUE);
|
|
CheckRadioButton(hDlg, IDC_SCALAR_RB, IDC_VECTOR_RB, IDC_SCALAR_RB);
|
|
updateVarList(hDlg, ec);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_ASGN_CONST), 0);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_ASGN_CNTRL), 0);
|
|
SetDlgItemText(hDlg, IDC_EXPR_EDIT, ec->expr.getExprStr());
|
|
SetDlgItemText(hDlg, IDC_DESCRIPTION, ec->desc);
|
|
SetFocus(GetDlgItem(hDlg, IDC_EXPR_EDIT));
|
|
GetDlgItemText(hDlg, IDC_EXPLAIN_NOTATION, buf, sizeof(buf));
|
|
if(buf[0]) {
|
|
WINDOWPLACEMENT wp;
|
|
wp.length = sizeof(WINDOWPLACEMENT);
|
|
GetWindowPlacement(GetDlgItem(hDlg, IDC_EXPR_EDIT), &wp);
|
|
wp.rcNormalPosition.bottom -= 12;
|
|
SetWindowPlacement(GetDlgItem(hDlg, IDC_EXPR_EDIT), &wp);
|
|
ShowWindow(GetDlgItem(hDlg, IDC_EXPLAIN_NOTATION), SW_SHOW);
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
case CC_SPINNER_CHANGE:
|
|
switch ( LOWORD(wParam) ) {
|
|
case IDC_OFFSET_SPIN:
|
|
GetDlgItemText(hDlg, IDC_VAR_NAME, buf, 256);
|
|
if(buf[0]) {
|
|
ct = ec->sVars.Count();
|
|
for(i = 0; i < ct; i++) {
|
|
if(_tcscmp(buf, ec->sVars[i].name) == 0) {
|
|
spin = GetISpinner(GetDlgItem(hDlg, IDC_OFFSET_SPIN));
|
|
ec->sVars[i].offset = spin->GetIVal();
|
|
ReleaseISpinner(spin);
|
|
break;
|
|
}
|
|
}
|
|
if(i < ct)
|
|
break;
|
|
ct = ec->vVars.Count();
|
|
for(i = 0; i < ct; i++) {
|
|
if(_tcscmp(buf, ec->vVars[i].name) == 0) {
|
|
spin = GetISpinner(GetDlgItem(hDlg, IDC_OFFSET_SPIN));
|
|
ec->vVars[i].offset = spin->GetIVal();
|
|
ReleaseISpinner(spin);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDC_EXPR_DEBUG:
|
|
if(ec->edbg)
|
|
ShowWindow(ec->edbg->hWnd, SW_SHOWNORMAL);
|
|
else
|
|
ec->edbg = new ExprDebug(hDlg, ec);
|
|
updateExpr(hDlg, ec);
|
|
ec->edbg->Update();
|
|
break;
|
|
case IDC_FUNCTIONS:
|
|
DialogBox(hInstance, MAKEINTRESOURCE(IDD_FUNC_LIST), hDlg, functionListProc);
|
|
break;
|
|
case IDC_CREATE_VAR:
|
|
GetDlgItemText(hDlg, IDC_VAR_NAME, buf, 256);
|
|
if(buf[0]) {
|
|
if(invalidName(buf)) {
|
|
_tcscpy(buf2, GetString(IDS_DB_BAD_NAME));
|
|
MessageBox(hDlg, buf2, GetString(IDS_DB_CANT_CREATE_VAR),
|
|
MB_ICONEXCLAMATION | MB_APPLMODAL | MB_OK);
|
|
break;
|
|
}
|
|
type = IsDlgButtonChecked(hDlg, IDC_SCALAR_RB) ? SCALAR_VAR : VECTOR_VAR;
|
|
ec->updRegCt(slot = ec->expr.defVar(type, buf), type);
|
|
spin = GetISpinner(GetDlgItem(hDlg, IDC_OFFSET_SPIN));
|
|
i = spin->GetIVal();
|
|
ReleaseISpinner(spin);
|
|
if(slot >= 0)
|
|
ec->dfnVar(type, buf, slot, i);
|
|
else {
|
|
_tcscpy(buf2, GetString(IDS_DB_DUPNAME));
|
|
MessageBox(hDlg, buf2, GetString(IDS_DB_CANT_CREATE_VAR),
|
|
MB_ICONEXCLAMATION | MB_APPLMODAL | MB_OK);
|
|
}
|
|
}
|
|
updateVarList(hDlg, ec);
|
|
slot = type == SCALAR_VAR ? IDC_SCALAR_LIST : IDC_VECTOR_LIST;
|
|
ct = SendDlgItemMessage(hDlg, slot, LB_GETCOUNT, 0, 0);
|
|
for(i = 0; i < ct; i++) {
|
|
SendDlgItemMessage(hDlg, slot, LB_GETTEXT, i, (LPARAM)buf2);
|
|
if(_tcscmp(buf, buf2) == 0) {
|
|
SendDlgItemMessage(hDlg, slot, LB_SETCURSEL, i, 0);
|
|
break;
|
|
}
|
|
}
|
|
SendMessage(hDlg, WM_COMMAND, slot | (LBN_SELCHANGE << 16), 0);
|
|
break;
|
|
case IDC_DELETE_VAR:
|
|
GetDlgItemText(hDlg, IDC_VAR_NAME, buf, 256);
|
|
if(buf[0]) {
|
|
ct = ec->sVars.Count();
|
|
for(i = 0; i < ct; i++) {
|
|
if(_tcscmp(buf, ec->sVars[i].name) == 0) {
|
|
ec->expr.deleteVar(buf);
|
|
delete ec->sVars[i].name;
|
|
ec->sVars.Delete(i, 1);
|
|
SetDlgItemText(hDlg, IDC_VAR_NAME, _T(""));
|
|
break;
|
|
}
|
|
}
|
|
if(i < ct) {
|
|
updateVarList(hDlg, ec);
|
|
break;
|
|
}
|
|
|
|
ct = ec->vVars.Count();
|
|
for(i = 0; i < ct; i++) {
|
|
if(_tcscmp(buf, ec->vVars[i].name) == 0) {
|
|
ec->expr.deleteVar(buf);
|
|
delete ec->vVars[i].name;
|
|
ec->vVars.Delete(i, 1);
|
|
SetDlgItemText(hDlg, IDC_VAR_NAME, _T(""));
|
|
break;
|
|
}
|
|
}
|
|
if(i < ct) {
|
|
updateVarList(hDlg, ec);
|
|
break;
|
|
}
|
|
_stprintf(buf2, GetString(IDS_DB_CANTDELETE), buf);
|
|
MessageBox(hDlg, buf2, GetString(IDS_DB_EXPRCNTL),
|
|
MB_ICONEXCLAMATION | MB_APPLMODAL | MB_OK);
|
|
}
|
|
else {
|
|
_tcscpy(buf2, GetString(IDS_DB_NOTHINGDEL));
|
|
MessageBox(hDlg, buf2, GetString(IDS_DB_EXPRCNTL),
|
|
MB_ICONEXCLAMATION | MB_APPLMODAL | MB_OK);
|
|
}
|
|
break;
|
|
case IDC_EXPR_EVAL:
|
|
updateExpr(hDlg, ec);
|
|
if(ec->edbg)
|
|
ec->edbg->Update();
|
|
break;
|
|
case IDC_VAR_NAME:
|
|
case IDC_EXPR_EDIT:
|
|
case IDC_DESCRIPTION:
|
|
if(HIWORD(wParam) == EN_SETFOCUS)
|
|
DisableAccelerators();
|
|
else if(HIWORD(wParam) == EN_KILLFOCUS) {
|
|
EnableAccelerators();
|
|
if (LOWORD(wParam) == IDC_DESCRIPTION) {
|
|
GetDlgItemText(hDlg, IDC_DESCRIPTION, buf, 4096);
|
|
ec->desc = buf;
|
|
}
|
|
}
|
|
break;
|
|
case IDC_ASGN_CNTRL:
|
|
ct = SendDlgItemMessage(hDlg, IDC_SCALAR_LIST, LB_GETCOUNT, 0, 0);
|
|
for(i = 0; i < ct; i++)
|
|
if(SendDlgItemMessage(hDlg, IDC_SCALAR_LIST, LB_GETSEL, i, 0))
|
|
break;
|
|
if(i < ct) {
|
|
SendDlgItemMessage(hDlg, IDC_SCALAR_LIST, LB_GETTEXT, i, (LPARAM)buf);
|
|
ct = ec->getVarCount(SCALAR_VAR);
|
|
for(i = 0; i < ct; i++) {
|
|
if(_tcscmp(buf, ec->getVarName(SCALAR_VAR, i)) == 0)
|
|
break;
|
|
}
|
|
FloatFilter ff;
|
|
if(ec->ip->TrackViewPickDlg(hDlg, &res, &ff)) {
|
|
assert(res.anim->SuperClassID() == CTRL_FLOAT_CLASS_ID);
|
|
ec->assignController(SCALAR_VAR, i, res.client, res.subNum);
|
|
SendMessage(hDlg, WM_COMMAND, IDC_SCALAR_LIST | (LBN_SELCHANGE << 16), 0);
|
|
}
|
|
break;
|
|
}
|
|
ct = SendDlgItemMessage(hDlg, IDC_VECTOR_LIST, LB_GETCOUNT, 0, 0);
|
|
for(i = 0; i < ct; i++)
|
|
if(SendDlgItemMessage(hDlg, IDC_VECTOR_LIST, LB_GETSEL, i, 0))
|
|
break;
|
|
if(i < ct) {
|
|
slot = IDC_VECTOR_LIST;
|
|
SendDlgItemMessage(hDlg, IDC_VECTOR_LIST, LB_GETTEXT, i, (LPARAM)buf);
|
|
ct = ec->getVarCount(VECTOR_VAR);
|
|
for(i = 0; i < ct; i++) {
|
|
if(_tcscmp(buf, ec->getVarName(VECTOR_VAR, i)) == 0)
|
|
break;
|
|
}
|
|
VectorFilter vf;
|
|
if(ec->ip->TrackViewPickDlg(hDlg, &res, &vf)) {
|
|
assert(res.anim->SuperClassID() == CTRL_POSITION_CLASS_ID ||
|
|
res.anim->SuperClassID() == CTRL_POINT3_CLASS_ID ||
|
|
res.anim->SuperClassID() == BASENODE_CLASS_ID);
|
|
|
|
if (res.anim->SuperClassID()==BASENODE_CLASS_ID) {
|
|
ec->assignController(VECTOR_VAR, i, res.anim, -1);
|
|
} else {
|
|
ec->assignController(VECTOR_VAR, i, res.client, res.subNum);
|
|
}
|
|
SendMessage(hDlg, WM_COMMAND, IDC_VECTOR_LIST | (LBN_SELCHANGE << 16), 0);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case IDC_ASGN_CONST:
|
|
ct = SendDlgItemMessage(hDlg, IDC_SCALAR_LIST, LB_GETCOUNT, 0, 0);
|
|
for(i = 0; i < ct; i++)
|
|
if(SendDlgItemMessage(hDlg, IDC_SCALAR_LIST, LB_GETSEL, i, 0))
|
|
break;
|
|
if(i < ct) {
|
|
SendDlgItemMessage(hDlg, IDC_SCALAR_LIST, LB_GETTEXT, i, (LPARAM)buf);
|
|
ct = ec->getVarCount(SCALAR_VAR);
|
|
for(i = 0; i < ct; i++) {
|
|
if(_tcscmp(buf, ec->getVarName(SCALAR_VAR, i)) == 0)
|
|
break;
|
|
}
|
|
ec->curIndex = i;
|
|
DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_SCALAR_ASGN),
|
|
hDlg, ScalarAsgnDlgProc, (LPARAM)ec);
|
|
SendMessage(hDlg, WM_COMMAND, IDC_SCALAR_LIST | (LBN_SELCHANGE << 16), 0);
|
|
break;
|
|
}
|
|
ct = SendDlgItemMessage(hDlg, IDC_VECTOR_LIST, LB_GETCOUNT, 0, 0);
|
|
for(i = 0; i < ct; i++)
|
|
if(SendDlgItemMessage(hDlg, IDC_VECTOR_LIST, LB_GETSEL, i, 0))
|
|
break;
|
|
if(i < ct) {
|
|
slot = IDC_VECTOR_LIST;
|
|
SendDlgItemMessage(hDlg, IDC_VECTOR_LIST, LB_GETTEXT, i, (LPARAM)buf);
|
|
ct = ec->getVarCount(VECTOR_VAR);
|
|
for(i = 0; i < ct; i++) {
|
|
if(_tcscmp(buf, ec->getVarName(VECTOR_VAR, i)) == 0)
|
|
break;
|
|
}
|
|
ec->curIndex = i;
|
|
DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_VECTOR_ASGN),
|
|
hDlg, VectorAsgnDlgProc, (LPARAM)ec);
|
|
SendMessage(hDlg, WM_COMMAND, IDC_VECTOR_LIST | (LBN_SELCHANGE << 16), 0);
|
|
break;
|
|
}
|
|
break;
|
|
case IDC_SCALAR_LIST:
|
|
if(HIWORD(wParam) == LBN_SELCHANGE) {
|
|
SendDlgItemMessage(hDlg, IDC_VECTOR_LIST, LB_SETCURSEL, (WPARAM)-1, (LPARAM)0);
|
|
ct = SendDlgItemMessage(hDlg, IDC_SCALAR_LIST, LB_GETCOUNT, 0, 0);
|
|
for(i = 0; i < ct; i++)
|
|
if(SendDlgItemMessage(hDlg, IDC_SCALAR_LIST, LB_GETSEL, i, 0))
|
|
break;
|
|
if(i < ct) {
|
|
SendDlgItemMessage(hDlg, IDC_SCALAR_LIST, LB_GETTEXT, i, (LPARAM)buf);
|
|
ct = ec->getVarCount(SCALAR_VAR);
|
|
for(i = 0; i < ct; i++)
|
|
if(_tcscmp(buf, ec->getVarName(SCALAR_VAR, i)) == 0)
|
|
break;
|
|
SetDlgItemText(hDlg, IDC_VAR_NAME, buf);
|
|
CheckRadioButton(hDlg, IDC_SCALAR_RB, IDC_VECTOR_RB, IDC_SCALAR_RB);
|
|
spin = GetISpinner(GetDlgItem(hDlg, IDC_OFFSET_SPIN));
|
|
spin->SetValue(ec->sVars[i].offset, FALSE);
|
|
ReleaseISpinner(spin);
|
|
if(ec->sVars[i].refID < 0) {
|
|
_stprintf(buf, "Constant: %g", ec->getScalarValue(i));
|
|
UglyPatch(buf);
|
|
}
|
|
else {
|
|
slot = ec->sVars[i].refID;
|
|
#if 0 // displays unique controller id
|
|
_stprintf(buf, "Controller: %s {%08x}:%d",
|
|
ec->refTab[slot].client->SubAnimName(ec->sVars[i].subNum),
|
|
ec->refTab[slot].client, ec->sVars[i].subNum);
|
|
#else // displays more user-friendly (but possibly wrong) text
|
|
TSTR nname;
|
|
ec->refTab[slot].client->NotifyDependents(FOREVER,(PartID)&nname,REFMSG_GET_NODE_NAME);
|
|
TSTR pname;
|
|
if (nname.Length())
|
|
pname = nname + TSTR(_T("\\")) + ec->refTab[slot].client->SubAnimName(ec->sVars[i].subNum);
|
|
else
|
|
pname = ec->refTab[slot].client->SubAnimName(ec->sVars[i].subNum);
|
|
_tcscpy(buf, pname);
|
|
#endif
|
|
}
|
|
SetDlgItemText(hDlg, IDC_CUR_ASGN, buf);
|
|
}
|
|
EnableWindow(GetDlgItem(hDlg, IDC_ASGN_CONST), 1);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_ASGN_CNTRL), 1);
|
|
}
|
|
break;
|
|
case IDC_VECTOR_LIST:
|
|
if(HIWORD(wParam) == LBN_SELCHANGE) {
|
|
SendDlgItemMessage(hDlg, IDC_SCALAR_LIST, LB_SETCURSEL, (WPARAM)-1, (LPARAM)0);
|
|
ct = SendDlgItemMessage(hDlg, IDC_VECTOR_LIST, LB_GETCOUNT, 0, 0);
|
|
for(i = 0; i < ct; i++)
|
|
if(SendDlgItemMessage(hDlg, IDC_VECTOR_LIST, LB_GETSEL, i, 0))
|
|
break;
|
|
if(i < ct) {
|
|
SendDlgItemMessage(hDlg, IDC_VECTOR_LIST, LB_GETTEXT, i, (LPARAM)buf);
|
|
ct = ec->getVarCount(VECTOR_VAR);
|
|
for(i = 0; i < ct; i++)
|
|
if(_tcscmp(buf, ec->getVarName(VECTOR_VAR, i)) == 0)
|
|
break;
|
|
SetDlgItemText(hDlg, IDC_VAR_NAME, buf);
|
|
CheckRadioButton(hDlg, IDC_SCALAR_RB, IDC_VECTOR_RB, IDC_VECTOR_RB);
|
|
spin = GetISpinner(GetDlgItem(hDlg, IDC_OFFSET_SPIN));
|
|
spin->SetValue(ec->vVars[i].offset, FALSE);
|
|
ReleaseISpinner(spin);
|
|
if(ec->vVars[i].refID < 0 || !ec->refTab[ec->vVars[i].refID].client) {
|
|
pt = ec->getVectorValue(i);
|
|
_stprintf(buf, "Constant: [%g; %g; %g]", pt.x, pt.y, pt.z);
|
|
UglyPatch(buf);
|
|
}
|
|
else {
|
|
slot = ec->vVars[i].refID;
|
|
#if 0 // displays unique controller id
|
|
_stprintf(buf, "Controller: %s {%08x}:%d",
|
|
ec->refTab[slot].client->SubAnimName(ec->vVars[i].subNum),
|
|
ec->refTab[slot].client, ec->vVars[i].subNum);
|
|
#else // displays more user-friendly (but possibly wrong) text
|
|
TSTR pname;
|
|
if(ec->vVars[i].subNum == -1) // special case: we're referencing a node
|
|
pname = ((INode *)ec->refTab[slot].client)->GetName();
|
|
else {
|
|
TSTR nname;
|
|
ec->refTab[slot].client->NotifyDependents(FOREVER,(PartID)&nname,REFMSG_GET_NODE_NAME);
|
|
if (nname.Length())
|
|
pname = nname + TSTR(_T("\\")) + ec->refTab[slot].client->SubAnimName(ec->vVars[i].subNum);
|
|
else
|
|
pname = ec->refTab[slot].client->SubAnimName(ec->vVars[i].subNum);
|
|
}
|
|
_tcscpy(buf, pname);
|
|
#endif
|
|
}
|
|
SetDlgItemText(hDlg, IDC_CUR_ASGN, buf);
|
|
}
|
|
EnableWindow(GetDlgItem(hDlg, IDC_ASGN_CONST), 1);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_ASGN_CNTRL), 1);
|
|
}
|
|
break;
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
if(updateExpr(hDlg, ec))
|
|
DestroyWindow(hDlg);
|
|
break;
|
|
|
|
case IDC_SAVE:
|
|
SaveExpression(hDlg, ec);
|
|
break;
|
|
|
|
case IDC_LOAD:
|
|
LoadExpression(hDlg, ec);
|
|
// updateExpr(hDlg, ec);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY: {
|
|
Rect rect;
|
|
GetWindowRect(hDlg,&rect);
|
|
ec->winX = rect.left;
|
|
ec->winY = rect.top;
|
|
}
|
|
ec->hParams = NULL;
|
|
break;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
void ExprControl::EditTrackParams(
|
|
TimeValue t, // The horizontal position of where the user right clicked.
|
|
ParamDimensionBase *dim,
|
|
TCHAR *pname,
|
|
HWND hParent,
|
|
IObjParam *ip,
|
|
DWORD flags)
|
|
{
|
|
if (!hParams) {
|
|
this->ip = ip;
|
|
hParams = CreateDialogParam(
|
|
hInstance,
|
|
MAKEINTRESOURCE(IDD_EXPRPARAMS),
|
|
hParent,
|
|
ExprParamsWndProc,
|
|
(LPARAM)this);
|
|
TSTR title = TSTR(GetString(IDS_RB_EXPRESSIONCONTROLTITLE)) + TSTR(pname);
|
|
SetWindowText(hParams,title);
|
|
}
|
|
else {
|
|
SetActiveWindow(hParams);
|
|
}
|
|
}
|
|
|
|
#define EXPR_STR_CHUNK 0x5000
|
|
#define EXPR_RANGE_CHUNK 0x5001
|
|
#define EXPR_REFTAB_SIZE 0x5002
|
|
#define EXPR_SVAR_TABSIZE 0x5003
|
|
#define EXPR_VVAR_TABSIZE 0x5005
|
|
#define EXPR_VAR_NAME 0x5006
|
|
#define EXPR_VAR_REFID 0x5007
|
|
#define EXPR_VAR_FLOAT 0x5008
|
|
#define EXPR_VAR_POINT3 0x5009
|
|
#define EXPR_VAR_SUBNUM 0x500a
|
|
#define EXPR_DESCRIPTION 0x500b
|
|
#define EXPR_REFTAB_REFCT 0x500c
|
|
#define EXPR_VAR_OFFSET 0x500d
|
|
#define EXPR_SVAR_ENTRY0 0x6000
|
|
#define EXPR_SVAR_ENTRYN 0x6fff
|
|
#define EXPR_VVAR_ENTRY0 0x7000
|
|
#define EXPR_VVAR_ENTRYN 0x7fff
|
|
|
|
IOResult ExprControl::Save(ISave *isave)
|
|
{
|
|
ULONG nb;
|
|
int i, ct, intVar;
|
|
|
|
Control::Save(isave); // RB: this will handle saving ORTs
|
|
|
|
if(desc.Length()) {
|
|
isave->BeginChunk(EXPR_DESCRIPTION);
|
|
isave->WriteCString(desc);
|
|
isave->EndChunk();
|
|
}
|
|
|
|
isave->BeginChunk(EXPR_RANGE_CHUNK);
|
|
isave->Write(&range, sizeof(range), &nb);
|
|
isave->EndChunk();
|
|
|
|
isave->BeginChunk(EXPR_REFTAB_SIZE);
|
|
intVar = refTab.Count();
|
|
isave->Write(&intVar, sizeof(intVar), &nb);
|
|
isave->EndChunk();
|
|
|
|
ct = refTab.Count();
|
|
for(i = 0; i < ct; i++) {
|
|
isave->BeginChunk(EXPR_REFTAB_REFCT);
|
|
isave->Write(&i, sizeof(int), &nb);
|
|
isave->Write(&refTab[i].refCt, sizeof(int), &nb);
|
|
isave->EndChunk();
|
|
}
|
|
|
|
|
|
isave->BeginChunk(EXPR_SVAR_TABSIZE);
|
|
intVar = sVars.Count();
|
|
isave->Write(&intVar, sizeof(intVar), &nb);
|
|
isave->EndChunk();
|
|
|
|
ct = sVars.Count();
|
|
for(i = 0; i < ct; i++) {
|
|
isave->BeginChunk(EXPR_SVAR_ENTRY0+i);
|
|
isave->BeginChunk(EXPR_VAR_NAME);
|
|
isave->WriteCString(sVars[i].name);
|
|
isave->EndChunk();
|
|
isave->BeginChunk(EXPR_VAR_REFID);
|
|
isave->Write(&sVars[i].refID, sizeof(int), &nb);
|
|
isave->EndChunk();
|
|
isave->BeginChunk(EXPR_VAR_FLOAT);
|
|
isave->Write(&sVars[i].val, sizeof(float), &nb);
|
|
isave->EndChunk();
|
|
isave->BeginChunk(EXPR_VAR_SUBNUM);
|
|
isave->Write(&sVars[i].subNum, sizeof(int), &nb);
|
|
isave->EndChunk();
|
|
isave->BeginChunk(EXPR_VAR_OFFSET);
|
|
isave->Write(&sVars[i].offset, sizeof(int), &nb);
|
|
isave->EndChunk();
|
|
isave->EndChunk();
|
|
}
|
|
|
|
isave->BeginChunk(EXPR_VVAR_TABSIZE);
|
|
intVar = vVars.Count();
|
|
isave->Write(&intVar, sizeof(intVar), &nb);
|
|
isave->EndChunk();
|
|
|
|
ct = vVars.Count();
|
|
for(i = 0; i < ct; i++) {
|
|
isave->BeginChunk(EXPR_VVAR_ENTRY0+i);
|
|
isave->BeginChunk(EXPR_VAR_NAME);
|
|
isave->WriteCString(vVars[i].name);
|
|
isave->EndChunk();
|
|
isave->BeginChunk(EXPR_VAR_REFID);
|
|
isave->Write(&vVars[i].refID, sizeof(int), &nb);
|
|
isave->EndChunk();
|
|
isave->BeginChunk(EXPR_VAR_POINT3);
|
|
isave->Write(&vVars[i].val, sizeof(Point3), &nb);
|
|
isave->EndChunk();
|
|
isave->BeginChunk(EXPR_VAR_SUBNUM);
|
|
isave->Write(&vVars[i].subNum, sizeof(int), &nb);
|
|
isave->EndChunk();
|
|
isave->BeginChunk(EXPR_VAR_OFFSET);
|
|
isave->Write(&vVars[i].offset, sizeof(int), &nb);
|
|
isave->EndChunk();
|
|
isave->EndChunk();
|
|
}
|
|
|
|
isave->BeginChunk(EXPR_STR_CHUNK);
|
|
isave->WriteCString(expr.getExprStr());
|
|
isave->EndChunk();
|
|
|
|
return IO_OK;
|
|
}
|
|
|
|
IOResult ExprControl::Load(ILoad *iload)
|
|
{
|
|
ULONG nb;
|
|
TCHAR *cp;
|
|
int id, i, varIndex, intVar;
|
|
IOResult res;
|
|
VarRef dummyVarRef;
|
|
|
|
Control::Load(iload); // RB: this will handle loading ORTs
|
|
|
|
while (IO_OK==(res=iload->OpenChunk())) {
|
|
switch (id = iload->CurChunkID()) {
|
|
case EXPR_STR_CHUNK:
|
|
iload->ReadCStringChunk(&cp);
|
|
expr.load(cp);
|
|
break;
|
|
case EXPR_DESCRIPTION:
|
|
iload->ReadCStringChunk(&cp);
|
|
desc = cp;
|
|
break;
|
|
case EXPR_RANGE_CHUNK:
|
|
iload->Read(&range, sizeof(range), &nb);
|
|
break;
|
|
case EXPR_REFTAB_SIZE:
|
|
iload->Read(&intVar, sizeof(intVar), &nb);
|
|
refTab.SetCount(intVar);
|
|
for(i = 0; i < intVar; i++) {
|
|
refTab[i].refCt = 0;
|
|
refTab[i].client = NULL;
|
|
}
|
|
break;
|
|
case EXPR_REFTAB_REFCT:
|
|
iload->Read(&intVar, sizeof(int), &nb);
|
|
if(intVar < refTab.Count()) // this should always be true!!!!
|
|
iload->Read(&refTab[intVar].refCt, sizeof(int), &nb);
|
|
break;
|
|
case EXPR_SVAR_TABSIZE:
|
|
iload->Read(&intVar, sizeof(intVar), &nb);
|
|
sVars.SetCount(intVar);
|
|
for(i = 0; i < intVar; i++)
|
|
memset(&sVars[i], 0, sizeof(SVar));
|
|
break;
|
|
case EXPR_VVAR_TABSIZE:
|
|
iload->Read(&intVar, sizeof(intVar), &nb);
|
|
vVars.SetCount(intVar);
|
|
for(i = 0; i < intVar; i++)
|
|
memset(&vVars[i], 0, sizeof(VVar));
|
|
break;
|
|
}
|
|
if(id >= EXPR_SVAR_ENTRY0 && id <= EXPR_SVAR_ENTRYN) {
|
|
varIndex = id - EXPR_SVAR_ENTRY0;
|
|
assert(varIndex < sVars.Count());
|
|
while (IO_OK == iload->OpenChunk()) {
|
|
switch (iload->CurChunkID()) {
|
|
case EXPR_VAR_NAME:
|
|
iload->ReadCStringChunk(&cp);
|
|
sVars[varIndex].name = cp;
|
|
break;
|
|
case EXPR_VAR_REFID:
|
|
iload->Read(&sVars[varIndex].refID, sizeof(int), &nb);
|
|
break;
|
|
case EXPR_VAR_SUBNUM:
|
|
iload->Read(&sVars[varIndex].subNum, sizeof(int), &nb);
|
|
break;
|
|
case EXPR_VAR_OFFSET:
|
|
iload->Read(&sVars[varIndex].offset, sizeof(int), &nb);
|
|
break;
|
|
case EXPR_VAR_FLOAT:
|
|
iload->Read(&sVars[varIndex].val, sizeof(float), &nb);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
}
|
|
updRegCt(intVar = expr.defVar(SCALAR_VAR, sVars[varIndex].name), SCALAR_VAR);
|
|
sVars[varIndex].regNum = intVar;
|
|
}
|
|
else if(id >= EXPR_VVAR_ENTRY0 && id <= EXPR_VVAR_ENTRYN) {
|
|
varIndex = id - EXPR_VVAR_ENTRY0;
|
|
assert(varIndex < vVars.Count());
|
|
while (IO_OK == iload->OpenChunk()) {
|
|
switch (iload->CurChunkID()) {
|
|
case EXPR_VAR_NAME:
|
|
iload->ReadCStringChunk(&cp);
|
|
vVars[varIndex].name = cp;
|
|
break;
|
|
case EXPR_VAR_REFID:
|
|
iload->Read(&vVars[varIndex].refID, sizeof(int), &nb);
|
|
break;
|
|
case EXPR_VAR_SUBNUM:
|
|
iload->Read(&vVars[varIndex].subNum, sizeof(int), &nb);
|
|
break;
|
|
case EXPR_VAR_OFFSET:
|
|
iload->Read(&vVars[varIndex].offset, sizeof(int), &nb);
|
|
break;
|
|
case EXPR_VAR_POINT3:
|
|
iload->Read(&vVars[varIndex].val, sizeof(Point3), &nb);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
}
|
|
updRegCt(intVar = expr.defVar(VECTOR_VAR, vVars[varIndex].name), VECTOR_VAR);
|
|
vVars[varIndex].regNum = intVar;
|
|
}
|
|
iload->CloseChunk();
|
|
}
|
|
|
|
return IO_OK;
|
|
}
|
|
|
|
|
|
static BOOL CALLBACK ExprDbgWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
|
|
int ExprDebug::winX = -1;
|
|
int ExprDebug::winY = -1;
|
|
|
|
|
|
ExprDebug::ExprDebug(HWND hParent, ExprControl *exprControl)
|
|
{
|
|
ec = exprControl;
|
|
CreateDialogParam(
|
|
hInstance,
|
|
MAKEINTRESOURCE(IDD_EXPR_DEBUG),
|
|
hParent,
|
|
ExprDbgWndProc,
|
|
(LPARAM)this);
|
|
}
|
|
|
|
ExprDebug::~ExprDebug()
|
|
{
|
|
Rect rect;
|
|
GetWindowRect(hWnd,&rect);
|
|
winX = rect.left;
|
|
winY = rect.top;
|
|
GetCOREInterface()->UnRegisterTimeChangeCallback(this);
|
|
if(ec)
|
|
ec->edbg = NULL;
|
|
}
|
|
|
|
void ExprDebug::Invalidate()
|
|
{
|
|
Rect rect;
|
|
rect.left = 0;
|
|
rect.right = 10;
|
|
rect.top = 0;
|
|
rect.bottom = 10;
|
|
InvalidateRect(hWnd,&rect,FALSE);
|
|
}
|
|
|
|
void ExprDebug::Update()
|
|
{
|
|
int i, ct;
|
|
float fval;
|
|
Point3 vval;
|
|
TCHAR buf[1024];
|
|
HWND hList = GetDlgItem(hWnd, IDC_DEBUG_LIST);
|
|
|
|
SendMessage(hList, LB_RESETCONTENT, 0, 0);
|
|
|
|
_stprintf(buf, _T("%s\t%g"), _T("T"), (float)t);
|
|
SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)buf);
|
|
_stprintf(buf, _T("%s\t%g"), _T("S"), (float)t/4800.0f);
|
|
SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)buf);
|
|
_stprintf(buf, _T("%s\t%g"), _T("F"), (float)t/GetTicksPerFrame());
|
|
SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)buf);
|
|
_stprintf(buf, _T("%s\t%g"), _T("NT"), (float)(t-ec->range.Start()) /
|
|
(float)(ec->range.End()-ec->range.Start()));
|
|
SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)buf);
|
|
|
|
ct = ec->getVarCount(SCALAR_VAR);
|
|
for(i = 0; i < ct; i++) {
|
|
if(ec->sVars[i].refID < 0)
|
|
fval = ec->sVars[i].val;
|
|
else {
|
|
Control *c;
|
|
Interval iv;
|
|
c = (Control *)ec->refTab[ec->sVars[i].refID].client->SubAnim(ec->sVars[i].subNum);
|
|
c->GetValue(t+ec->sVars[i].offset, &fval, iv);
|
|
}
|
|
_stprintf(buf, _T("%s\t%.4f"), ec->getVarName(SCALAR_VAR, i), fval);
|
|
SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)buf);
|
|
}
|
|
ct = ec->getVarCount(VECTOR_VAR);
|
|
for(i = 0; i < ct; i++) {
|
|
if(ec->vVars[i].refID < 0 || !ec->refTab[ec->vVars[i].refID].client)
|
|
vval = ec->vVars[i].val;
|
|
else {
|
|
Control *c;
|
|
Interval iv;
|
|
if (ec->vVars[i].subNum < 0) { // this is referencing a node, not a controller! DB 1/98
|
|
ec->GetAbsoluteControlValue(
|
|
(INode*)ec->refTab[ec->vVars[i].refID].client,t+ec->vVars[i].offset,&vval, iv);
|
|
}
|
|
else { // controller reference...
|
|
c = (Control *)ec->refTab[ec->vVars[i].refID].client->SubAnim(ec->vVars[i].subNum);
|
|
c->GetValue(t+ec->vVars[i].offset, &vval, iv);
|
|
}
|
|
}
|
|
_stprintf(buf, _T("%s\t[%.4f, %.4f, %.4f]"), ec->getVarName(VECTOR_VAR, i), vval.x, vval.y, vval.z);
|
|
SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)buf);
|
|
}
|
|
if(ec->expr.getExprType() == SCALAR_EXPR) {
|
|
Interval iv;
|
|
ec->GetValue(t, &ec->curFloatVal, iv);
|
|
_stprintf(buf, _T("%g"), ec->curFloatVal);
|
|
}
|
|
else if(ec->type == EXPR_SCALE_CONTROL_CLASS_ID) {
|
|
Interval iv;
|
|
Quat q;
|
|
ec->GetValue(t, &q, iv);
|
|
_stprintf(buf, _T("[%g, %g, %g]"), q.x, q.y, q.z);
|
|
}
|
|
else {
|
|
Interval iv;
|
|
ec->GetValue(t, &ec->curPosVal, iv);
|
|
_stprintf(buf, _T("[%g, %g, %g]"), ec->curPosVal.x, ec->curPosVal.y, ec->curPosVal.z);
|
|
}
|
|
SetDlgItemText(hWnd, IDC_DEBUG_VALUE, buf);
|
|
}
|
|
|
|
static int tabs[] = { 75 };
|
|
|
|
void ExprDebug::Init(HWND hWnd)
|
|
{
|
|
this->hWnd = hWnd;
|
|
|
|
if (winX==-1 || winY==-1)
|
|
CenterWindow(hWnd,GetParent(hWnd));
|
|
else
|
|
SetWindowPos(hWnd,NULL,winX, winY, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
|
|
|
|
t = GetCOREInterface()->GetTime();
|
|
|
|
SendMessage(GetDlgItem(hWnd, IDC_DEBUG_LIST), LB_SETTABSTOPS, 1, (LPARAM)tabs);
|
|
GetCOREInterface()->RegisterTimeChangeCallback(this);
|
|
}
|
|
|
|
|
|
static BOOL CALLBACK ExprDbgWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
ExprDebug *ed = (ExprDebug*)GetWindowLong(hWnd,GWL_USERDATA);
|
|
|
|
switch (msg) {
|
|
case WM_INITDIALOG:
|
|
// SetWindowContextHelpId(hWnd,idh_dialog_xform_typein);
|
|
ed = (ExprDebug*)lParam;
|
|
SetWindowLong(hWnd,GWL_USERDATA,lParam);
|
|
ed->Init(hWnd);
|
|
return FALSE;
|
|
|
|
case WM_SYSCOMMAND:
|
|
// if ((wParam & 0xfff0)==SC_CONTEXTHELP)
|
|
// Help(HELP_CONTEXT,idh_dialog_xform_typein);
|
|
return 0;
|
|
|
|
case WM_PAINT:
|
|
// if (!ed->valid)
|
|
ed->Update();
|
|
return 0;
|
|
|
|
case WM_COMMAND:
|
|
if(LOWORD(wParam) == IDCANCEL)
|
|
goto weAreDone;
|
|
SendMessage(GetParent(hWnd), msg, wParam, lParam);
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
weAreDone:
|
|
DestroyWindow(hWnd);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
delete ed;
|
|
break;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
|