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.
1918 lines
47 KiB
C++
1918 lines
47 KiB
C++
/**********************************************************************
|
|
*<
|
|
FILE: mapmod.cpp
|
|
|
|
DESCRIPTION: A UVW mapping modifier 6/1/98 Copied over to make it work
|
|
in my code. JLC
|
|
|
|
CREATED BY: Rolf Berteig
|
|
|
|
HISTORY: 10/21/95
|
|
|
|
*> Copyright (c) 1994, All Rights Reserved.
|
|
**********************************************************************/
|
|
#include "mods.h"
|
|
#include "iparamm.h"
|
|
#include "texutil.h"
|
|
#include "bmmlib.h"
|
|
#include "simpobj.h"
|
|
#include "simpmod.h"
|
|
#include "decomp.h"
|
|
#include "mapping.h"
|
|
#include "buildver.h"
|
|
|
|
class MapMod : public MappingMod {
|
|
public:
|
|
IParamBlock *pblock;
|
|
|
|
static IParamMap *pmapParam;
|
|
static MoveModBoxCMode *moveMode;
|
|
static RotateModBoxCMode *rotMode;
|
|
static UScaleModBoxCMode *uscaleMode;
|
|
static NUScaleModBoxCMode *nuscaleMode;
|
|
static SquashModBoxCMode *squashMode;
|
|
static FaceAlignMode *faceAlignMode;
|
|
static RegionFitMode *regionFitMode;
|
|
static PickAcquire pickAcquire;
|
|
static MapMod *editMod;
|
|
|
|
MapMod(BOOL create);
|
|
|
|
// From Animatable
|
|
void DeleteThis() { delete this; }
|
|
void GetClassName(TSTR& s) {s=GetString(IDS_RB_MAPMOD);}
|
|
virtual Class_ID ClassID() {return Class_ID(UVWMAPOSM_CLASS_ID,0);}
|
|
void BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev);
|
|
void EndEditParams( IObjParam *ip,ULONG flags,Animatable *next);
|
|
TCHAR *GetObjectName() { return GetString(IDS_RB_UVWMAPPING); }
|
|
CreateMouseCallBack* GetCreateMouseCallBack() {return NULL;}
|
|
BOOL AssignController(Animatable *control,int subAnim);
|
|
int SubNumToRefNum(int subNum);
|
|
|
|
ChannelMask ChannelsUsed() {return PART_GEOM|PART_TOPO|PART_SELECT|PART_SUBSEL_TYPE|PART_VERTCOLOR;}
|
|
ChannelMask ChannelsChanged() {return TEXMAP_CHANNEL|PART_VERTCOLOR; }
|
|
Class_ID InputType() {return mapObjectClassID;}
|
|
void ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node);
|
|
Interval LocalValidity(TimeValue t);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
IOResult Save(ISave *isave);
|
|
|
|
int NumRefs() {return 2;}
|
|
RefTargetHandle GetReference(int i);
|
|
void SetReference(int i, RefTargetHandle rtarg);
|
|
|
|
int NumSubs() {return 2;}
|
|
Animatable* SubAnim(int i);
|
|
TSTR SubAnimName(int i);
|
|
|
|
RefTargetHandle Clone(RemapDir& remap = NoRemap());
|
|
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message);
|
|
|
|
void ActivateSubobjSel(int level, XFormModes& modes);
|
|
|
|
// From MappingMod
|
|
void EnterNormalAlign();
|
|
void ExitNormalAlign();
|
|
void EnterRegionFit();
|
|
void ExitRegionFit();
|
|
int GetMapType();
|
|
void SetMapType(int type);
|
|
float GetTile(TimeValue t,int which);
|
|
void SetTile(TimeValue t,int which, float tile);
|
|
BOOL GetFlip(int which);
|
|
void SetFlip(int which,BOOL flip);
|
|
void EnterAcquire();
|
|
void ExitAcquire();
|
|
float GetLength(TimeValue t);
|
|
float GetWidth(TimeValue t);
|
|
float GetHeight(TimeValue t);
|
|
int GetAxis();
|
|
void SetLength(TimeValue t,float v);
|
|
void SetWidth(TimeValue t,float v);
|
|
void SetHeight(TimeValue t,float v);
|
|
void SetAxis(int v);
|
|
int GetFirstParamVer() {return 3;}
|
|
int GetPBlockVersion() {return pblock->GetVersion();}
|
|
|
|
};
|
|
|
|
|
|
//--- ClassDescriptor and class vars ---------------------------------
|
|
|
|
IObjParam* MappingMod::ip = NULL;
|
|
|
|
IParamMap* MapMod::pmapParam = NULL;
|
|
MoveModBoxCMode* MapMod::moveMode = NULL;
|
|
RotateModBoxCMode* MapMod::rotMode = NULL;
|
|
UScaleModBoxCMode* MapMod::uscaleMode = NULL;
|
|
NUScaleModBoxCMode* MapMod::nuscaleMode = NULL;
|
|
SquashModBoxCMode* MapMod::squashMode = NULL;
|
|
FaceAlignMode* MapMod::faceAlignMode = NULL;
|
|
RegionFitMode* MapMod::regionFitMode = NULL;
|
|
PickAcquire MapMod::pickAcquire;
|
|
MapMod* MapMod::editMod = NULL;
|
|
|
|
class UVWMapClassDesc:public ClassDesc {
|
|
public:
|
|
int IsPublic() { return 1; }
|
|
void * Create(BOOL loading = FALSE) {return new MapMod(!loading);}
|
|
const TCHAR * ClassName() { return GetString(IDS_RB_UVWMAP_CLASS); }
|
|
SClass_ID SuperClassID() { return OSM_CLASS_ID; }
|
|
Class_ID ClassID() { return Class_ID(UVWMAPOSM_CLASS_ID,0); }
|
|
const TCHAR* Category() {return GetString(IDS_RB_DEFSURFACE);}
|
|
};
|
|
|
|
static UVWMapClassDesc mapDesc;
|
|
extern ClassDesc* GetUVWMapModDesc() {return &mapDesc;}
|
|
|
|
static void DoBoxIcon(BOOL sel,float length, PolyLineProc& lp);
|
|
|
|
//--- Parameter map/block descriptors -------------------------------
|
|
|
|
#define PB_MAPTYPE 0
|
|
#define PB_UTILE 1
|
|
#define PB_VTILE 2
|
|
#define PB_WTILE 3
|
|
#define PB_UFLIP 4
|
|
#define PB_VFLIP 5
|
|
#define PB_WFLIP 6
|
|
#define PB_CAP 7
|
|
#define PB_CHANNEL 8
|
|
#define PB_LENGTH 9
|
|
#define PB_WIDTH 10
|
|
#define PB_HEIGHT 11
|
|
#define PB_AXIS 12
|
|
|
|
//
|
|
//
|
|
// Parameters
|
|
|
|
static int mapIDs[] = {IDC_MAP_PLANAR,IDC_MAP_CYL,IDC_MAP_SPHERE,IDC_MAP_BALL,IDC_MAP_BOX,IDC_MAP_FACE};
|
|
static int chanIDs[] = {IDC_MAP_CHAN1,IDC_MAP_CHAN2};
|
|
static int axisIDs[] = {IDC_MAP_X,IDC_MAP_Y,IDC_MAP_Z};
|
|
|
|
static ParamUIDesc descParam[] = {
|
|
// Map type
|
|
ParamUIDesc(PB_MAPTYPE,TYPE_RADIO,mapIDs,6),
|
|
|
|
// U Tile
|
|
ParamUIDesc(
|
|
PB_UTILE,
|
|
EDITTYPE_FLOAT,
|
|
IDC_MAP_UTILE,IDC_MAP_UTILESPIN,
|
|
-999999999.0f,999999999.0f,
|
|
0.01f),
|
|
|
|
// V Tile
|
|
ParamUIDesc(
|
|
PB_VTILE,
|
|
EDITTYPE_FLOAT,
|
|
IDC_MAP_VTILE,IDC_MAP_VTILESPIN,
|
|
-999999999.0f,999999999.0f,
|
|
0.01f),
|
|
|
|
// W Tile
|
|
ParamUIDesc(
|
|
PB_WTILE,
|
|
EDITTYPE_FLOAT,
|
|
IDC_MAP_WTILE,IDC_MAP_WTILESPIN,
|
|
-999999999.0f,999999999.0f,
|
|
0.01f),
|
|
|
|
// U Flip
|
|
ParamUIDesc(PB_UFLIP,TYPE_SINGLECHEKBOX,IDC_MAP_UFLIP),
|
|
|
|
// V Flip
|
|
ParamUIDesc(PB_VFLIP,TYPE_SINGLECHEKBOX,IDC_MAP_VFLIP),
|
|
|
|
// W Flip
|
|
ParamUIDesc(PB_WFLIP,TYPE_SINGLECHEKBOX,IDC_MAP_WFLIP),
|
|
|
|
// Cap
|
|
ParamUIDesc(PB_CAP,TYPE_SINGLECHEKBOX,IDC_MAP_CAP),
|
|
|
|
// Channel
|
|
ParamUIDesc(PB_CHANNEL,TYPE_RADIO,chanIDs,2),
|
|
|
|
// Length
|
|
ParamUIDesc(
|
|
PB_LENGTH,
|
|
EDITTYPE_UNIVERSE,
|
|
IDC_MAP_LENGTH,IDC_MAP_LENGTHSPIN,
|
|
-999999999.0f,999999999.0f,
|
|
SPIN_AUTOSCALE),
|
|
|
|
// Width
|
|
ParamUIDesc(
|
|
PB_WIDTH,
|
|
EDITTYPE_UNIVERSE,
|
|
IDC_MAP_WIDTH,IDC_MAP_WIDTHSPIN,
|
|
-999999999.0f,999999999.0f,
|
|
SPIN_AUTOSCALE),
|
|
|
|
// Height
|
|
ParamUIDesc(
|
|
PB_HEIGHT,
|
|
EDITTYPE_UNIVERSE,
|
|
IDC_MAP_HEIGHT,IDC_MAP_HEIGHTSPIN,
|
|
-999999999.0f,999999999.0f,
|
|
SPIN_AUTOSCALE),
|
|
|
|
// Axis
|
|
ParamUIDesc(PB_AXIS,TYPE_RADIO,axisIDs,3),
|
|
};
|
|
#define PARAMDESC_LENGH 13
|
|
|
|
static ParamBlockDescID descVer0[] = {
|
|
{ TYPE_INT, NULL, FALSE, 0 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 1 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 2 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 3 },
|
|
{ TYPE_INT, NULL, TRUE, 4 },
|
|
{ TYPE_INT, NULL, TRUE, 5 },
|
|
{ TYPE_INT, NULL, TRUE, 6 }};
|
|
|
|
static ParamBlockDescID descVer1[] = {
|
|
{ TYPE_INT, NULL, FALSE, 0 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 1 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 2 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 3 },
|
|
{ TYPE_INT, NULL, FALSE, 4 },
|
|
{ TYPE_INT, NULL, FALSE, 5 },
|
|
{ TYPE_INT, NULL, FALSE, 6 },
|
|
{ TYPE_INT, NULL, FALSE, 7 }};
|
|
|
|
static ParamBlockDescID descVer2[] = {
|
|
{ TYPE_INT, NULL, FALSE, 0 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 1 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 2 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 3 },
|
|
{ TYPE_INT, NULL, FALSE, 4 },
|
|
{ TYPE_INT, NULL, FALSE, 5 },
|
|
{ TYPE_INT, NULL, FALSE, 6 },
|
|
{ TYPE_INT, NULL, FALSE, 7 },
|
|
{ TYPE_INT, NULL, FALSE, 8 }};
|
|
|
|
static ParamBlockDescID descVer3[] = {
|
|
{ TYPE_INT, NULL, FALSE, 0 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 1 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 2 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 3 },
|
|
{ TYPE_INT, NULL, FALSE, 4 },
|
|
{ TYPE_INT, NULL, FALSE, 5 },
|
|
{ TYPE_INT, NULL, FALSE, 6 },
|
|
{ TYPE_INT, NULL, FALSE, 7 },
|
|
{ TYPE_INT, NULL, FALSE, 8 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 9 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 10 },
|
|
{ TYPE_FLOAT, NULL, TRUE, 11 },
|
|
{ TYPE_INT, NULL, FALSE, 12 },
|
|
};
|
|
|
|
#define PBLOCK_LENGTH 13
|
|
|
|
|
|
// Array of old versions
|
|
static ParamVersionDesc versions[] = {
|
|
ParamVersionDesc(descVer0,7,0),
|
|
ParamVersionDesc(descVer1,8,1),
|
|
ParamVersionDesc(descVer2,9,2),
|
|
};
|
|
#define NUM_OLDVERSIONS 3
|
|
|
|
// Current version
|
|
#define CURRENT_VERSION 3
|
|
static ParamVersionDesc curVersion(descVer3,PBLOCK_LENGTH,CURRENT_VERSION);
|
|
|
|
|
|
//--- MapDlgProc -------------------------------------------------------
|
|
|
|
void MappingMod::ViewportAlign()
|
|
{
|
|
ViewExp *vpt = ip->GetActiveViewport();
|
|
if (!vpt) return;
|
|
|
|
// Get mod contexts and nodes for this modifier
|
|
ModContextList mcList;
|
|
INodeTab nodeList;
|
|
ip->GetModContexts(mcList,nodeList);
|
|
|
|
// Viewport tm
|
|
Matrix3 vtm;
|
|
vpt->GetAffineTM(vtm);
|
|
vtm = Inverse(vtm);
|
|
|
|
// Node tm
|
|
Matrix3 ntm = nodeList[0]->GetObjectTM(ip->GetTime());
|
|
ntm.NoScale();
|
|
|
|
// MC tm
|
|
Matrix3 mctm(1);
|
|
if (mcList[0]->tm) mctm = *mcList[0]->tm;
|
|
|
|
// Compute the new destination transform for tmCont
|
|
Matrix3 destTM = vtm * Inverse(ntm) * mctm;
|
|
destTM.PreRotateZ(PI);
|
|
switch (GetAxis()) {
|
|
case 0:
|
|
destTM.PreRotateY(-HALFPI);
|
|
break;
|
|
case 1:
|
|
destTM.PreRotateX(HALFPI);
|
|
break;
|
|
}
|
|
|
|
// Current val of tmCont
|
|
Matrix3 curTM(1);
|
|
tmControl->GetValue(ip->GetTime(),&curTM,FOREVER,CTRL_RELATIVE);
|
|
Point3 s;
|
|
for (int i=0; i<3; i++) s[i] = Length(curTM.GetRow(i));
|
|
|
|
// These types are aligned differently
|
|
if (GetMapType()==MAP_CYLINDRICAL ||
|
|
GetMapType()==MAP_SPHERICAL ||
|
|
GetMapType()==MAP_BALL) {
|
|
destTM.PreRotateX(-HALFPI);
|
|
}
|
|
|
|
// Keep position and scale the same
|
|
destTM.SetTrans(curTM.GetTrans());
|
|
destTM.PreScale(s);
|
|
|
|
// Plug-in the new value
|
|
SetXFormPacket pckt(destTM);
|
|
tmControl->SetValue(ip->GetTime(), &pckt);
|
|
|
|
nodeList.DisposeTemporary();
|
|
ip->ReleaseViewport(vpt);
|
|
ip->RedrawViews(ip->GetTime());
|
|
}
|
|
|
|
static void MatrixFromNormal(Point3& normal, Matrix3& mat)
|
|
{
|
|
Point3 vx;
|
|
vx.z = .0f;
|
|
vx.x = -normal.y;
|
|
vx.y = normal.x;
|
|
if ( vx.x == .0f && vx.y == .0f ) {
|
|
vx.x = 1.0f;
|
|
}
|
|
mat.SetRow(0,vx);
|
|
mat.SetRow(1,normal^vx);
|
|
mat.SetRow(2,normal);
|
|
mat.SetTrans(Point3(0,0,0));
|
|
mat.NoScale();
|
|
}
|
|
|
|
void FaceAlignMouseProc::FaceAlignMap(HWND hWnd,IPoint2 m)
|
|
{
|
|
ViewExp *vpt = ip->GetViewport(hWnd);
|
|
if (!vpt) return;
|
|
|
|
Ray ray, wray;
|
|
float at;
|
|
TimeValue t = ip->GetTime();
|
|
GeomObject *obj;
|
|
Point3 norm, pt;
|
|
Interval valid;
|
|
|
|
// Get mod contexts and nodes for this modifier
|
|
ModContextList mcList;
|
|
INodeTab nodeList;
|
|
ip->GetModContexts(mcList,nodeList);
|
|
|
|
// Calculate a ray from the mouse point
|
|
vpt->MapScreenToWorldRay(float(m.x), float(m.y),wray);
|
|
|
|
for (int i=0; i<nodeList.Count(); i++) {
|
|
INode *node = nodeList[i];
|
|
|
|
// Get the object from the node
|
|
ObjectState os = node->EvalWorldState(t);
|
|
if (os.obj->SuperClassID()==GEOMOBJECT_CLASS_ID) {
|
|
obj = (GeomObject*)os.obj;
|
|
} else {
|
|
continue;
|
|
}
|
|
|
|
// Back transform the ray into object space.
|
|
Matrix3 obtm = node->GetObjectTM(t);
|
|
Matrix3 iobtm = Inverse(obtm);
|
|
ray.p = iobtm * wray.p;
|
|
ray.dir = VectorTransform(iobtm, wray.dir);
|
|
|
|
// See if we hit the object
|
|
if (obj->IntersectRay(t,ray,at,norm)) {
|
|
// Calculate the hit point
|
|
pt = ray.p + ray.dir * at;
|
|
|
|
// Get the mod context tm
|
|
Matrix3 tm(1);
|
|
if (mcList[0]->tm) tm = tm * *mcList[0]->tm;
|
|
|
|
// Transform the point and ray into mod context space
|
|
pt = pt * tm;
|
|
norm = Normalize(VectorTransform(tm,norm));
|
|
|
|
// Construct the target transformation in mod context space
|
|
Matrix3 destTM;
|
|
MatrixFromNormal(norm,destTM);
|
|
destTM.SetTrans(pt);
|
|
destTM.PreRotateZ(PI);
|
|
switch (mod->GetAxis()) {
|
|
case 0:
|
|
destTM.PreRotateY(-HALFPI);
|
|
break;
|
|
case 1:
|
|
destTM.PreRotateX(HALFPI);
|
|
break;
|
|
}
|
|
// Our current transformation... gives relative TM
|
|
Matrix3 curTM(1), relTM, id(1);
|
|
mod->tmControl->GetValue(t,&curTM,valid,CTRL_RELATIVE);
|
|
relTM = Inverse(curTM) * destTM;
|
|
|
|
// Here's the modifications we need to make to get there
|
|
tm.IdentityMatrix();
|
|
tm.SetTrans(curTM.GetTrans());
|
|
AffineParts parts;
|
|
decomp_affine(relTM,&parts);
|
|
Point3 delta = destTM.GetTrans()-curTM.GetTrans();
|
|
mod->Rotate(t,id,tm,parts.q);
|
|
mod->Move(t,id,id,delta);
|
|
break;
|
|
}
|
|
}
|
|
|
|
nodeList.DisposeTemporary();
|
|
ip->ReleaseViewport(vpt);
|
|
}
|
|
|
|
int FaceAlignMouseProc::proc(
|
|
HWND hWnd, int msg, int point, int flags, IPoint2 m)
|
|
{
|
|
switch (msg) {
|
|
case MOUSE_POINT:
|
|
if (point==0) {
|
|
theHold.Begin();
|
|
ip->RedrawViews(ip->GetTime(),REDRAW_BEGIN);
|
|
} else {
|
|
theHold.Accept(0);
|
|
ip->RedrawViews(ip->GetTime(),REDRAW_END);
|
|
}
|
|
break;
|
|
|
|
case MOUSE_MOVE: {
|
|
theHold.Restore();
|
|
FaceAlignMap(hWnd,m);
|
|
ip->RedrawViews(ip->GetTime(),REDRAW_INTERACTIVE);
|
|
break;
|
|
}
|
|
|
|
case MOUSE_ABORT:
|
|
theHold.Cancel();
|
|
ip->RedrawViews(ip->GetTime(),REDRAW_END);
|
|
break;
|
|
|
|
case MOUSE_FREEMOVE:
|
|
SetCursor(ip->GetSysCursor(SYSCUR_SELECT));
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void FaceAlignMode::EnterMode()
|
|
{
|
|
mod->EnterNormalAlign();
|
|
}
|
|
|
|
void FaceAlignMode::ExitMode()
|
|
{
|
|
mod->ExitNormalAlign();
|
|
}
|
|
|
|
|
|
void RegionFitMouseProc::RegionFitMap(HWND hWnd,IPoint2 m)
|
|
{
|
|
ViewExp *vpt = ip->GetViewport(hWnd);
|
|
if (!vpt) return;
|
|
|
|
// Get mod contexts and nodes for this modifier
|
|
ModContextList mcList;
|
|
INodeTab nodeList;
|
|
ip->GetModContexts(mcList,nodeList);
|
|
|
|
// Viewport tm
|
|
Matrix3 vtm;
|
|
vpt->GetAffineTM(vtm);
|
|
vtm = Inverse(vtm);
|
|
|
|
// Node tm
|
|
Matrix3 ntm = nodeList[0]->GetObjectTM(ip->GetTime());
|
|
|
|
// MC tm
|
|
Matrix3 mctm(1);
|
|
if (mcList[0]->tm) mctm = *mcList[0]->tm;
|
|
|
|
// Current val of tmCont.. remove any scale
|
|
Matrix3 ctm(1);
|
|
mod->tmControl->GetValue(ip->GetTime(),&ctm,FOREVER,CTRL_RELATIVE);
|
|
AffineParts parts;
|
|
decomp_affine(ctm, &parts);
|
|
parts.q.MakeMatrix(ctm);
|
|
ctm.Translate(parts.t);
|
|
|
|
// Compute the inverse world space tm for the gizmo
|
|
Matrix3 iwtm = Inverse(ctm * Inverse(mctm) * ntm);
|
|
|
|
// Calculate a ray from the two mouse points
|
|
Ray mray, omray;
|
|
float at;
|
|
Point3 p1, p2;
|
|
vpt->MapScreenToWorldRay(float(m.x), float(m.y),mray);
|
|
vpt->MapScreenToWorldRay(float(om.x), float(om.y),omray);
|
|
|
|
// Back transform the rays into gizmo space
|
|
mray.p = iwtm * mray.p;
|
|
mray.dir = VectorTransform(iwtm, mray.dir);
|
|
omray.p = iwtm * omray.p;
|
|
omray.dir = VectorTransform(iwtm, omray.dir);
|
|
|
|
float dir, pnt, odir, opnt;
|
|
switch (mod->GetAxis()) {
|
|
case 0:
|
|
dir = mray.dir.x; odir = omray.dir.x;
|
|
pnt = mray.p.x; opnt = omray.p.x;
|
|
break;
|
|
case 1:
|
|
dir = mray.dir.y; odir = omray.dir.y;
|
|
pnt = mray.p.y; opnt = omray.p.y;
|
|
break;
|
|
case 2:
|
|
dir = mray.dir.z; odir = omray.dir.z;
|
|
pnt = mray.p.z; opnt = omray.p.z;
|
|
break;
|
|
}
|
|
#define EPSILON 0.001
|
|
// Make sure we're going to hit
|
|
if (fabs(dir)>EPSILON && fabs(odir)>EPSILON) {
|
|
|
|
// Compute the point of intersection
|
|
at = -pnt/dir;
|
|
p1 = mray.p + at*mray.dir;
|
|
at = -opnt/odir;
|
|
p2 = omray.p + at*omray.dir;
|
|
|
|
// Center the map in the region
|
|
ctm.PreTranslate((p1+p2)/2.0f);
|
|
|
|
// Compute scale factors and scale
|
|
float sx;
|
|
float sy;
|
|
switch (mod->GetAxis()) {
|
|
case 0:
|
|
sx = (float)fabs(p1.z-p2.z);
|
|
sy = (float)fabs(p1.y-p2.y);
|
|
break;
|
|
case 1:
|
|
sx = (float)fabs(p1.x-p2.x);
|
|
sy = (float)fabs(p1.z-p2.z);
|
|
break;
|
|
case 2:
|
|
sx = (float)fabs(p1.x-p2.x);
|
|
sy = (float)fabs(p1.y-p2.y);
|
|
break;
|
|
}
|
|
|
|
// Scale params instead of the matrix
|
|
TimeValue t = ip->GetTime();
|
|
mod->SetWidth(t,sx);
|
|
mod->SetLength(t,sy);
|
|
/*
|
|
if (sx>0.0f && sy>0.0f) {
|
|
ctm.PreScale(Point3(sx,sy,1.0f));
|
|
}
|
|
*/
|
|
|
|
// Plug-in the new value
|
|
SetXFormPacket pckt(ctm);
|
|
mod->tmControl->SetValue(ip->GetTime(), &pckt);
|
|
}
|
|
|
|
nodeList.DisposeTemporary();
|
|
ip->ReleaseViewport(vpt);
|
|
ip->RedrawViews(ip->GetTime());
|
|
}
|
|
|
|
int RegionFitMouseProc::proc(
|
|
HWND hWnd, int msg, int point, int flags, IPoint2 m)
|
|
{
|
|
switch (msg) {
|
|
case MOUSE_PROPCLICK:
|
|
ip->SetStdCommandMode(CID_OBJMOVE);
|
|
break;
|
|
|
|
case MOUSE_POINT:
|
|
if (point==0) {
|
|
om = m;
|
|
theHold.Begin();
|
|
ip->RedrawViews(ip->GetTime(),REDRAW_BEGIN);
|
|
} else {
|
|
theHold.Accept(0);
|
|
ip->RedrawViews(ip->GetTime(),REDRAW_END);
|
|
}
|
|
break;
|
|
|
|
case MOUSE_MOVE: {
|
|
theHold.Restore();
|
|
RegionFitMap(hWnd,m);
|
|
ip->RedrawViews(ip->GetTime(),REDRAW_INTERACTIVE);
|
|
break;
|
|
}
|
|
|
|
case MOUSE_ABORT:
|
|
theHold.Cancel();
|
|
ip->RedrawViews(ip->GetTime(),REDRAW_END);
|
|
break;
|
|
|
|
case MOUSE_FREEMOVE:
|
|
SetCursor(ip->GetSysCursor(SYSCUR_SELECT));
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void RegionFitMode::EnterMode()
|
|
{
|
|
mod->EnterRegionFit();
|
|
}
|
|
|
|
void RegionFitMode::ExitMode()
|
|
{
|
|
mod->ExitRegionFit();
|
|
}
|
|
|
|
|
|
//--- PickAcquire -------------------------------------------------------
|
|
|
|
|
|
static BOOL CALLBACK AcquireTypeDlgProc(
|
|
HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static int type = IDC_ACQUIRE_REL;
|
|
|
|
switch (msg) {
|
|
case WM_INITDIALOG:
|
|
CheckRadioButton(hWnd,IDC_ACQUIRE_REL,IDC_ACQUIRE_ABS,type);
|
|
CenterWindow(hWnd,GetParent(hWnd));
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDOK:
|
|
if (IsDlgButtonChecked(hWnd,IDC_ACQUIRE_REL))
|
|
type = IDC_ACQUIRE_REL;
|
|
else type = IDC_ACQUIRE_ABS;
|
|
EndDialog(hWnd,type);
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hWnd,-1);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL GetAcquireType(HWND hWnd,int &type)
|
|
{
|
|
type = DialogBox(
|
|
hInstance,
|
|
MAKEINTRESOURCE(IDD_MAP_ACQUIRE),
|
|
hWnd,
|
|
AcquireTypeDlgProc);
|
|
if (type<0) return FALSE;
|
|
else return TRUE;
|
|
}
|
|
|
|
MappingMod *PickAcquire::FindFirstMap(ReferenceTarget *ref)
|
|
{
|
|
MappingMod *mod;
|
|
if (mod = GetMappingInterface(ref)) {
|
|
if (!mod->TestAFlag(A_MOD_DISABLED)) return mod;
|
|
}
|
|
|
|
for (int i=ref->NumRefs()-1; i>=0; i--) {
|
|
ReferenceTarget *cref = ref->GetReference(i);
|
|
if (cref) {
|
|
if (mod = FindFirstMap(cref)) return mod;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
BOOL PickAcquire::Filter(INode *node)
|
|
{
|
|
MappingMod *amod = FindFirstMap(node->GetObjectRef());
|
|
if (amod!=mod && amod) return TRUE;
|
|
else return FALSE;
|
|
}
|
|
|
|
BOOL PickAcquire::HitTest(
|
|
IObjParam *ip,HWND hWnd,ViewExp *vpt,IPoint2 m,int flags)
|
|
{
|
|
INode *node =
|
|
ip->PickNode(hWnd,m,this);
|
|
return node ? TRUE : FALSE;
|
|
}
|
|
|
|
|
|
class PickAcquireSourceMC : public ModContextEnumProc {
|
|
public:
|
|
ModContext *mc;
|
|
PickAcquireSourceMC() {mc = NULL;}
|
|
BOOL proc(ModContext *mc) {
|
|
this->mc = mc;
|
|
return FALSE;
|
|
}
|
|
};
|
|
|
|
BOOL PickAcquire::Pick(IObjParam *ip,ViewExp *vpt)
|
|
{
|
|
INode *node = vpt->GetClosestHit();
|
|
assert(node);
|
|
MappingMod *amod = FindFirstMap(node->GetObjectRef());
|
|
if (amod) {
|
|
int type;
|
|
if (!GetAcquireType(ip->GetMAXHWnd(),type)) return TRUE;
|
|
|
|
// Get our node and mod context
|
|
ModContextList mcList;
|
|
INodeTab nodes;
|
|
ip->GetModContexts(mcList,nodes);
|
|
assert(nodes.Count());
|
|
|
|
// Get the source mod's mod context
|
|
PickAcquireSourceMC pasmc;
|
|
amod->EnumModContexts(&pasmc);
|
|
assert(pasmc.mc);
|
|
|
|
// Do it!
|
|
theHold.Begin();
|
|
AcquireMapping(mod,mcList[0],nodes[0],amod,pasmc.mc,node,type);
|
|
theHold.Accept(_T("Acquire Mapping"));
|
|
|
|
nodes.DisposeTemporary();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void PickAcquire::EnterMode(IObjParam *ip)
|
|
{
|
|
mod->EnterAcquire();
|
|
}
|
|
|
|
void PickAcquire::ExitMode(IObjParam *ip)
|
|
{
|
|
mod->ExitAcquire();
|
|
}
|
|
|
|
void PickAcquire::AcquireMapping(
|
|
MappingMod *toMod, ModContext *toMC, INode *toNode,
|
|
MappingMod *fromMod, ModContext *fromMC, INode *fromNode,
|
|
int type)
|
|
{
|
|
// Build the mats
|
|
Matrix3 fromNTM(1);
|
|
Matrix3 toNTM(1);
|
|
if (type==IDC_ACQUIRE_ABS) {
|
|
fromNTM = fromNode->GetObjectTM(ip->GetTime());
|
|
toNTM = toNode->GetObjectTM(ip->GetTime());
|
|
}
|
|
Matrix3 fromTM = fromMod->CompMatrix(ip->GetTime(),fromMC,&fromNTM,FALSE,type==IDC_ACQUIRE_ABS);
|
|
Matrix3 destTM = fromTM * Inverse(toNTM);
|
|
if (toMC->tm) destTM = destTM * (*toMC->tm);
|
|
|
|
if (type==IDC_ACQUIRE_ABS && toMod->TestAFlag(A_PLUGIN1)) {
|
|
switch (toMod->GetMapType()) {
|
|
case MAP_BOX:
|
|
case MAP_PLANAR:
|
|
destTM.PreRotateZ(-PI);
|
|
break;
|
|
|
|
case MAP_BALL:
|
|
case MAP_SPHERICAL:
|
|
case MAP_CYLINDRICAL:
|
|
destTM.PreRotateZ(-HALFPI);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set the TM
|
|
SetXFormPacket pckt(destTM);
|
|
toMod->tmControl->SetValue(ip->GetTime(),&pckt);
|
|
toMod->SetMapType(fromMod->GetMapType());
|
|
TimeValue t = ip->GetTime();
|
|
for (int i=0; i<3; i++) {
|
|
toMod->SetTile(t, i, fromMod->GetTile(t,i));
|
|
toMod->SetFlip(i, fromMod->GetFlip(i));
|
|
}
|
|
|
|
// Copy length/width/height
|
|
toMod->SetLength(t,fromMod->GetLength(t));
|
|
toMod->SetWidth(t,fromMod->GetWidth(t));
|
|
toMod->SetHeight(t,fromMod->GetHeight(t));
|
|
if (type!=IDC_ACQUIRE_ABS) {
|
|
toMod->SetAxis(fromMod->GetAxis());
|
|
} else {
|
|
toMod->SetAxis(2);
|
|
}
|
|
|
|
ip->RedrawViews(ip->GetTime());
|
|
}
|
|
|
|
|
|
//--- MapDlgProc -----------------------------------------------------
|
|
|
|
class MapDlgProc : public ParamMapUserDlgProc {
|
|
public:
|
|
MapMod *mod;
|
|
MapDlgProc(MapMod *m) {mod = m;}
|
|
BOOL DlgProc(TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
|
|
void DeleteThis() {delete this;}
|
|
void DoBitmapFit(HWND hWnd);
|
|
};
|
|
|
|
void MapDlgProc::DoBitmapFit(HWND hWnd)
|
|
{
|
|
BitmapInfo bi;
|
|
TheManager->SelectFileInputEx(
|
|
&bi, hWnd, GetString(IDS_RB_SELECTIMAGE));
|
|
if (bi.Name()[0]) {
|
|
TheManager->GetImageInfo(&bi);
|
|
mod->aspect = bi.Aspect() * float(bi.Width())/float(bi.Height());
|
|
mod->flags |= CONTROL_ASPECT|CONTROL_HOLD;
|
|
mod->NotifyDependents(FOREVER,PART_TEXMAP,REFMSG_CHANGE);
|
|
}
|
|
}
|
|
|
|
BOOL MapDlgProc::DlgProc(
|
|
TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
|
{
|
|
switch (msg) {
|
|
case WM_INITDIALOG:
|
|
SendMessage(GetDlgItem(hWnd,IDC_MAP_FITREGION),CC_COMMAND,CC_CMD_SET_TYPE,CBT_CHECK);
|
|
SendMessage(GetDlgItem(hWnd,IDC_MAP_FITREGION),CC_COMMAND,CC_CMD_HILITE_COLOR,GREEN_WASH);
|
|
SendMessage(GetDlgItem(hWnd,IDC_MAP_NORMALALIGN),CC_COMMAND,CC_CMD_SET_TYPE,CBT_CHECK);
|
|
SendMessage(GetDlgItem(hWnd,IDC_MAP_NORMALALIGN),CC_COMMAND,CC_CMD_HILITE_COLOR,GREEN_WASH);
|
|
SendMessage(GetDlgItem(hWnd,IDC_MAP_ACQUIRE),CC_COMMAND,CC_CMD_SET_TYPE,CBT_CHECK);
|
|
SendMessage(GetDlgItem(hWnd,IDC_MAP_ACQUIRE),CC_COMMAND,CC_CMD_HILITE_COLOR,GREEN_WASH);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDC_MAP_SPHERE:
|
|
case IDC_MAP_BALL:
|
|
mod->flags |= CONTROL_UNIFORM|CONTROL_HOLD;
|
|
mod->NotifyDependents(FOREVER,PART_TEXMAP,REFMSG_CHANGE);
|
|
break;
|
|
|
|
case IDC_MAP_FIT:
|
|
mod->flags |= CONTROL_FIT|CONTROL_HOLD;
|
|
mod->NotifyDependents(FOREVER,PART_TEXMAP,REFMSG_CHANGE);
|
|
break;
|
|
|
|
case IDC_MAP_CENTER:
|
|
mod->flags |= CONTROL_CENTER|CONTROL_HOLD;
|
|
mod->NotifyDependents(FOREVER,PART_TEXMAP,REFMSG_CHANGE);
|
|
break;
|
|
|
|
case IDC_MAP_BITMAPFIT:
|
|
DoBitmapFit(hWnd);
|
|
break;
|
|
|
|
case IDC_MAP_ACQUIRE:
|
|
mod->ip->SetPickMode(&mod->pickAcquire);
|
|
break;
|
|
|
|
case IDC_MAP_NORMALALIGN:
|
|
if (mod->ip->GetCommandMode()->ID()==CID_FACEALIGNMAP) {
|
|
mod->ip->SetStdCommandMode(CID_OBJMOVE);
|
|
} else {
|
|
mod->ip->SetCommandMode(mod->faceAlignMode);
|
|
}
|
|
break;
|
|
|
|
case IDC_MAP_RESET:
|
|
theHold.Begin();
|
|
mod->ReplaceReference(TM_REF,NULL);
|
|
mod->flags |= CONTROL_FIT|CONTROL_CENTER|CONTROL_INIT;
|
|
theHold.Accept(0);
|
|
mod->NotifyDependents(FOREVER,PART_TEXMAP,REFMSG_CHANGE);
|
|
break;
|
|
|
|
case IDC_MAP_VIEWALIGN:
|
|
theHold.Begin();
|
|
mod->ViewportAlign();
|
|
theHold.Accept(0);
|
|
break;
|
|
|
|
case IDC_MAP_FITREGION:
|
|
if (mod->ip->GetCommandMode()->ID()==CID_REGIONFIT) {
|
|
mod->ip->SetStdCommandMode(CID_OBJMOVE);
|
|
} else {
|
|
mod->ip->SetCommandMode(mod->regionFitMode);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
//--- MapMod methods ---------------------------------------------------
|
|
|
|
|
|
MapMod::MapMod(BOOL create)
|
|
{
|
|
SetAFlag(A_PLUGIN1);
|
|
if (create) flags = CONTROL_CENTER|CONTROL_FIT|CONTROL_INIT;
|
|
else flags = 0;
|
|
|
|
MakeRefByID(FOREVER, PBLOCK_REF,
|
|
CreateParameterBlock(descVer3, PBLOCK_LENGTH, CURRENT_VERSION));
|
|
tmControl = NULL;
|
|
pblock->SetValue(PB_UTILE,0,1.0f);
|
|
pblock->SetValue(PB_VTILE,0,1.0f);
|
|
pblock->SetValue(PB_WTILE,0,1.0f);
|
|
pblock->SetValue(PB_WIDTH,0,1.0f);
|
|
pblock->SetValue(PB_LENGTH,0,1.0f);
|
|
pblock->SetValue(PB_HEIGHT,0,1.0f);
|
|
pblock->SetValue(PB_AXIS,0,2);
|
|
}
|
|
|
|
#define NEWMAP_CHUNKID 0x0100
|
|
|
|
|
|
IOResult MapMod::Load(ILoad *iload)
|
|
{
|
|
Modifier::Load(iload);
|
|
|
|
ClearAFlag(A_PLUGIN1);
|
|
|
|
IOResult res;
|
|
while (IO_OK==(res=iload->OpenChunk())) {
|
|
switch (iload->CurChunkID()) {
|
|
case NEWMAP_CHUNKID:
|
|
SetAFlag(A_PLUGIN1);
|
|
break;
|
|
}
|
|
iload->CloseChunk();
|
|
if (res!=IO_OK) return res;
|
|
}
|
|
|
|
iload->RegisterPostLoadCallback(
|
|
new FixDimsPLCB(this));
|
|
|
|
iload->RegisterPostLoadCallback(
|
|
new ParamBlockPLCB(versions,NUM_OLDVERSIONS,&curVersion,this,PBLOCK_REF));
|
|
|
|
return IO_OK;
|
|
}
|
|
|
|
IOResult MapMod::Save(ISave *isave)
|
|
{
|
|
Modifier::Save(isave);
|
|
if (TestAFlag(A_PLUGIN1)) {
|
|
isave->BeginChunk(NEWMAP_CHUNKID);
|
|
isave->EndChunk();
|
|
}
|
|
return IO_OK;
|
|
}
|
|
|
|
void MapMod::BeginEditParams(IObjParam *ip, ULONG flags,Animatable *prev)
|
|
{
|
|
this->ip = ip;
|
|
editMod = this;
|
|
|
|
// Add our sub object type
|
|
TSTR type1( GetString(IDS_RB_APPARATUS));
|
|
const TCHAR *ptype[] = {type1};
|
|
ip->RegisterSubObjectTypes(ptype, 1);
|
|
|
|
// Create sub object editing modes.
|
|
moveMode = new MoveModBoxCMode(this,ip);
|
|
rotMode = new RotateModBoxCMode(this,ip);
|
|
uscaleMode = new UScaleModBoxCMode(this,ip);
|
|
nuscaleMode = new NUScaleModBoxCMode(this,ip);
|
|
squashMode = new SquashModBoxCMode(this,ip);
|
|
faceAlignMode = new FaceAlignMode(this,ip);
|
|
regionFitMode = new RegionFitMode(this,ip);
|
|
|
|
pickAcquire.mod = this;
|
|
pickAcquire.ip = ip;
|
|
|
|
pmapParam = CreateCPParamMap(
|
|
descParam,PARAMDESC_LENGH,
|
|
pblock,
|
|
ip,
|
|
hInstance,
|
|
MAKEINTRESOURCE(IDD_UVWMAPPARAM),
|
|
GetString(IDS_RB_PARAMETERS),
|
|
0);
|
|
pmapParam->SetUserDlgProc(new MapDlgProc(this));
|
|
|
|
TimeValue t = ip->GetTime();
|
|
NotifyDependents(Interval(t,t), PART_ALL, REFMSG_BEGIN_EDIT);
|
|
NotifyDependents(Interval(t,t), PART_ALL, REFMSG_MOD_DISPLAY_ON);
|
|
SetAFlag(A_MOD_BEING_EDITED);
|
|
}
|
|
|
|
void MapMod::EndEditParams(IObjParam *ip, ULONG flags,Animatable *next)
|
|
{
|
|
this->ip = NULL;
|
|
editMod = NULL;
|
|
|
|
TimeValue t = ip->GetTime();
|
|
ClearAFlag(A_MOD_BEING_EDITED);
|
|
NotifyDependents(Interval(t,t), PART_ALL, REFMSG_END_EDIT);
|
|
NotifyDependents(Interval(t,t), PART_ALL, REFMSG_MOD_DISPLAY_OFF);
|
|
|
|
ip->ClearPickMode();
|
|
pickAcquire.mod = NULL;
|
|
pickAcquire.ip = NULL;
|
|
|
|
ip->DeleteMode(moveMode);
|
|
ip->DeleteMode(rotMode);
|
|
ip->DeleteMode(uscaleMode);
|
|
ip->DeleteMode(nuscaleMode);
|
|
ip->DeleteMode(squashMode);
|
|
ip->DeleteMode(faceAlignMode);
|
|
ip->DeleteMode(regionFitMode);
|
|
delete moveMode; moveMode = NULL;
|
|
delete rotMode; rotMode = NULL;
|
|
delete uscaleMode; uscaleMode = NULL;
|
|
delete nuscaleMode; nuscaleMode = NULL;
|
|
delete squashMode; squashMode = NULL;
|
|
delete faceAlignMode; faceAlignMode = NULL;
|
|
delete regionFitMode; regionFitMode = NULL;
|
|
|
|
DestroyCPParamMap(pmapParam);
|
|
}
|
|
|
|
void MapMod::EnterNormalAlign()
|
|
{
|
|
SendMessage(GetDlgItem(pmapParam->GetHWnd(),IDC_MAP_NORMALALIGN),CC_COMMAND,CC_CMD_SET_STATE,1);
|
|
}
|
|
|
|
void MapMod::ExitNormalAlign()
|
|
{
|
|
SendMessage(GetDlgItem(pmapParam->GetHWnd(),IDC_MAP_NORMALALIGN),CC_COMMAND,CC_CMD_SET_STATE,0);
|
|
}
|
|
|
|
void MapMod::EnterRegionFit()
|
|
{
|
|
SendMessage(GetDlgItem(pmapParam->GetHWnd(),IDC_MAP_FITREGION),CC_COMMAND,CC_CMD_SET_STATE,1);
|
|
}
|
|
|
|
void MapMod::ExitRegionFit()
|
|
{
|
|
SendMessage(GetDlgItem(pmapParam->GetHWnd(),IDC_MAP_FITREGION),CC_COMMAND,CC_CMD_SET_STATE,0);
|
|
}
|
|
|
|
void MapMod::EnterAcquire()
|
|
{
|
|
SendMessage(GetDlgItem(pmapParam->GetHWnd(),IDC_MAP_ACQUIRE),CC_COMMAND,CC_CMD_SET_STATE,1);
|
|
}
|
|
|
|
void MapMod::ExitAcquire()
|
|
{
|
|
SendMessage(GetDlgItem(pmapParam->GetHWnd(),IDC_MAP_ACQUIRE),CC_COMMAND,CC_CMD_SET_STATE,0);
|
|
}
|
|
|
|
float MapMod::GetLength(TimeValue t)
|
|
{
|
|
float f;
|
|
pblock->GetValue(PB_LENGTH,t,f,FOREVER);
|
|
return f;
|
|
}
|
|
|
|
float MapMod::GetWidth(TimeValue t)
|
|
{
|
|
float f;
|
|
pblock->GetValue(PB_WIDTH,t,f,FOREVER);
|
|
return f;
|
|
}
|
|
|
|
float MapMod::GetHeight(TimeValue t)
|
|
{
|
|
float f;
|
|
pblock->GetValue(PB_HEIGHT,t,f,FOREVER);
|
|
return f;
|
|
}
|
|
|
|
int MapMod::GetAxis()
|
|
{
|
|
int a;
|
|
pblock->GetValue(PB_AXIS,0,a,FOREVER);
|
|
return a;
|
|
}
|
|
|
|
void MapMod::SetLength(TimeValue t,float v)
|
|
{
|
|
pblock->SetValue(PB_LENGTH,t,v);
|
|
}
|
|
|
|
void MapMod::SetWidth(TimeValue t,float v)
|
|
{
|
|
pblock->SetValue(PB_WIDTH,t,v);
|
|
}
|
|
|
|
void MapMod::SetHeight(TimeValue t,float v)
|
|
{
|
|
pblock->SetValue(PB_HEIGHT,t,v);
|
|
}
|
|
|
|
void MapMod::SetAxis(int v)
|
|
{
|
|
pblock->SetValue(PB_AXIS,0,v);
|
|
}
|
|
|
|
int MapMod::GetMapType()
|
|
{
|
|
int type;
|
|
pblock->GetValue(PB_MAPTYPE,0,type,FOREVER);
|
|
return type;
|
|
}
|
|
|
|
void MapMod::SetMapType(int type)
|
|
{
|
|
pblock->SetValue(PB_MAPTYPE,0,type);
|
|
if (pmapParam) pmapParam->Invalidate();
|
|
}
|
|
|
|
float MapMod::GetTile(TimeValue t,int which)
|
|
{
|
|
float tile;
|
|
pblock->GetValue(PB_UTILE+which,t,tile,FOREVER);
|
|
return tile;
|
|
}
|
|
|
|
void MapMod::SetTile(TimeValue t,int which, float tile)
|
|
{
|
|
pblock->SetValue(PB_UTILE+which,t,tile);
|
|
if (pmapParam) pmapParam->Invalidate();
|
|
}
|
|
|
|
BOOL MapMod::GetFlip(int which)
|
|
{
|
|
int flip;
|
|
pblock->GetValue(PB_UFLIP+which,0,flip,FOREVER);
|
|
return flip;
|
|
}
|
|
|
|
void MapMod::SetFlip(int which,BOOL flip)
|
|
{
|
|
pblock->SetValue(PB_UFLIP+which,0,flip);
|
|
if (pmapParam) pmapParam->Invalidate();
|
|
}
|
|
|
|
Interval MapMod::LocalValidity(TimeValue t)
|
|
{
|
|
int i;
|
|
float f;
|
|
Interval valid = FOREVER;
|
|
pblock->GetValue(PB_MAPTYPE,t,i,valid);
|
|
pblock->GetValue(PB_UTILE,t,f,valid);
|
|
pblock->GetValue(PB_VTILE,t,f,valid);
|
|
pblock->GetValue(PB_WTILE,t,f,valid);
|
|
pblock->GetValue(PB_UFLIP,t,i,valid);
|
|
pblock->GetValue(PB_VFLIP,t,i,valid);
|
|
pblock->GetValue(PB_WFLIP,t,i,valid);
|
|
pblock->GetValue(PB_LENGTH,t,f,valid);
|
|
pblock->GetValue(PB_WIDTH,t,f,valid);
|
|
pblock->GetValue(PB_HEIGHT,t,f,valid);
|
|
pblock->GetValue(PB_AXIS,t,i,valid);
|
|
if (tmControl) {
|
|
Matrix3 tm(1);
|
|
tmControl->GetValue(t,&tm,valid,CTRL_RELATIVE);
|
|
}
|
|
return valid;
|
|
}
|
|
|
|
RefTargetHandle MapMod::Clone(RemapDir& remap)
|
|
{
|
|
MapMod* newmod = new MapMod(FALSE);
|
|
if (TestAFlag(A_PLUGIN1))
|
|
newmod->SetAFlag(A_PLUGIN1);
|
|
else newmod->ClearAFlag(A_PLUGIN1);
|
|
newmod->ReplaceReference(PBLOCK_REF,pblock->Clone(remap));
|
|
if (tmControl) {
|
|
newmod->ReplaceReference(TM_REF,tmControl->Clone(remap));
|
|
}
|
|
return newmod;
|
|
}
|
|
|
|
BOOL MapMod::AssignController(Animatable *control,int subAnim)
|
|
{
|
|
if (subAnim==TM_REF) {
|
|
ReplaceReference(TM_REF,(ReferenceTarget*)control);
|
|
NotifyDependents(FOREVER,0,REFMSG_CONTROLREF_CHANGE);
|
|
NotifyDependents(FOREVER,0,REFMSG_CHANGE);
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
int MapMod::SubNumToRefNum(int subNum)
|
|
{
|
|
if (subNum==TM_REF)
|
|
return TM_REF;
|
|
else return -1;
|
|
}
|
|
|
|
RefTargetHandle MapMod::GetReference(int i)
|
|
{
|
|
switch (i) {
|
|
case TM_REF: return tmControl;
|
|
case PBLOCK_REF: return pblock;
|
|
default: return NULL;
|
|
}
|
|
}
|
|
|
|
void MapMod::SetReference(int i, RefTargetHandle rtarg)
|
|
{
|
|
switch (i) {
|
|
case TM_REF: tmControl = (Control*)rtarg; break;
|
|
case PBLOCK_REF: pblock = (IParamBlock*)rtarg; break;
|
|
}
|
|
}
|
|
|
|
Animatable* MapMod::SubAnim(int i)
|
|
{
|
|
switch (i) {
|
|
case TM_REF: return tmControl;
|
|
case PBLOCK_REF: return pblock;
|
|
default: return NULL;
|
|
}
|
|
}
|
|
|
|
TSTR MapMod::SubAnimName(int i)
|
|
{
|
|
switch (i) {
|
|
case TM_REF: return GetString(IDS_RB_GIZMO);
|
|
case PBLOCK_REF: return GetString(IDS_RB_PARAMETERS);
|
|
default: return TSTR(_T(""));
|
|
}
|
|
}
|
|
|
|
RefResult MapMod::NotifyRefChanged(
|
|
Interval changeInt,
|
|
RefTargetHandle hTarget,
|
|
PartID& partID,
|
|
RefMessage message)
|
|
{
|
|
switch (message) {
|
|
case REFMSG_CHANGE:
|
|
if (editMod==this && pmapParam) pmapParam->Invalidate();
|
|
break;
|
|
|
|
case REFMSG_GET_PARAM_DIM: {
|
|
GetParamDim *gpd = (GetParamDim*)partID;
|
|
switch (gpd->index) {
|
|
case PB_LENGTH:
|
|
case PB_WIDTH:
|
|
case PB_HEIGHT: gpd->dim = stdWorldDim; break;
|
|
default: gpd->dim = defaultDim; break;
|
|
}
|
|
return REF_STOP;
|
|
}
|
|
|
|
case REFMSG_GET_PARAM_NAME: {
|
|
GetParamName *gpn = (GetParamName*)partID;
|
|
switch (gpn->index) {
|
|
case PB_UTILE: gpn->name = GetString(IDS_RB_UTILE); break;
|
|
case PB_VTILE: gpn->name = GetString(IDS_RB_VTILE); break;
|
|
case PB_WTILE: gpn->name = GetString(IDS_RB_WTILE); break;
|
|
case PB_LENGTH: gpn->name = GetString(IDS_RB_LENGTH); break;
|
|
case PB_WIDTH: gpn->name = GetString(IDS_RB_WIDTH); break;
|
|
case PB_HEIGHT: gpn->name = GetString(IDS_RB_HEIGHT); break;
|
|
default: gpn->name = TSTR(_T("")); break;
|
|
}
|
|
return REF_STOP;
|
|
}
|
|
}
|
|
return REF_SUCCEED;
|
|
}
|
|
|
|
|
|
void MapMod::ActivateSubobjSel(int level, XFormModes& modes )
|
|
{
|
|
switch (level) {
|
|
case 1: // Modifier box
|
|
modes = XFormModes(moveMode,rotMode,nuscaleMode,uscaleMode,squashMode,NULL);
|
|
break;
|
|
}
|
|
NotifyDependents(FOREVER,PART_DISPLAY,REFMSG_CHANGE);
|
|
}
|
|
|
|
|
|
// --- Modify Object ---------------------------------------------------
|
|
|
|
|
|
void MapMod::ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node)
|
|
{
|
|
// If it's not a mappable object then we can't help
|
|
Object *obj = os->obj;
|
|
if (!obj->IsMappable()) return;
|
|
|
|
// Get pblock values
|
|
int type, uflip, vflip, wflip, cap, channel;
|
|
float utile, vtile, wtile;
|
|
pblock->GetValue(PB_MAPTYPE,t,type,FOREVER);
|
|
pblock->GetValue(PB_UTILE,t,utile,FOREVER);
|
|
pblock->GetValue(PB_VTILE,t,vtile,FOREVER);
|
|
pblock->GetValue(PB_WTILE,t,wtile,FOREVER);
|
|
pblock->GetValue(PB_UFLIP,t,uflip,FOREVER);
|
|
pblock->GetValue(PB_VFLIP,t,vflip,FOREVER);
|
|
pblock->GetValue(PB_WFLIP,t,wflip,FOREVER);
|
|
pblock->GetValue(PB_CAP,t,cap,FOREVER);
|
|
pblock->GetValue(PB_CHANNEL,t,channel,FOREVER);
|
|
|
|
// Prepare the controller and set up mats
|
|
if (!tmControl || (flags&CONTROL_OP) || (flags&CONTROL_INITPARAMS))
|
|
InitControl(mc,obj,type,t);
|
|
Matrix3 tm;
|
|
tm = Inverse(CompMatrix(t,&mc,NULL));
|
|
|
|
obj->ApplyUVWMap(type,utile,vtile,wtile,uflip,vflip,wflip,cap,tm,channel);
|
|
|
|
// The tex mapping depends on the geom and topo so make sure the validity interval reflects this.
|
|
Interval iv = LocalValidity(t);
|
|
iv = iv & os->obj->ChannelValidity(t,GEOM_CHAN_NUM);
|
|
iv = iv & os->obj->ChannelValidity(t,TOPO_CHAN_NUM);
|
|
os->obj->UpdateValidity(TEXMAP_CHAN_NUM,iv);
|
|
}
|
|
|
|
|
|
|
|
|
|
static int lStart[12] = {0,1,3,2,4,5,7,6,0,1,2,3};
|
|
static int lEnd[12] = {1,3,2,0,5,7,6,4,4,5,6,7};
|
|
|
|
static void DoBoxIcon(BOOL sel,float length, PolyLineProc& lp)
|
|
{
|
|
Point3 pt[3];
|
|
|
|
length *= 0.5f;
|
|
Box3 box;
|
|
box.pmin = Point3(-length,-length,-length);
|
|
box.pmax = Point3( length, length, length);
|
|
|
|
if (sel) //lp.SetLineColor(1.0f,1.0f,0.0f);
|
|
lp.SetLineColor(GetUIColor(COLOR_SEL_GIZMOS));
|
|
else //lp.SetLineColor(0.85f,0.5f,0.0f);
|
|
lp.SetLineColor(GetUIColor(COLOR_GIZMOS));
|
|
|
|
for (int i=0; i<12; i++) {
|
|
pt[0] = box[lStart[i]];
|
|
pt[1] = box[lEnd[i]];
|
|
lp.proc(pt,2);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//--- MappingMod methods -----------------------------------------------
|
|
|
|
void* MappingMod::GetInterface(ULONG id)
|
|
{
|
|
if (id==I_MAPPINGINTERFACE) return this;
|
|
else return Modifier::GetInterface(id);
|
|
}
|
|
|
|
|
|
void MappingMod::InitControl(
|
|
ModContext &mc,Object *obj,int type,TimeValue t)
|
|
{
|
|
Box3 box;
|
|
Matrix3 tm;
|
|
|
|
if (tmControl==NULL) {
|
|
MakeRefByID(FOREVER,0,NewDefaultMatrix3Controller());
|
|
NotifyDependents(FOREVER,0,REFMSG_CONTROLREF_CHANGE);
|
|
}
|
|
|
|
if (flags&CONTROL_INIT) {
|
|
SuspendAnimate();
|
|
AnimateOff();
|
|
// Rotate the seem to the back
|
|
SetXFormPacket pckt(Quat(RotateZMatrix(PI)),TRUE);
|
|
tmControl->SetValue(t,&pckt,TRUE,CTRL_RELATIVE);
|
|
ResumeAnimate();
|
|
}
|
|
|
|
if (flags&CONTROL_INITPARAMS) {
|
|
SetLength(0,2.0f);
|
|
SetWidth(0,2.0f);
|
|
if (type==MAP_BALL ||
|
|
type==MAP_SPHERICAL ||
|
|
type==MAP_BOX) {
|
|
SetHeight(0,2.0f);
|
|
} else {
|
|
SetHeight(0,1.0f);
|
|
}
|
|
SetAxis(2);
|
|
}
|
|
|
|
if (!(flags&CONTROL_OP)) {
|
|
flags = 0;
|
|
return;
|
|
}
|
|
|
|
if (flags&CONTROL_HOLD) theHold.Begin();
|
|
|
|
Matrix3 oldtm = tm = Inverse(CompMatrix(t,&mc,NULL,FALSE));
|
|
AffineParts parts;
|
|
decomp_affine(tm, &parts);
|
|
parts.q.MakeMatrix(tm);
|
|
tm.Translate(parts.t);
|
|
|
|
Matrix3 mctm(1);
|
|
if (mc.tm) mctm = *mc.tm;
|
|
tm.Scale(Point3(
|
|
Length(mctm.GetRow(0)),
|
|
Length(mctm.GetRow(1)),
|
|
Length(mctm.GetRow(2))
|
|
));
|
|
|
|
Point3 s;
|
|
s.x = GetWidth(t);
|
|
s.y = GetLength(t);
|
|
s.z = GetHeight(t);
|
|
obj->GetDeformBBox(t,box,&tm,TRUE);
|
|
box.Scale(1.001f); // prevent wrap-around on sides of boxes
|
|
|
|
if (flags&CONTROL_ASPECT &&
|
|
(type==MAP_PLANAR ||
|
|
type==MAP_BOX ||
|
|
type==MAP_CYLINDRICAL)) {
|
|
|
|
if (type==MAP_PLANAR || type==MAP_BOX) {
|
|
float w = aspect*s.y;
|
|
s.x *= w / s.x;
|
|
s.z *= s.y / s.z;
|
|
} else
|
|
if (type==MAP_CYLINDRICAL) {
|
|
float w = (s.x+s.y)*PI;
|
|
s.z *= w/(aspect*s.z);
|
|
}
|
|
}
|
|
|
|
if (flags&CONTROL_UNIFORM) {
|
|
float av = (s.x + s.y + s.z)/3.0f;
|
|
s.x = s.y = s.z = av;
|
|
}
|
|
|
|
if (flags&CONTROL_FIT) {
|
|
Point3 w = box.Width();
|
|
if (box.IsEmpty()) w = Point3(10.0f,10.0f,10.0f);
|
|
|
|
if (type==MAP_PLANAR) {
|
|
s.x = w.x==0.0f ? 1.0f : w.x;
|
|
s.y = w.y==0.0f ? 1.0f : w.y;
|
|
s.z = w.z==0.0f ? 1.0f : w.z;
|
|
} else
|
|
if (type==MAP_BOX) {
|
|
s.x = w.x==0.0f ? 1.0f : w.x;
|
|
s.y = w.y==0.0f ? 1.0f : w.y;
|
|
s.z = w.z==0.0f ? 1.0f : w.z;
|
|
} else
|
|
if (type==MAP_SPHERICAL || type==MAP_BALL) {
|
|
float max = w.x;
|
|
if (w.y>max) max = w.y;
|
|
if (w.z>max) max = w.z;
|
|
if (max==0.0f) max = 1.0f;
|
|
s.x = s.y = s.z = max;
|
|
} else {
|
|
if (w.x>w.y) s.x = s.y = w.x;
|
|
else s.x = s.y = w.y;
|
|
s.z = w.z;
|
|
if (s.x==0.0f) s.x = 1.0f;
|
|
if (s.y==0.0f) s.y = 1.0f;
|
|
if (s.z==0.0f) s.z = 1.0f;
|
|
}
|
|
}
|
|
|
|
if (flags&(CONTROL_CENTER|CONTROL_FIT)) {
|
|
|
|
Box3 sbox;
|
|
obj->GetDeformBBox(t,sbox,&oldtm,TRUE);
|
|
|
|
Point3 cent = sbox.Center();
|
|
cent = VectorTransform(Inverse(oldtm),cent);
|
|
cent = VectorTransform(mctm,cent);
|
|
|
|
SetXFormPacket pckt(
|
|
cent, //sbox.Center(),
|
|
Matrix3(1),
|
|
Matrix3(1));
|
|
//Inverse(oldtm));
|
|
|
|
SuspendAnimate();
|
|
AnimateOff();
|
|
tmControl->SetValue(t,&pckt,TRUE,CTRL_RELATIVE);
|
|
ResumeAnimate();
|
|
}
|
|
|
|
if (flags&(CONTROL_FIT|CONTROL_ASPECT|CONTROL_INITPARAMS|CONTROL_UNIFORM)) {
|
|
SuspendAnimate();
|
|
AnimateOff();
|
|
|
|
// Clear out any scale in the transform
|
|
tm = Matrix3(1);
|
|
tmControl->GetValue(t,&tm,FOREVER,CTRL_RELATIVE);
|
|
decomp_affine(tm, &parts);
|
|
parts.q.MakeMatrix(tm);
|
|
tm.Translate(parts.t);
|
|
SetXFormPacket pckt(tm);
|
|
tmControl->SetValue(t,&pckt,TRUE,CTRL_ABSOLUTE);
|
|
|
|
// Set the new dimensions
|
|
SetLength(t,s.y);
|
|
SetWidth(t,s.x);
|
|
SetHeight(t,s.z);
|
|
|
|
ResumeAnimate();
|
|
}
|
|
|
|
if (flags&CONTROL_HOLD) theHold.Accept(0);
|
|
flags = 0;
|
|
}
|
|
|
|
|
|
#if 0
|
|
void MappingMod::InitControl(ModContext &mc,Object *obj,int type,TimeValue t)
|
|
{
|
|
Box3 box;
|
|
Matrix3 tm;
|
|
|
|
if (tmControl==NULL) {
|
|
MakeRefByID(FOREVER,0,NewDefaultMatrix3Controller());
|
|
NotifyDependents(FOREVER,0,REFMSG_CONTROLREF_CHANGE);
|
|
}
|
|
|
|
if (flags&CONTROL_HOLD) theHold.Begin();
|
|
if (flags&CONTROL_INIT) {
|
|
SuspendAnimate();
|
|
AnimateOff();
|
|
// Rotate the seem to the back
|
|
SetXFormPacket pckt(Quat(RotateZMatrix(PI)),TRUE);
|
|
tmControl->SetValue(t,&pckt,TRUE,CTRL_RELATIVE);
|
|
}
|
|
|
|
tm = Inverse(CompMatrix(t,&mc,NULL));
|
|
obj->GetDeformBBox(t,box,&tm,TRUE);
|
|
box.Scale(1.001f); // prevent wrap-around on sides of boxes
|
|
|
|
if (flags&CONTROL_ASPECT &&
|
|
(type==MAP_PLANAR ||
|
|
type==MAP_BOX ||
|
|
type==MAP_CYLINDRICAL)) {
|
|
Matrix3 tm(1), id(1);
|
|
Interval valid;
|
|
tmControl->GetValue(t,&tm,valid,CTRL_RELATIVE);
|
|
Point3 s;
|
|
|
|
if (type==MAP_PLANAR || type==MAP_BOX) {
|
|
float w = aspect*Length(tm.GetRow(1));
|
|
s.x = w / Length(tm.GetRow(0));
|
|
s.y = 1.0f;
|
|
s.z = Length(tm.GetRow(1)) / Length(tm.GetRow(2));
|
|
/*
|
|
float a = (Length(tm.GetRow(0))+Length(tm.GetRow(1))+Length(tm.GetRow(2)))/3.0f;
|
|
s.x = aspect*a / Length(tm.GetRow(0));
|
|
s.y = a / Length(tm.GetRow(1));
|
|
s.z = a / Length(tm.GetRow(2));
|
|
*/
|
|
} else
|
|
if (type==MAP_CYLINDRICAL) {
|
|
// Old way where we sized the radius
|
|
/*
|
|
float lz = Length(tm.GetRow(2));
|
|
float rad = lz*aspect/(TWOPI);
|
|
s.x = rad / Length(tm.GetRow(0));
|
|
s.y = rad / Length(tm.GetRow(1));
|
|
s.z = 1.0f;
|
|
*/
|
|
// Now we size the height
|
|
float w = (Length(tm.GetRow(0))+Length(tm.GetRow(1)))*PI;
|
|
s.x = 1.0f;
|
|
s.y = 1.0f;
|
|
s.z = w/(aspect*Length(tm.GetRow(2)));
|
|
}
|
|
|
|
SetXFormPacket pckt(s,TRUE,id,tm);
|
|
tmControl->SetValue(t,&pckt,TRUE,CTRL_RELATIVE);
|
|
}
|
|
|
|
if (flags&CONTROL_UNIFORM) {
|
|
Matrix3 tm(1), id(1);
|
|
Interval valid;
|
|
tmControl->GetValue(t,&tm,valid,CTRL_RELATIVE);
|
|
float av = 0.0f;
|
|
Point3 s;
|
|
av += Length(tm.GetRow(0));
|
|
av += Length(tm.GetRow(1));
|
|
av += Length(tm.GetRow(2));
|
|
av /= 3.0f;
|
|
s.x = av/Length(tm.GetRow(0));
|
|
s.y = av/Length(tm.GetRow(1));
|
|
s.z = av/Length(tm.GetRow(2));
|
|
|
|
SetXFormPacket pckt(s,TRUE,id,tm);
|
|
tmControl->SetValue(t,&pckt,TRUE,CTRL_RELATIVE);
|
|
}
|
|
|
|
if (flags&CONTROL_FIT) {
|
|
|
|
// Get the box of the object in mod context space but unscaled
|
|
Matrix3 mat = tm;
|
|
mat.NoScale();
|
|
obj->GetDeformBBox(t,box,&mat,TRUE);
|
|
box.Scale(1.001f); // prevent wrap-around on sides of boxes
|
|
|
|
Point3 s, w = box.Width();
|
|
if (box.IsEmpty()) w = Point3(10.0f,10.0f,10.0f);
|
|
Matrix3 tm(1), id(1);
|
|
Interval valid;
|
|
tmControl->GetValue(t,&tm,valid,CTRL_RELATIVE);
|
|
|
|
if (type==MAP_PLANAR) {
|
|
s.x = w.x==0.0f ? 1.0f : w.x/2.0f;
|
|
s.y = w.y==0.0f ? 1.0f : w.y/2.0f;
|
|
s.z = w.z==0.0f ? 1.0f : w.z;
|
|
} else
|
|
if (type==MAP_BOX) {
|
|
s.x = w.x==0.0f ? 1.0f : w.x/2.0f;
|
|
s.y = w.y==0.0f ? 1.0f : w.y/2.0f;
|
|
s.z = w.z==0.0f ? 1.0f : w.z/2.0f;
|
|
} else
|
|
if (type==MAP_SPHERICAL || type==MAP_BALL) {
|
|
float max = w.x;
|
|
if (w.y>max) max = w.y;
|
|
if (w.z>max) max = w.z;
|
|
if (max==0.0f) max = 1.0f;
|
|
s.x = s.y = s.z = max/2.0f;
|
|
} else {
|
|
if (w.x>w.y) s.x = s.y = w.x/2.0f;
|
|
else s.x = s.y = w.y/2.0f;
|
|
s.z = w.z;
|
|
if (s.x==0.0f) s.x = 1.0f;
|
|
if (s.y==0.0f) s.y = 1.0f;
|
|
if (s.z==0.0f) s.z = 1.0f;
|
|
}
|
|
|
|
s.x /= Length(tm.GetRow(0));
|
|
s.y /= Length(tm.GetRow(1));
|
|
s.z /= Length(tm.GetRow(2));
|
|
|
|
SetXFormPacket pckt(s,TRUE,id,tm);
|
|
tmControl->SetValue(t,&pckt,TRUE,CTRL_RELATIVE);
|
|
|
|
// redo the box so our center op works
|
|
tm = Inverse(CompMatrix(t,&mc,NULL));
|
|
obj->GetDeformBBox(t,box,&tm,TRUE);
|
|
box.Scale(1.001f); // prevent wrap-around on sides of boxes
|
|
}
|
|
|
|
if (flags&(CONTROL_CENTER|CONTROL_FIT)) {
|
|
Matrix3 tm(1);
|
|
Interval valid;
|
|
tmControl->GetValue(t,&tm,valid,CTRL_RELATIVE);
|
|
SetXFormPacket pckt(VectorTransform(tm,box.Center()));
|
|
tmControl->SetValue(t,&pckt,TRUE,CTRL_RELATIVE);
|
|
}
|
|
|
|
if (flags&CONTROL_HOLD) theHold.Accept(0);
|
|
if (flags&CONTROL_INIT) {
|
|
ResumeAnimate();
|
|
}
|
|
|
|
flags = 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
// --- Gizmo transformations ------------------------------------------
|
|
|
|
void MappingMod::Move(
|
|
TimeValue t, Matrix3& partm, Matrix3& tmAxis,
|
|
Point3& val, BOOL localOrigin)
|
|
{
|
|
#ifdef DESIGN_VER
|
|
t=0;
|
|
#endif
|
|
assert(tmControl);
|
|
SetXFormPacket pckt(val,partm,tmAxis);
|
|
tmControl->SetValue(t,&pckt,TRUE,CTRL_RELATIVE);
|
|
}
|
|
|
|
|
|
void MappingMod::Rotate(
|
|
TimeValue t, Matrix3& partm, Matrix3& tmAxis,
|
|
Quat& val, BOOL localOrigin)
|
|
{
|
|
#ifdef DESIGN_VER
|
|
t=0;
|
|
#endif
|
|
assert(tmControl);
|
|
SetXFormPacket pckt(val,localOrigin,partm,tmAxis);
|
|
tmControl->SetValue(t,&pckt,TRUE,CTRL_RELATIVE);
|
|
}
|
|
|
|
void MappingMod::Scale(
|
|
TimeValue t, Matrix3& partm, Matrix3& tmAxis,
|
|
Point3& val, BOOL localOrigin)
|
|
{
|
|
#ifdef DESIGN_VER
|
|
t=0;
|
|
#endif
|
|
assert(tmControl);
|
|
SetXFormPacket pckt(val,localOrigin,partm,tmAxis);
|
|
tmControl->SetValue(t,&pckt,TRUE,CTRL_RELATIVE);
|
|
}
|
|
|
|
|
|
Matrix3 MappingMod::CompMatrix(
|
|
TimeValue t,ModContext *mc, Matrix3 *ntm,BOOL applySize, BOOL applyAxis)
|
|
{
|
|
Matrix3 tm(1);
|
|
Interval valid;
|
|
|
|
int type = GetMapType();
|
|
|
|
if (tmControl) {
|
|
tmControl->GetValue(t,&tm,valid,CTRL_RELATIVE);
|
|
}
|
|
|
|
// Rotate icon
|
|
if (applyAxis && TestAFlag(A_PLUGIN1)) {
|
|
switch (type) {
|
|
case MAP_BOX:
|
|
case MAP_PLANAR:
|
|
tm.PreRotateZ(PI);
|
|
break;
|
|
|
|
case MAP_BALL:
|
|
case MAP_SPHERICAL:
|
|
case MAP_CYLINDRICAL:
|
|
tm.PreRotateZ(HALFPI);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (applyAxis) {
|
|
switch (GetAxis()) {
|
|
case 0:
|
|
tm.PreRotateY(-HALFPI);
|
|
break;
|
|
case 1:
|
|
tm.PreRotateX(HALFPI);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (applySize) {
|
|
Point3 s;
|
|
s.x = GetWidth(t);
|
|
s.y = GetLength(t);
|
|
s.z = GetHeight(t);
|
|
switch (type) {
|
|
case MAP_CYLINDRICAL:
|
|
case MAP_PLANAR:
|
|
s.x *= 0.5f;
|
|
s.y *= 0.5f;
|
|
break;
|
|
|
|
case MAP_BALL:
|
|
case MAP_SPHERICAL:
|
|
case MAP_BOX:
|
|
s *= 0.5f;
|
|
break;
|
|
}
|
|
tm.PreScale(s);
|
|
}
|
|
|
|
if (mc && mc->tm) {
|
|
tm = tm * Inverse(*mc->tm);
|
|
}
|
|
if (ntm) {
|
|
tm = tm * *ntm;
|
|
}
|
|
return tm;
|
|
}
|
|
|
|
|
|
void MappingMod::DoIcon(PolyLineProc& lp,BOOL sel)
|
|
{
|
|
int type = GetMapType();
|
|
switch (type) {
|
|
case MAP_BOX: DoBoxIcon(sel,2.0f,lp); break;
|
|
case MAP_PLANAR: DoPlanarMapIcon(sel,2.0f,2.0f,lp); break;
|
|
case MAP_BALL:
|
|
case MAP_SPHERICAL: DoSphericalMapIcon(sel,1.0f,lp); break;
|
|
case MAP_CYLINDRICAL: DoCylindricalMapIcon(sel,1.0f,1.0f,lp); break;
|
|
}
|
|
}
|
|
|
|
int MappingMod::HitTest(
|
|
TimeValue t, INode* inode, int type, int crossing,
|
|
int flags, IPoint2 *p, ViewExp *vpt, ModContext* mc)
|
|
{
|
|
int savedLimits;
|
|
GraphicsWindow *gw = vpt->getGW();
|
|
HitRegion hr;
|
|
MakeHitRegion(hr,type, crossing,4,p);
|
|
gw->setHitRegion(&hr);
|
|
Matrix3 modmat, ntm = inode->GetObjectTM(t);
|
|
DrawLineProc lp(gw);
|
|
|
|
gw->setRndLimits(((savedLimits = gw->getRndLimits()) | GW_PICK) & ~GW_ILLUM);
|
|
gw->clearHitCode();
|
|
|
|
if (ip && ip->GetSubObjectLevel() == 1) {
|
|
modmat = CompMatrix(t,mc,&ntm);
|
|
gw->setTransform(modmat);
|
|
DoIcon(lp,FALSE);
|
|
}
|
|
|
|
gw->setRndLimits(savedLimits);
|
|
if (gw->checkHitCode()) {
|
|
vpt->LogHit(inode, mc, gw->getHitDistance(), 0, NULL);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int MappingMod::Display(
|
|
TimeValue t, INode* inode, ViewExp *vpt, int flags,
|
|
ModContext *mc)
|
|
{
|
|
GraphicsWindow *gw = vpt->getGW();
|
|
Matrix3 modmat, ntm = inode->GetObjectTM(t);
|
|
DrawLineProc lp(gw);
|
|
|
|
modmat = CompMatrix(t,mc,&ntm);
|
|
gw->setTransform(modmat);
|
|
DoIcon(lp, ip&&ip->GetSubObjectLevel()==1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void MappingMod::GetWorldBoundBox(
|
|
TimeValue t,INode* inode, ViewExp *vpt, Box3& box,
|
|
ModContext *mc)
|
|
{
|
|
Matrix3 modmat, ntm = inode->GetObjTMBeforeWSM(t);
|
|
modmat = CompMatrix(t,mc,&ntm);
|
|
BoxLineProc bproc(&modmat);
|
|
DoIcon(bproc,FALSE);
|
|
box = bproc.Box();
|
|
}
|
|
|
|
void MappingMod::GetSubObjectCenters(
|
|
SubObjAxisCallback *cb,TimeValue t,INode *node,ModContext *mc)
|
|
{
|
|
Matrix3 modmat, ntm = node->GetObjectTM(t);
|
|
modmat = CompMatrix(t,mc,&ntm);
|
|
cb->Center(modmat.GetTrans(),0);
|
|
}
|
|
|
|
void MappingMod::GetSubObjectTMs(
|
|
SubObjAxisCallback *cb,TimeValue t,INode *node,ModContext *mc)
|
|
{
|
|
Matrix3 ntm = node->GetObjectTM(t), modmat;
|
|
modmat = CompMatrix(t,mc,&ntm);
|
|
cb->TM(modmat,0);
|
|
}
|
|
|
|
void FixDimsPLCB::proc(ILoad *iload)
|
|
{
|
|
if (mod->GetPBlockVersion()<mod->GetFirstParamVer()) {
|
|
mod->flags |= CONTROL_INITPARAMS;
|
|
}
|
|
delete this;
|
|
}
|