Files
firestorm/Gameleap/code/mw4/Tools/3DSPlugins/MaxControls/SURFCTRL.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

874 lines
21 KiB
C++

/**********************************************************************
*<
FILE: surfctrl.cpp
DESCRIPTION: A controller that moves an object along a surface
CREATED BY: Rolf Berteig
HISTORY: created 2/13/97
*> Copyright (c) 1997, All Rights Reserved.
**********************************************************************/
#include "ctrl.h"
#include "units.h"
#include "interpik.h"
#include "istdplug.h"
#define SURF_CONTROL_CNAME GetString(IDS_RB_SURF)
#define U_REF 0
#define V_REF 1
#define SURF_REF 2
class SurfPosition;
class PickSurfMode :
public PickModeCallback,
public PickNodeCallback {
public:
SurfPosition *cont;
PickSurfMode(SurfPosition *c) {cont=c;}
BOOL HitTest(IObjParam *ip,HWND hWnd,ViewExp *vpt,IPoint2 m,int flags);
BOOL Pick(IObjParam *ip,ViewExp *vpt);
void EnterMode(IObjParam *ip);
void ExitMode(IObjParam *ip);
BOOL RightClick(IObjParam *ip,ViewExp *vpt) {return TRUE;}
BOOL Filter(INode *node);
PickNodeCallback *GetFilter() {return this;}
};
class SurfPosition : public ISurfPosition, public TimeChangeCallback {
public:
Control *uCont, *vCont;
INode *surf;
int align;
BOOL flip;
Point3 curval;
Quat curRot;
Interval ivalid;
static HWND hWnd;
static IObjParam *ip;
static ICustButton *iPick;
static PickSurfMode *pickMode;
static ISpinnerControl *iU, *iV;
static SurfPosition *editCont;
SurfPosition();
~SurfPosition();
// Animatable methods
Class_ID ClassID() {return SURF_CONTROL_CLASSID;}
SClass_ID SuperClassID() { return CTRL_POSITION_CLASS_ID; }
void GetClassName(TSTR& s) {s = SURF_CONTROL_CNAME;}
void DeleteThis() {delete this;}
int IsKeyable() {return 0;}
int NumSubs() {return 2;}
Animatable* SubAnim(int i);
TSTR SubAnimName(int i);
int SubNumToRefNum(int subNum);
ParamDimension* GetParamDimension(int i) {return stdPercentDim;}
BOOL AssignController(Animatable *control,int subAnim);
void BeginEditParams(IObjParam *ip, ULONG flags,Animatable *prev);
void EndEditParams(IObjParam *ip, ULONG flags,Animatable *next);
int SetProperty(ULONG id, void *data);
void *GetProperty(ULONG id);
// Reference methods
int NumRefs() {return 3;};
RefTargetHandle GetReference(int i);
void SetReference(int i, RefTargetHandle rtarg);
RefResult NotifyRefChanged(Interval, RefTargetHandle, PartID&, RefMessage);
RefTargetHandle Clone(RemapDir& remap);
IOResult Save(ISave *isave);
IOResult Load(ILoad *iload);
// Control methods
void Copy(Control *from);
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);
void EnumIKParams(IKEnumCallback &callback);
BOOL CompDeriv(TimeValue t,Matrix3& ptm,IKDeriv& derivs,DWORD flags);
float IncIKParam(TimeValue t,int index,float delta);
void ClearIKParam(Interval iv,int index);
// TimeChangeCallback methods
void TimeChanged(TimeValue t);
// Local methods
void SetSurface(INode *node);
void SetupDialog(HWND hWnd);
void DestroyDialog();
void UpdateDialog();
void GetUV(TimeValue t,float &u, float &v,Interval *iv=NULL);
Point3 DU(TimeValue t,float u, float v);
Point3 DV(TimeValue t,float u, float v);
Point3 Norm(TimeValue t,float u, float v);
Point3 Pos(TimeValue t,float u, float v,Interval *iv=NULL);
int GetAlign() {return align;}
void SetAlign(int a);
BOOL GetFlip() {return flip;}
void SetFlip(BOOL f);
};
class JointParamsSurf : public JointParams {
public:
JointParamsSurf() : JointParams((DWORD)JNT_POS,2,1.0f) {}
void SpinnerChange(InterpCtrlUI *ui,WORD id,ISpinnerControl *spin,BOOL interactive);
};
//--- ClassDesc and class vars -------------------------------------
class SurfClassDesc:public ClassDesc {
public:
int IsPublic() {return 1;}
void * Create(BOOL loading) { return new SurfPosition();}
const TCHAR * ClassName() {return SURF_CONTROL_CNAME;}
SClass_ID SuperClassID() {return CTRL_POSITION_CLASS_ID;}
Class_ID ClassID() {return SURF_CONTROL_CLASSID;}
const TCHAR* Category() {return _T("");}
};
static SurfClassDesc surfCD;
ClassDesc* GetSurfCtrlDesc() {return &surfCD;}
HWND SurfPosition::hWnd = NULL;
IObjParam *SurfPosition::ip = NULL;
ICustButton *SurfPosition::iPick = NULL;
ISpinnerControl *SurfPosition::iU = NULL;
ISpinnerControl *SurfPosition::iV = NULL;
PickSurfMode *SurfPosition::pickMode = NULL;
SurfPosition *SurfPosition::editCont = NULL;
static BOOL CALLBACK SurfParamDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
//--- SurfPosition methods ------------------------------------------
SurfPosition::SurfPosition()
{
uCont = vCont = NULL;
surf = NULL;
ReplaceReference(U_REF,NewDefaultFloatController());
ReplaceReference(V_REF,NewDefaultFloatController());
align = IDC_ALIGN_NONE;
flip = FALSE;
ivalid.SetEmpty();
}
SurfPosition::~SurfPosition()
{
DeleteAllRefsFromMe();
}
Animatable* SurfPosition::SubAnim(int i)
{
switch (i) {
case 0: return uCont; break;
case 1: return vCont; break;
};
return NULL;
}
TSTR SurfPosition::SubAnimName(int i)
{
switch (i) {
case 0: return GetString(IDS_RB_U); break;
case 1: return GetString(IDS_RB_V); break;
}
return _T("");
}
int SurfPosition::SubNumToRefNum(int subNum)
{
switch (subNum) {
case 0: return 0;
case 1: return 1;
default: return -1;
}
}
BOOL SurfPosition::AssignController(
Animatable *control,int subAnim)
{
ReplaceReference(subAnim,(ReferenceTarget*)control);
ivalid.SetEmpty();
NotifyDependents(FOREVER,0,REFMSG_SUBANIM_STRUCTURE_CHANGED);
NotifyDependents(FOREVER,0,REFMSG_CHANGE);
return TRUE;
}
void SurfPosition::BeginEditParams(
IObjParam *ip, ULONG flags,Animatable *prev)
{
this->ip = ip;
editCont = this;
if (flags&BEGIN_EDIT_HIERARCHY) {
if (align!=IDC_ALIGN_NONE) return;
JointParamsSurf *jp = (JointParamsSurf*)GetProperty(PROPID_JOINTPARAMS);
InterpCtrlUI *ui;
if (!jp) {
jp = new JointParamsSurf();
SetProperty(PROPID_JOINTPARAMS,jp);
}
if (prev &&
prev->ClassID()==ClassID() &&
(ui = (InterpCtrlUI*)prev->GetProperty(PROPID_INTERPUI))) {
JointParams *prevjp = (JointParams*)prev->GetProperty(PROPID_JOINTPARAMS);
prevjp->EndDialog(ui);
ui->cont = this;
ui->ip = ip;
prev->SetProperty(PROPID_INTERPUI,NULL);
JointDlgData *jd = (JointDlgData*)GetWindowLong(ui->hParams,GWL_USERDATA);
jd->jp = jp;
jp->InitDialog(ui);
} else {
ui = new InterpCtrlUI(NULL,ip,this);
DWORD f=0;
if (!jp || !jp->RollupOpen()) f = APPENDROLL_CLOSED;
ui->hParams = ip->AddRollupPage(
hInstance,
MAKEINTRESOURCE(IDD_SURFJOINTPARAMS),
JointParamDlgProc,
GetString(IDS_RB_SURFJOINTPARAMS),
(LPARAM)new JointDlgData(ui,jp),f);
}
SetProperty(PROPID_INTERPUI,ui);
} else {
pickMode = new PickSurfMode(this);
hWnd = ip->AddRollupPage(
hInstance,
MAKEINTRESOURCE(IDD_SURFPARAMS),
SurfParamDlgProc,
GetString(IDS_RB_SURFPARAMS),
(LPARAM)this );
ip->RegisterTimeChangeCallback(this);
}
}
void SurfPosition::EndEditParams(
IObjParam *ip, ULONG flags,Animatable *next)
{
editCont = NULL;
this->ip = NULL;
if (next && next->ClassID()==ClassID() && !hWnd) return;
if (hWnd) {
ip->UnRegisterTimeChangeCallback(this);
ip->ClearPickMode();
delete pickMode;
pickMode = NULL;
ip->DeleteRollupPage(hWnd);
hWnd = NULL;
} else {
int index = aprops.FindProperty(PROPID_INTERPUI);
if (index>=0) {
InterpCtrlUI *ui = (InterpCtrlUI*)aprops[index];
if (ui->hParams) {
ip->UnRegisterDlgWnd(ui->hParams);
ip->DeleteRollupPage(ui->hParams);
}
index = aprops.FindProperty(PROPID_INTERPUI);
if (index>=0) {
delete aprops[index];
aprops.Delete(index,1);
}
}
}
}
RefTargetHandle SurfPosition::GetReference(int i)
{
switch (i) {
case U_REF: return uCont;
case V_REF: return vCont;
case SURF_REF: return surf;
}
return NULL;
}
void SurfPosition::SetReference(int i, RefTargetHandle rtarg)
{
switch (i) {
case U_REF: uCont = (Control*)rtarg; break;
case V_REF: vCont = (Control*)rtarg; break;
case SURF_REF: surf = (INode*)rtarg; break;
}
}
RefResult SurfPosition::NotifyRefChanged(
Interval iv, RefTargetHandle hTarg,
PartID &partID, RefMessage msg)
{
switch (msg) {
case REFMSG_CHANGE:
ivalid.SetEmpty();
break;
case REFMSG_TARGET_DELETED:
if (hTarg == surf) {
surf = NULL;
if (hWnd && editCont == this) {
SetWindowText(GetDlgItem(hWnd,IDC_SURFNAME),
GetString(IDS_RB_NONE));
}
}
break;
}
return REF_SUCCEED;
}
void SurfPosition::SetAlign(int a)
{
align = a;
NotifyDependents(FOREVER,0,REFMSG_CHANGE);
}
void SurfPosition::SetFlip(BOOL f)
{
flip = f;
NotifyDependents(FOREVER,0,REFMSG_CHANGE);
}
RefTargetHandle SurfPosition::Clone(RemapDir& remap)
{
SurfPosition *cont = new SurfPosition;
cont->ReplaceReference(U_REF,remap.CloneRef(uCont));
cont->ReplaceReference(V_REF,remap.CloneRef(vCont));
cont->ReplaceReference(SURF_REF,surf);
cont->align = align;
cont->flip = flip;
return cont;
}
#define ALIGN_CHUNK 0x0100
#define FLIP_CHUNK 0x0110
#define JOINTPARAMSURF_CHUNK 0x0200
IOResult SurfPosition::Save(ISave *isave)
{
JointParamsSurf *jp = (JointParamsSurf*)GetProperty(PROPID_JOINTPARAMS);
ULONG nb;
if (jp) {
isave->BeginChunk(JOINTPARAMSURF_CHUNK);
jp->Save(isave);
isave->EndChunk();
}
isave->BeginChunk(ALIGN_CHUNK);
isave->Write(&align,sizeof(align),&nb);
isave->EndChunk();
if (flip) {
isave->BeginChunk(FLIP_CHUNK);
isave->EndChunk();
}
return IO_OK;
}
IOResult SurfPosition::Load(ILoad *iload)
{
ULONG nb;
IOResult res = IO_OK;
while (IO_OK==(res=iload->OpenChunk())) {
switch (iload->CurChunkID()) {
case ALIGN_CHUNK:
res=iload->Read(&align,sizeof(align),&nb);
break;
case JOINTPARAMSURF_CHUNK: {
JointParamsSurf *jp = new JointParamsSurf;
jp->Load(iload);
SetProperty(PROPID_JOINTPARAMS,jp);
break;
}
case FLIP_CHUNK:
flip = TRUE;
break;
}
iload->CloseChunk();
if (res!=IO_OK) return res;
}
return IO_OK;
}
void SurfPosition::Copy(Control *from)
{
if (from->ClassID()==ClassID()) {
SurfPosition *cont = (SurfPosition*)from;
ReplaceReference(U_REF,cont->uCont->Clone());
ReplaceReference(V_REF,cont->vCont->Clone());
ReplaceReference(SURF_REF,cont->surf);
align = cont->align;
flip = cont->flip;
}
}
void SurfPosition::GetUV(
TimeValue t,float &u, float &v,Interval *iv)
{
Interval valid;
if (!iv) iv = &valid;
uCont->GetValue(t,&u,*iv);
vCont->GetValue(t,&v,*iv);
}
Point3 SurfPosition::DU(TimeValue t,float u, float v)
{
return (Pos(t,u+0.01f,v)-Pos(t,u,v))/0.01f;
}
Point3 SurfPosition::DV(TimeValue t,float u, float v)
{
return (Pos(t,u,v+0.01f)-Pos(t,u,v))/0.01f;
}
Point3 SurfPosition::Norm(TimeValue t,float u, float v)
{
Point3 du = DU(t,u,v);
Point3 dv = DV(t,u,v);
return Normalize(du^dv);
}
Point3 SurfPosition::Pos(
TimeValue t,float u, float v,Interval *iv)
{
Interval valid;
if (!iv) iv = &valid;
if (surf) {
ObjectState os = surf->EvalWorldState(0);
return os.obj->GetSurfacePoint(t,u,v,*iv) *
surf->GetObjTMBeforeWSM(t,iv);
} else {
return Point3(0,0,0);
}
}
void SurfPosition::GetValue(
TimeValue t, void *val, Interval &valid,
GetSetMethod method)
{
if (!ivalid.InInterval(t)) {
float u, v;
ivalid = FOREVER;
GetUV(t,u,v,&ivalid);
curval = Pos(t,u,v,&ivalid);
if (align!=IDC_ALIGN_NONE) {
Matrix3 tm(1);
Point3 norm = Norm(t,u,v);
tm.SetRow(2,flip?-norm:norm);
if (align==IDC_ALIGN_U)
tm.SetRow(0,Normalize(DU(t,u,v)));
else tm.SetRow(0,Normalize(DV(t,u,v)));
tm.SetRow(1,Normalize(tm.GetRow(2)^tm.GetRow(0)));
curRot = Quat(tm);
}
}
if (method==CTRL_RELATIVE) {
Matrix3 *mat = (Matrix3*)val;
if (align!=IDC_ALIGN_NONE) {
curRot.MakeMatrix(*mat);
}
mat->SetTrans(curval);
} else {
*((Point3*)val) = curval;
}
valid &= ivalid;
}
void SurfPosition::CommitValue(TimeValue t)
{
uCont->CommitValue(t);
vCont->CommitValue(t);
}
void SurfPosition::RestoreValue(TimeValue t)
{
uCont->RestoreValue(t);
vCont->RestoreValue(t);
}
void SurfPosition::TimeChanged(TimeValue t)
{
UpdateDialog();
}
void SurfPosition::SetSurface(INode *node)
{
ivalid.SetEmpty();
ReplaceReference(SURF_REF,node);
NotifyDependents(FOREVER,0,REFMSG_CHANGE);
UpdateDialog();
}
//--- PickSurfMode methods -----------------------------------------
BOOL PickSurfMode::HitTest(
IObjParam *ip,HWND hWnd,ViewExp *vpt,
IPoint2 m,int flags)
{
INode *node = cont->ip->PickNode(hWnd,m);
return node?TRUE:FALSE;
}
BOOL PickSurfMode::Pick(IObjParam *ip,ViewExp *vpt)
{
INode *node = vpt->GetClosestHit();
if (node) {
cont->SetSurface(node);
ip->RedrawViews(ip->GetTime());
}
return TRUE;
}
void PickSurfMode::EnterMode(IObjParam *ip)
{
cont->iPick->SetCheck(TRUE);
}
void PickSurfMode::ExitMode(IObjParam *ip)
{
cont->iPick->SetCheck(FALSE);
}
BOOL PickSurfMode::Filter(INode *node)
{
if (node) {
ObjectState os = node->EvalWorldState(0);
if (os.obj->IsParamSurface()) return TRUE;
}
return FALSE;
}
//--- UI -------------------------------------------------------------
static BOOL CALLBACK SurfParamDlgProc(
HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
SurfPosition *co = (SurfPosition*)GetWindowLong(hWnd,GWL_USERDATA);
switch (msg) {
case WM_INITDIALOG:
co = (SurfPosition*)lParam;
SetWindowLong(hWnd, GWL_USERDATA, (LONG)co);
co->SetupDialog(hWnd);
break;
case CC_SPINNER_BUTTONDOWN:
theHold.Begin();
break;
case WM_CUSTEDIT_ENTER:
case CC_SPINNER_BUTTONUP:
if (HIWORD(wParam)) {
theHold.Accept(GetString(IDS_RB_CHANGEUV));
} else {
theHold.Cancel();
}
co->ip->RedrawViews(co->ip->GetTime());
break;
case CC_SPINNER_CHANGE: {
float f;
switch (LOWORD(wParam)) {
case IDC_SURF_USPIN:
f = co->iU->GetFVal();
co->uCont->SetValue(co->ip->GetTime(),&f);
break;
case IDC_SURF_VSPIN:
f = co->iV->GetFVal();
co->vCont->SetValue(co->ip->GetTime(),&f);
break;
}
co->ip->RedrawViews(co->ip->GetTime());
break;
}
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_ALIGN_FLIP:
co->flip = IsDlgButtonChecked(hWnd,IDC_ALIGN_FLIP);
co->ivalid.SetEmpty();
co->NotifyDependents(FOREVER,0,REFMSG_CHANGE);
co->ip->RedrawViews(co->ip->GetTime());
break;
case IDC_ALIGN_NONE:
case IDC_ALIGN_U:
case IDC_ALIGN_V:
co->align = LOWORD(wParam);
co->ivalid.SetEmpty();
co->NotifyDependents(FOREVER,0,REFMSG_CHANGE);
co->ip->RedrawViews(co->ip->GetTime());
co->UpdateDialog();
break;
case IDC_PICKSURF:
co->ip->SetPickMode(co->pickMode);
break;
}
break;
case WM_LBUTTONDOWN:case WM_LBUTTONUP: case WM_MOUSEMOVE:
co->ip->RollupMouseMessage(hWnd,msg,wParam,lParam);
return FALSE;
case WM_DESTROY:
co->DestroyDialog();
break;
default:
return FALSE;
}
return TRUE;
}
void SurfPosition::SetupDialog(HWND hWnd)
{
this->hWnd = hWnd;
iPick = GetICustButton(GetDlgItem(hWnd,IDC_PICKSURF));
iPick->SetType(CBT_CHECK);
iPick->SetHighlightColor(GREEN_WASH);
iU = GetISpinner(GetDlgItem(hWnd,IDC_SURF_USPIN));
iU->SetLimits(-999999999.0f,999999999.0f,FALSE);
iU->SetAutoScale();
iU->LinkToEdit(GetDlgItem(hWnd,IDC_SURF_U),EDITTYPE_FLOAT);
iV = GetISpinner(GetDlgItem(hWnd,IDC_SURF_VSPIN));
iV->SetLimits(-999999999.0f,999999999.0f,FALSE);
iV->SetAutoScale();
iV->LinkToEdit(GetDlgItem(hWnd,IDC_SURF_V),EDITTYPE_FLOAT);
UpdateDialog();
}
void SurfPosition::UpdateDialog()
{
TimeValue t = ip->GetTime();
float f;
uCont->GetValue(t,&f,FOREVER);
iU->SetValue(f,FALSE);
vCont->GetValue(t,&f,FOREVER);
iV->SetValue(f,FALSE);
CheckDlgButton(hWnd,align,TRUE);
CheckDlgButton(hWnd,IDC_ALIGN_FLIP,flip);
if (align!=IDC_ALIGN_NONE)
EnableWindow(GetDlgItem(hWnd,IDC_ALIGN_FLIP),TRUE);
else EnableWindow(GetDlgItem(hWnd,IDC_ALIGN_FLIP),FALSE);
if (surf) {
SetWindowText(GetDlgItem(hWnd,IDC_SURFNAME),
surf->GetName());
} else {
SetWindowText(GetDlgItem(hWnd,IDC_SURFNAME),
GetString(IDS_RB_NONE));
}
}
void SurfPosition::DestroyDialog()
{
ReleaseISpinner(iU); iU = NULL;
ReleaseISpinner(iV); iV = NULL;
ReleaseICustButton(iPick); iPick = NULL;
}
//--- IK -----------------------------------------------------------
int SurfPosition::SetProperty(ULONG id, void *data)
{
if (id==PROPID_JOINTPARAMS) {
if (!data) {
int index = aprops.FindProperty(id);
if (index>=0) {
aprops.Delete(index,1);
}
} else {
JointParamsSurf *jp = (JointParamsSurf*)GetProperty(id);
if (jp) {
*jp = *((JointParamsSurf*)data);
delete (JointParamsSurf*)data;
} else {
aprops.Append(1,(AnimProperty**)&data);
}
}
return 1;
} else
if (id==PROPID_INTERPUI) {
if (!data) {
int index = aprops.FindProperty(id);
if (index>=0) {
aprops.Delete(index,1);
}
} else {
InterpCtrlUI *ui = (InterpCtrlUI*)GetProperty(id);
if (ui) {
*ui = *((InterpCtrlUI*)data);
} else {
aprops.Append(1,(AnimProperty**)&data);
}
}
return 1;
} else {
return Animatable::SetProperty(id,data);
}
}
void* SurfPosition::GetProperty(ULONG id)
{
if (id==PROPID_INTERPUI || id==PROPID_JOINTPARAMS) {
int index = aprops.FindProperty(id);
if (index>=0) {
return aprops[index];
} else {
return NULL;
}
} else {
return Animatable::GetProperty(id);
}
}
void JointParamsSurf::SpinnerChange(
InterpCtrlUI *ui,WORD id,ISpinnerControl *spin,
BOOL interactive)
{
float val;
int set = 0;
switch (id) {
case IDC_XFROMSPIN:
val = min[0] = spin->GetFVal()/scale;
set = 1;
break;
case IDC_XTOSPIN:
val = max[0] = spin->GetFVal()/scale;
set = 1;
break;
case IDC_XDAMPINGSPIN:
damping[0] = spin->GetFVal(); break;
case IDC_YFROMSPIN:
val = min[1] = spin->GetFVal()/scale;
set = 2;
break;
case IDC_YTOSPIN:
val = max[1] = spin->GetFVal()/scale;
set = 2;
break;
case IDC_YDAMPINGSPIN:
damping[1] = spin->GetFVal(); break;
}
if (set && interactive) {
SurfPosition *c = (SurfPosition*)ui->cont;
if (set==1)
c->uCont->SetValue(
ui->ip->GetTime(),&val,TRUE,CTRL_ABSOLUTE);
else c->vCont->SetValue(
ui->ip->GetTime(),&val,TRUE,CTRL_ABSOLUTE);
ui->ip->RedrawViews(ui->ip->GetTime(),REDRAW_INTERACTIVE);
}
}
void SurfPosition::EnumIKParams(IKEnumCallback &callback)
{
JointParamsSurf *jp = (JointParamsSurf*)GetProperty(PROPID_JOINTPARAMS);
if (jp && align==IDC_ALIGN_NONE) {
if (jp->Active(0)) callback.proc(this,0);
if (jp->Active(1)) callback.proc(this,1);
}
}
BOOL SurfPosition::CompDeriv(
TimeValue t,Matrix3& ptm,IKDeriv& derivs,DWORD flags)
{
JointParamsSurf *jp = (JointParamsSurf*)GetProperty(PROPID_JOINTPARAMS);
if (!jp || align!=IDC_ALIGN_NONE) return FALSE;
float u, v;
GetUV(t,u,v);
Point3 zero(0,0,0);
if (jp->Active(0)) {
Point3 d = DU(t,u,v);
for (int j=0; j<derivs.NumEndEffectors(); j++) {
if (flags&POSITION_DERIV) {
derivs.DP(d,j);
}
if (flags&ROTATION_DERIV) {
derivs.DR(zero,j);
}
}
derivs.NextDOF();
}
if (jp->Active(1)) {
Point3 d = DV(t,u,v);
for (int j=0; j<derivs.NumEndEffectors(); j++) {
if (flags&POSITION_DERIV) {
derivs.DP(d,j);
}
if (flags&ROTATION_DERIV) {
derivs.DR(zero,j);
}
}
derivs.NextDOF();
}
ptm.SetTrans(Pos(t,u,v));
return TRUE;
}
float SurfPosition::IncIKParam(TimeValue t,int index,float delta)
{
JointParamsSurf *jp = (JointParamsSurf*)GetProperty(PROPID_JOINTPARAMS);
if (fabs(delta) > 0.01f) {
if (delta<0) delta = -0.01f;
else delta = 0.01f;
}
if (jp) {
float u, v;
if (index==0) {
if (jp->Limited(0)) {
uCont->GetValue(t,&u,FOREVER);
}
delta = jp->ConstrainInc(0,u,delta);
uCont->SetValue(t,&delta,FALSE,CTRL_RELATIVE);
} else {
if (jp->Limited(1)) {
vCont->GetValue(t,&v,FOREVER);
}
delta = jp->ConstrainInc(0,v,delta);
vCont->SetValue(t,&delta,FALSE,CTRL_RELATIVE);
}
}
return delta;
}
void SurfPosition::ClearIKParam(Interval iv,int index)
{
uCont->DeleteTime(iv,TIME_INCRIGHT|TIME_NOSLIDE);
vCont->DeleteTime(iv,TIME_INCRIGHT|TIME_NOSLIDE);
}