2012-05-29 13:31:11 +00:00
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
*<
|
|
|
|
FILE: editpat.h
|
|
|
|
|
|
|
|
DESCRIPTION: Edit Patch OSM
|
|
|
|
|
|
|
|
CREATED BY: Tom Hudson, Dan Silva & Rolf Berteig
|
|
|
|
|
|
|
|
HISTORY: created 23 June 1995
|
|
|
|
|
|
|
|
*> Copyright (c) 1995, All Rights Reserved.
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef __EDITPATCH_H__
|
|
|
|
#define __EDITPATCH_H__
|
|
|
|
|
|
|
|
#include "mods.h"
|
|
|
|
#include "modsres.h"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <list>
|
|
|
|
|
|
|
|
#include <nel/misc/rgba.h>
|
|
|
|
#include <nel/3d/quad_tree.h>
|
|
|
|
#include <nel/3d/tile_bank.h>
|
|
|
|
|
|
|
|
#include "../nel_patch_lib/rpo.h"
|
|
|
|
#include "../nel_patch_lib/vertex_neighborhood.h"
|
|
|
|
|
|
|
|
// For MAX_RELEASE
|
|
|
|
#include <plugapi.h>
|
|
|
|
|
|
|
|
namespace NL3D
|
|
|
|
{
|
|
|
|
class CCamera;
|
|
|
|
class CViewport;
|
|
|
|
class CLandscape;
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace NL3D;
|
|
|
|
using namespace NLMISC;
|
|
|
|
|
|
|
|
#define Alert(x) MessageBox(GetActiveWindow(),x,_T("Alert"),MB_OK);
|
|
|
|
|
|
|
|
#define EDITPAT_CHANNELS (PART_GEOM|SELECT_CHANNEL|PART_SUBSEL_TYPE|PART_DISPLAY|PART_TOPO|TEXMAP_CHANNEL)
|
|
|
|
#define CID_EP_PAINT CID_EP_BEVEL+5
|
|
|
|
|
|
|
|
// These are values for selLevel.
|
|
|
|
#define EP_OBJECT 0
|
|
|
|
#define EP_VERTEX 1
|
|
|
|
#define EP_EDGE 2
|
|
|
|
#define EP_PATCH 3
|
|
|
|
#define EP_TILE 4
|
|
|
|
|
|
|
|
#define COLOR_BRUSH_STEP 10
|
|
|
|
#define COLOR_BRUSH_MIN (2.f)
|
|
|
|
#define COLOR_BRUSH_MAX (32.f)
|
|
|
|
|
|
|
|
// Named selection set levels:
|
|
|
|
#define EP_NS_VERTEX 0
|
|
|
|
#define EP_NS_EDGE 1
|
|
|
|
#define EP_NS_PATCH 2
|
|
|
|
// Conversion from selLevel to named selection level:
|
|
|
|
static int namedSetLevel[] = { EP_NS_VERTEX, EP_NS_VERTEX, EP_NS_EDGE, EP_NS_PATCH };
|
|
|
|
static int namedClipLevel[] = { CLIP_P_VERT, CLIP_P_VERT, CLIP_P_EDGE, CLIP_P_PATCH };
|
|
|
|
|
|
|
|
#define MAX_MATID 0xffff
|
|
|
|
|
|
|
|
#define UNDEFINED 0xffffffff
|
|
|
|
|
|
|
|
#define CID_EPM_BIND CID_USER + 203
|
|
|
|
#define CID_EPM_EXTRUDE CID_USER + 204
|
|
|
|
#define CID_EPM_BEVEL CID_USER + 205
|
|
|
|
|
|
|
|
class EditPatchMod;
|
|
|
|
class CNelPatchChanger;
|
|
|
|
|
|
|
|
#define BRUSH_COUNT 3
|
|
|
|
|
|
|
|
// Advanced TessApprox settings...
|
|
|
|
class AdvParams
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
TessSubdivStyle mStyle;
|
|
|
|
int mMin, mMax;
|
|
|
|
int mTris;
|
|
|
|
};
|
|
|
|
|
|
|
|
class PatchRightMenu : public RightClickMenu
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
EditPatchMod *ep;
|
|
|
|
public:
|
|
|
|
void Init(RightClickMenuManager* manager, HWND hWnd, IPoint2 m);
|
|
|
|
void Selected(UINT id);
|
|
|
|
void SetMod(EditPatchMod *ep) { this->ep = ep; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class EPM_BindMouseProc : public MouseCallBack
|
|
|
|
{
|
|
|
|
friend class MouseListener;
|
|
|
|
private:
|
|
|
|
EditPatchMod *pobj;
|
|
|
|
IObjParam *ip;
|
|
|
|
IPoint2 om;
|
|
|
|
BitArray knotList;
|
|
|
|
PatchMesh *pMesh;
|
|
|
|
RPatchMesh *rpMesh;
|
|
|
|
CVertexNeighborhood tab;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
HCURSOR GetTransformCursor();
|
|
|
|
BOOL HitAKnot(ViewExp *vpt, IPoint2 *p, int *vert);
|
|
|
|
BOOL HitASegment(ViewExp *vpt, IPoint2 *p, int *Seg);
|
|
|
|
|
|
|
|
BOOL HitTest( ViewExp *vpt, IPoint2 *p, int type, int flags, int subType );
|
|
|
|
BOOL AnyHits( ViewExp *vpt ) { return vpt->NumSubObjHits(); }
|
|
|
|
|
|
|
|
public:
|
|
|
|
EPM_BindMouseProc(EditPatchMod* spl, IObjParam *i) { pobj=spl; ip=i; }
|
|
|
|
int proc(
|
|
|
|
HWND hwnd,
|
|
|
|
int msg,
|
|
|
|
int point,
|
|
|
|
int flags,
|
|
|
|
IPoint2 m );
|
|
|
|
};
|
|
|
|
|
|
|
|
struct EPM_Mesh
|
|
|
|
{
|
|
|
|
EPM_Mesh (PatchMesh *pmesh, RPatchMesh *rmesh, class EditPatchData *patchData, INode* node, ModContext *mod, int mcListIndex)
|
|
|
|
{
|
|
|
|
PMesh=pmesh;
|
|
|
|
RMesh=rmesh;
|
|
|
|
PatchData=patchData;
|
|
|
|
Node=node;
|
|
|
|
Mod=mod;
|
|
|
|
McListIndex=mcListIndex;
|
|
|
|
}
|
|
|
|
PatchMesh *PMesh;
|
|
|
|
RPatchMesh *RMesh;
|
|
|
|
INode *Node;
|
|
|
|
ModContext *Mod;
|
|
|
|
int McListIndex;
|
|
|
|
class EditPatchData *PatchData;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct EPM_PaintVertex
|
|
|
|
{
|
|
|
|
EPM_PaintVertex (sint32 mesh, sint32 vert)
|
|
|
|
{
|
|
|
|
Mesh=mesh;
|
|
|
|
vertex=vert;
|
|
|
|
}
|
|
|
|
sint32 Mesh;
|
|
|
|
sint32 vertex;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct EPM_PaintTile
|
|
|
|
{
|
|
|
|
EPM_PaintTile ()
|
|
|
|
{
|
|
|
|
Mesh=-1;
|
|
|
|
}
|
|
|
|
EPM_PaintTile* get2Voisin (int i)
|
|
|
|
{
|
|
|
|
if (voisins[i])
|
|
|
|
{
|
|
|
|
return voisins[i]->voisins[(i+rotate[i])&3];
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
int get2VoisinRotate (int i)
|
|
|
|
{
|
|
|
|
if (voisins[i])
|
|
|
|
{
|
|
|
|
return rotate[i]+voisins[i]->rotate[(i+rotate[i])&3];
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
EPM_PaintTile* getRight256 (int rot, int& _rotate)
|
|
|
|
{
|
|
|
|
_rotate=rotate[(2+rot)&3];
|
|
|
|
return voisins[(2+rot)&3];
|
|
|
|
}
|
|
|
|
EPM_PaintTile* getBottom256 (int rot, int& _rotate)
|
|
|
|
{
|
|
|
|
_rotate=rotate[(1+rot)&3];
|
|
|
|
return voisins[(1+rot)&3];
|
|
|
|
}
|
|
|
|
EPM_PaintTile* getRightBottom256 (int rot, int& _rotate)
|
|
|
|
{
|
|
|
|
int rightRot;
|
|
|
|
EPM_PaintTile* right=getRight256 (rot, rightRot);
|
|
|
|
if (right)
|
|
|
|
return right->getBottom256 ((rot-rightRot)&3, _rotate);
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
EPM_PaintTile* getBottomRight256 (int rot, int& _rotate)
|
|
|
|
{
|
|
|
|
int bottomRot;
|
|
|
|
EPM_PaintTile* bottom=getBottom256 (rot, bottomRot);
|
|
|
|
if (bottom)
|
|
|
|
return bottom->getRight256 ((rot-bottomRot)&3, _rotate);
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
bool validFor256 (int rot)
|
|
|
|
{
|
|
|
|
int _rotate;
|
|
|
|
if (!getRight256 (rot, _rotate))
|
|
|
|
return false;
|
|
|
|
if (!getBottom256 (rot, _rotate))
|
|
|
|
return false;
|
|
|
|
if (!getRightBottom256 (rot, _rotate))
|
|
|
|
return false;
|
|
|
|
if (getRightBottom256 (rot, _rotate)!=getBottomRight256 (rot, _rotate))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
void set256 (int rotate)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
bool intersect (const Ray& ray, std::vector<EPM_Mesh>& vectMesh, TimeValue t, NLMISC::CVector& hit);
|
|
|
|
sint32 patch;
|
|
|
|
sint32 tile;
|
|
|
|
sint16 Mesh;
|
|
|
|
uint8 u;
|
|
|
|
uint8 v;
|
|
|
|
EPM_PaintTile* voisins[4];
|
|
|
|
uint8 rotate[4];
|
|
|
|
CVector Center;
|
|
|
|
float Radius;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct EPM_PaintPatch
|
|
|
|
{
|
|
|
|
enum TBorder {left=0, bottom, right, top, count};
|
|
|
|
EPM_PaintPatch ()
|
|
|
|
{
|
|
|
|
Mesh=-1;
|
|
|
|
}
|
|
|
|
EPM_PaintPatch (sint32 mesh, sint32 p)
|
|
|
|
{
|
|
|
|
Mesh=mesh;
|
|
|
|
patch=p;
|
|
|
|
}
|
|
|
|
sint32 Mesh;
|
|
|
|
sint32 patch;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
class tileSetIndex
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
int TileSet;
|
|
|
|
int Rotate;
|
|
|
|
bool operator< (const tileSetIndex& other) const
|
|
|
|
{
|
|
|
|
if (TileSet<other.TileSet)
|
|
|
|
return true;
|
|
|
|
if (TileSet>other.TileSet)
|
|
|
|
return false;
|
|
|
|
int delta=(other.Rotate-Rotate)&3;
|
|
|
|
if (delta==1)
|
|
|
|
return true;
|
|
|
|
if (delta==3)
|
|
|
|
return false;
|
|
|
|
if (delta==0)
|
|
|
|
return false;
|
|
|
|
nlassert (0); // no!
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bool operator!= (const tileSetIndex& other) const
|
|
|
|
{
|
|
|
|
return ((TileSet!=other.TileSet)||(Rotate!=other.Rotate));
|
|
|
|
}
|
|
|
|
bool operator== (const tileSetIndex& other) const
|
|
|
|
{
|
|
|
|
return ((TileSet==other.TileSet)&&(Rotate==other.Rotate));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
class CBackupValue
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// Ctor
|
|
|
|
CBackupValue () {}
|
|
|
|
CBackupValue (const tileDesc& desc, uint mesh, uint tile) : Desc (desc), Mesh (mesh), Tile (tile)
|
|
|
|
{}
|
|
|
|
|
|
|
|
// Public data
|
|
|
|
tileDesc Desc;
|
|
|
|
uint Mesh;
|
|
|
|
uint Tile;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
class EPM_PaintMouseProc : public MouseCallBack
|
|
|
|
{
|
|
|
|
friend class MouseListener;
|
|
|
|
friend DWORD WINAPI myThread (LPVOID vData);
|
|
|
|
friend class CTileUndo;
|
|
|
|
friend class CPaintColor;
|
|
|
|
friend class CFillPatch;
|
|
|
|
|
|
|
|
private:
|
|
|
|
EditPatchMod *pobj;
|
|
|
|
IObjParam *ip;
|
|
|
|
IPoint2 om;
|
|
|
|
//PatchMesh *pMesh;
|
|
|
|
//sint32 Mesh;
|
|
|
|
//std::map<PatchMesh* ,sint32 > metaMeshIndex;
|
|
|
|
std::vector<std::vector<EPM_PaintTile> > metaTile;
|
|
|
|
std::vector<BitArray> bitArray;
|
|
|
|
int Rotation;
|
|
|
|
int TileIndex;
|
|
|
|
CQuadTree<EPM_PaintTile*> quadTreeSelect;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
// Paint algorithm
|
|
|
|
void SetTile (int mesh, int tile, const tileDesc& desc, std::vector<EPM_Mesh>& vectMesh, CLandscape* land, CNelPatchChanger& nelPatchChg,
|
|
|
|
std::vector<CBackupValue>* backupStack, bool undo=true, bool updateDisplace=false);
|
|
|
|
|
|
|
|
// Get a tile
|
|
|
|
void GetTile (int mesh, int tile, tileDesc& desc, std::vector<EPM_Mesh>& vectMesh, CLandscape* land);
|
|
|
|
|
|
|
|
bool PutATile ( EPM_PaintTile* pTile, int tileSet, int curRotation, const NL3D::CTileBank& bank,
|
|
|
|
bool selectCycle, std::set<EPM_PaintTile*>& visited, std::vector<EPM_Mesh>& vectMesh,
|
|
|
|
NL3D::CLandscape* land, CNelPatchChanger& nelPatchChg, bool _256);
|
|
|
|
|
|
|
|
void PutADisplacetile ( EPM_PaintTile* pTile, const CTileBank& bank,
|
|
|
|
std::vector<EPM_Mesh>& vectMesh,
|
|
|
|
CLandscape* land, CNelPatchChanger& nelPatchChg);
|
|
|
|
|
|
|
|
BOOL PutDisplace (int tile, int mesh, const CTileBank& bank, std::vector<EPM_Mesh>& vectMesh, CLandscape* land,
|
|
|
|
int recurs, std::set<EPM_PaintTile*>& alreadyRecursed, CNelPatchChanger& nelPatchChg);
|
|
|
|
|
|
|
|
int selectTile (uint tileSet, bool selectCycle, bool _256, uint group, const CTileBank& bank);
|
|
|
|
bool GetBorderDesc (EPM_PaintTile* tile, tileSetIndex *pVoisinCorner, NL3D::CTileSet::TFlagBorder pBorder[4][3],
|
|
|
|
tileDesc *pVoisinIndex, const NL3D::CTileBank& bank, std::vector<EPM_Mesh>& vectMesh, CNelPatchChanger& nelPatchChg);
|
|
|
|
|
|
|
|
const NL3D::CTileSetTransition* FindTransition (int nTileSet, int nRotate, const NL3D::CTileSet::TFlagBorder *border,
|
|
|
|
const NL3D::CTileBank& bank);
|
|
|
|
bool PropagateBorder (EPM_PaintTile* tile, int curRotation, int curTileSet, std::set<EPM_PaintTile*>& visited,
|
|
|
|
const NL3D::CTileBank& bank, std::vector<EPM_Mesh>& vectMesh, NL3D::CLandscape* land, CNelPatchChanger& nelPatchChg,
|
|
|
|
std::vector<CBackupValue>& backupStack, bool recurseNoDiff=true);
|
|
|
|
|
|
|
|
// Calc rotate path
|
|
|
|
uint8 CalcRotPath (EPM_PaintTile* from, EPM_PaintTile* to, int depth, int rotate, int& deltaX, int& deltaY, int& cost);
|
|
|
|
|
|
|
|
// Just put a tile
|
|
|
|
BOOL PutTile (int tile, int mesh, bool first, const NL3D::CTileBank& bank, int tileSet, std::vector<EPM_Mesh>& vectMesh, NL3D::CLandscape* land,
|
|
|
|
int recurs, std::set<EPM_PaintTile*>& alreadyRecursed, CNelPatchChanger& nelPatchChg, bool _256);
|
|
|
|
|
|
|
|
void RecursTile (EPM_PaintTile* pTile, const CTileBank& bank, int tileSet, std::vector<EPM_Mesh>& vectMesh, CLandscape* land, int recurs,
|
|
|
|
std::set<EPM_PaintTile*>& alreadyRecursed, bool first, int rotation, CNelPatchChanger& nelPatchChg, bool _256);
|
|
|
|
|
|
|
|
|
|
|
|
BOOL HitATile(ViewExp *vpt, IPoint2 *p, int *tile, int *mesh, TimeValue t, std::vector<EPM_Mesh>& vectMesh, NLMISC::CVector& hit);
|
|
|
|
BOOL HitATile(const CViewport& viewport, const CCamera& camera, float x, float y, int *tile, int *mesh, TimeValue t, std::vector<EPM_Mesh>& vectMesh, NLMISC::CVector& hit);
|
|
|
|
BOOL AnyHits( ViewExp *vpt )
|
|
|
|
{
|
|
|
|
return vpt->NumSubObjHits();
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
EPM_PaintMouseProc(EditPatchMod* spl, IObjParam *i)
|
|
|
|
{
|
|
|
|
pobj=spl;
|
|
|
|
ip=i;
|
|
|
|
TileIndex=0;
|
|
|
|
|
|
|
|
// Init plane matrix XY
|
|
|
|
NLMISC::CMatrix tmp;
|
|
|
|
NLMISC::CVector I(1,0,0);
|
|
|
|
NLMISC::CVector J(0,0,-1);
|
|
|
|
NLMISC::CVector K(0,1,0);
|
|
|
|
tmp.identity();
|
|
|
|
tmp.setRot(I,J,K, true);
|
|
|
|
quadTreeSelect.changeBase (tmp);
|
|
|
|
}
|
|
|
|
int proc(
|
|
|
|
HWND hwnd,
|
|
|
|
int msg,
|
|
|
|
int point,
|
|
|
|
int flags,
|
|
|
|
IPoint2 m );
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class EPM_BindCMode : public CommandMode
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
ChangeFGObject fgProc;
|
|
|
|
EPM_BindMouseProc eproc;
|
|
|
|
EditPatchMod* pobj;
|
|
|
|
// int type; // See above
|
|
|
|
|
|
|
|
public:
|
|
|
|
EPM_BindCMode(EditPatchMod* spl, IObjParam *i) :
|
|
|
|
fgProc((ReferenceTarget*)spl), eproc(spl,i) {pobj=spl;}
|
|
|
|
|
|
|
|
int Class() { return MODIFY_COMMAND; }
|
|
|
|
int ID() { return CID_EP_BIND; }
|
|
|
|
MouseCallBack *MouseProc(int *numPoints) { *numPoints=2; return &eproc; }
|
|
|
|
ChangeForegroundCallback *ChangeFGProc() { return &fgProc; }
|
|
|
|
BOOL ChangeFG( CommandMode *oldMode ) { return oldMode->ChangeFGProc() != &fgProc; }
|
|
|
|
void EnterMode();
|
|
|
|
void ExitMode();
|
|
|
|
// void SetType(int type) { this->type = type; eproc.SetType(type); }
|
|
|
|
};
|
|
|
|
|
|
|
|
class EPM_ExtrudeMouseProc : public MouseCallBack {
|
|
|
|
private:
|
|
|
|
MoveTransformer moveTrans;
|
|
|
|
EditPatchMod *po;
|
|
|
|
Interface *ip;
|
|
|
|
IPoint2 om;
|
|
|
|
Point3 ndir;
|
|
|
|
public:
|
|
|
|
EPM_ExtrudeMouseProc(EditPatchMod* o, IObjParam *i) : moveTrans(i) {po=o;ip=i;}
|
|
|
|
int proc(HWND hwnd, int msg, int point, int flags, IPoint2 m);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class EPM_ExtrudeSelectionProcessor : public GenModSelectionProcessor {
|
|
|
|
protected:
|
|
|
|
HCURSOR GetTransformCursor();
|
|
|
|
public:
|
|
|
|
EPM_ExtrudeSelectionProcessor(EPM_ExtrudeMouseProc *mc, EditPatchMod *o, IObjParam *i)
|
|
|
|
: GenModSelectionProcessor(mc,(BaseObject*) o,i) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class EPM_ExtrudeCMode : public CommandMode {
|
|
|
|
private:
|
|
|
|
ChangeFGObject fgProc;
|
|
|
|
EPM_ExtrudeSelectionProcessor mouseProc;
|
|
|
|
EPM_ExtrudeMouseProc eproc;
|
|
|
|
EditPatchMod* po;
|
|
|
|
|
|
|
|
public:
|
|
|
|
EPM_ExtrudeCMode(EditPatchMod* o, IObjParam *i) :
|
|
|
|
fgProc((ReferenceTarget *)o), mouseProc(&eproc,o,i), eproc(o,i) {po=o;}
|
|
|
|
int Class() { return MODIFY_COMMAND; }
|
|
|
|
int ID() { return CID_EPM_EXTRUDE; }
|
|
|
|
MouseCallBack *MouseProc(int *numPoints) { *numPoints=2; return &mouseProc; }
|
|
|
|
ChangeForegroundCallback *ChangeFGProc() { return &fgProc; }
|
|
|
|
BOOL ChangeFG( CommandMode *oldMode ) { return oldMode->ChangeFGProc() != &fgProc; }
|
|
|
|
void EnterMode();
|
|
|
|
void ExitMode();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class EPM_BevelMouseProc : public MouseCallBack {
|
|
|
|
private:
|
|
|
|
MoveTransformer moveTrans;
|
|
|
|
EditPatchMod *po;
|
|
|
|
Interface *ip;
|
|
|
|
IPoint2 om;
|
|
|
|
|
|
|
|
public:
|
|
|
|
EPM_BevelMouseProc(EditPatchMod* o, IObjParam *i) : moveTrans(i) {po=o;ip=i;}
|
|
|
|
int proc(HWND hwnd, int msg, int point, int flags, IPoint2 m);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class EPM_BevelSelectionProcessor : public GenModSelectionProcessor {
|
|
|
|
protected:
|
|
|
|
HCURSOR GetTransformCursor();
|
|
|
|
public:
|
|
|
|
EPM_BevelSelectionProcessor(EPM_BevelMouseProc *mc, EditPatchMod *o, IObjParam *i)
|
|
|
|
: GenModSelectionProcessor(mc,(BaseObject*) o,i) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class EPM_BevelCMode : public CommandMode {
|
|
|
|
private:
|
|
|
|
ChangeFGObject fgProc;
|
|
|
|
EPM_BevelSelectionProcessor mouseProc;
|
|
|
|
EPM_BevelMouseProc eproc;
|
|
|
|
EditPatchMod* po;
|
|
|
|
|
|
|
|
public:
|
|
|
|
EPM_BevelCMode(EditPatchMod* o, IObjParam *i) :
|
|
|
|
fgProc((ReferenceTarget *)o), mouseProc(&eproc,o,i), eproc(o,i) {po=o;}
|
|
|
|
int Class() { return MODIFY_COMMAND; }
|
|
|
|
int ID() { return CID_EPM_BEVEL; }
|
|
|
|
MouseCallBack *MouseProc(int *numPoints) { *numPoints=3; return &mouseProc; }
|
|
|
|
ChangeForegroundCallback *ChangeFGProc() { return &fgProc; }
|
|
|
|
BOOL ChangeFG( CommandMode *oldMode ) { return oldMode->ChangeFGProc() != &fgProc; }
|
|
|
|
void EnterMode();
|
|
|
|
void ExitMode();
|
|
|
|
};
|
|
|
|
|
|
|
|
class VertInsertRecord;
|
|
|
|
class PickPatchAttach;
|
|
|
|
|
|
|
|
class EditPatchMod : public Modifier, IPatchOps, IPatchSelect, ISubMtlAPI, AttachMatDlgUser
|
|
|
|
{
|
|
|
|
friend class EPTempData;
|
|
|
|
friend class EditPatchData;
|
|
|
|
friend class XFormProc;
|
|
|
|
friend class PatchRestore;
|
|
|
|
friend class PVertexRightMenu;
|
|
|
|
friend class PatchRightMenu;
|
|
|
|
friend class PickPatchAttach;
|
|
|
|
|
|
|
|
public:
|
|
|
|
static HWND hSelectPanel, hOpsPanel, hSurfPanel, hTilePanel, hEdgePanel;
|
|
|
|
static BOOL rsSel, rsOps, rsSurf, rsTile, rsEdge; // rollup states (FALSE = rolled up)
|
|
|
|
static IObjParam *ip;
|
|
|
|
|
|
|
|
static MoveModBoxCMode *moveMode;
|
|
|
|
static RotateModBoxCMode *rotMode;
|
|
|
|
static UScaleModBoxCMode *uscaleMode;
|
|
|
|
static NUScaleModBoxCMode *nuscaleMode;
|
|
|
|
static SquashModBoxCMode *squashMode;
|
|
|
|
static SelectModBoxCMode *selectMode;
|
|
|
|
static ISpinnerControl *weldSpin;
|
|
|
|
static ISpinnerControl *stepsSpin;
|
|
|
|
static ISpinnerControl *tileSpin;
|
|
|
|
static ISpinnerControl *transitionSpin;
|
|
|
|
//3-18-99 to suport render steps and removal of the mental tesselator
|
|
|
|
static ISpinnerControl *stepsRenderSpin;
|
|
|
|
static PickPatchAttach pickCB;
|
|
|
|
static BOOL patchUIValid;
|
|
|
|
static BOOL tileUIValid;
|
|
|
|
static BOOL edgeUIValid;
|
|
|
|
|
|
|
|
//watje command mode for the extrude and beevl
|
|
|
|
static EPM_ExtrudeCMode *extrudeMode;
|
|
|
|
static EPM_BevelCMode *bevelMode;
|
|
|
|
static EPM_BindCMode *bindMode;
|
|
|
|
|
|
|
|
// for the tessellation controls
|
|
|
|
static BOOL settingViewportTess; // are we doing viewport or renderer
|
|
|
|
static BOOL settingDisp; // if we're doign renderer is it mesh or displacmenent
|
|
|
|
static ISpinnerControl *uSpin;
|
|
|
|
static ISpinnerControl *vSpin;
|
|
|
|
static ISpinnerControl *edgeSpin;
|
|
|
|
static ISpinnerControl *angSpin;
|
|
|
|
static ISpinnerControl *distSpin;
|
|
|
|
static ISpinnerControl *mergeSpin;
|
|
|
|
static ISpinnerControl *matSpin;
|
|
|
|
static ISpinnerControl *tessUSpin;
|
|
|
|
static ISpinnerControl *tessVSpin;
|
|
|
|
static ISpinnerControl *tileNum;
|
|
|
|
static ISpinnerControl *tileRot;
|
|
|
|
static int attachMat;
|
|
|
|
static BOOL condenseMat;
|
|
|
|
static int CurrentTileSet;
|
|
|
|
static int brushSize;
|
|
|
|
static int ColorBushSize;
|
|
|
|
static int tileSize;
|
|
|
|
static int TileGroup; // Active group of tiles. 0: no gourp, 1-4: group 0 to 3
|
|
|
|
static int DisplaceTile; // Active displace tile
|
|
|
|
static int DisplaceTileSet; // Active tileset in displace
|
|
|
|
static uint TileFillRotation; // Rotation used in fill
|
|
|
|
static bool TileTrick; // Trick
|
|
|
|
static int tileSetSet;
|
|
|
|
static int channelModified;
|
|
|
|
static bool additiveTile;
|
|
|
|
static bool automaticLighting;
|
|
|
|
|
|
|
|
RefResult NotifyRefChanged( Interval changeInt,RefTargetHandle hTarget,
|
|
|
|
PartID& partID, RefMessage message ) { return REF_SUCCEED; }
|
|
|
|
|
|
|
|
int selLevel;
|
|
|
|
|
|
|
|
// RB:named sel sets
|
|
|
|
BOOL namedSelNeedsFixup; // TRUE for pre-r3 files
|
|
|
|
Tab<TSTR*> namedSel[5];
|
|
|
|
int FindSet(TSTR &setName,int level);
|
|
|
|
void AddSet(TSTR &setName,int level);
|
|
|
|
void RemoveSet(TSTR &setName,int level);
|
|
|
|
void RemoveAllSets();
|
|
|
|
void ClearSetNames();
|
|
|
|
|
|
|
|
// Remembered info
|
|
|
|
PatchMesh *rememberedPatch; // NULL if using all selected patches
|
|
|
|
int rememberedIndex;
|
|
|
|
int rememberedData;
|
|
|
|
|
|
|
|
BOOL displaySurface;
|
|
|
|
BOOL displayLattice;
|
|
|
|
int meshSteps;
|
|
|
|
//3-18-99 to suport render steps and removal of the mental tesselator
|
|
|
|
int meshStepsRender;
|
|
|
|
BOOL showInterior;
|
|
|
|
int tileLevel;
|
|
|
|
bool tileMode;
|
|
|
|
bool includeMeshes;
|
|
|
|
bool keepMapping;
|
|
|
|
int transitionType;
|
|
|
|
|
|
|
|
BOOL meshAdaptive; // Future use (Not used now)
|
|
|
|
TessApprox viewTess; // for GAP tessellation
|
|
|
|
TessApprox prodTess;
|
|
|
|
TessApprox dispTess;
|
|
|
|
|
|
|
|
BOOL mViewTessNormals; // use normals from the tesselator
|
|
|
|
BOOL mProdTessNormals; // use normals from the tesselator
|
|
|
|
BOOL mViewTessWeld; // Weld the mesh after tessellation
|
|
|
|
BOOL mProdTessWeld; // Weld the mesh after tessellation
|
|
|
|
BOOL propagate;
|
|
|
|
|
|
|
|
BOOL inExtrude;
|
|
|
|
BOOL inBevel;
|
|
|
|
|
|
|
|
|
|
|
|
EditPatchMod();
|
|
|
|
~EditPatchMod();
|
|
|
|
|
|
|
|
Interval LocalValidity(TimeValue t);
|
|
|
|
ChannelMask ChannelsUsed() { return EDITPAT_CHANNELS; }
|
|
|
|
ChannelMask ChannelsChanged() { return channelModified; }
|
|
|
|
void ModifyObject(TimeValue t, ModContext &mc, ObjectState *os, INode *node);
|
|
|
|
void NotifyInputChanged(Interval changeInt, PartID partID, RefMessage message, ModContext *mc);
|
|
|
|
Class_ID InputType() { return RYKOLPATCHOBJ_CLASS_ID; }
|
|
|
|
|
|
|
|
int CompMatrix(TimeValue t, ModContext& mc, Matrix3& tm, Interval& valid);
|
|
|
|
|
|
|
|
// From Animatable
|
|
|
|
void DeleteThis() { delete this; }
|
|
|
|
void GetClassName(TSTR& s) { s= TSTR(_T("EditPatchNeLMod")); }
|
|
|
|
Class_ID ClassID() { return Class_ID(0x4dd14a3c, 0x4ac23c0c); }
|
|
|
|
void* GetInterface(ULONG id);
|
|
|
|
|
|
|
|
// From BaseObject
|
|
|
|
int HitTest(TimeValue t, INode* inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt, ModContext* mc);
|
|
|
|
int Display(TimeValue t, INode* inode, ViewExp *vpt, int flagst, ModContext *mc);
|
|
|
|
void GetWorldBoundBox(TimeValue t,INode* inode, ViewExp *vpt, Box3& box, ModContext *mc);
|
|
|
|
|
|
|
|
void GetSubObjectCenters(SubObjAxisCallback *cb,TimeValue t,INode *node,ModContext *mc);
|
|
|
|
void GetSubObjectTMs(SubObjAxisCallback *cb,TimeValue t,INode *node,ModContext *mc);
|
|
|
|
int SubObjectIndex(HitRecord *hitRec);
|
|
|
|
|
|
|
|
BOOL DependOnTopology(ModContext &mc);
|
|
|
|
|
|
|
|
// Generic xform procedure.
|
|
|
|
void XFormVerts( XFormProc *xproc, TimeValue t, Matrix3& partm, Matrix3& tmAxis );
|
|
|
|
|
|
|
|
// Specialized xform for bezier handles
|
|
|
|
void XFormHandles( XFormProc *xproc, TimeValue t, Matrix3& partm, Matrix3& tmAxis, int object, int handleIndex );
|
|
|
|
|
|
|
|
// Affine transform methods
|
|
|
|
void Move( TimeValue t, Matrix3& partm, Matrix3& tmAxis, Point3& val, BOOL localOrigin=FALSE );
|
|
|
|
void Rotate( TimeValue t, Matrix3& partm, Matrix3& tmAxis, Quat& val, BOOL localOrigin=FALSE );
|
|
|
|
void Scale( TimeValue t, Matrix3& partm, Matrix3& tmAxis, Point3& val, BOOL localOrigin=FALSE );
|
|
|
|
|
|
|
|
// The following is called before the first Move(), Rotate() or Scale() call
|
|
|
|
void TransformStart(TimeValue t);
|
|
|
|
|
|
|
|
// The following is called after the user has completed the Move, Rotate or Scale operation and
|
|
|
|
// the undo object has been accepted.
|
|
|
|
void TransformFinish(TimeValue t);
|
|
|
|
|
|
|
|
// The following is called when the transform operation is cancelled by a right-click and the undo
|
|
|
|
// has been cancelled.
|
|
|
|
void TransformCancel(TimeValue t);
|
|
|
|
|
|
|
|
BOOL SupportsNamedSubSels() {return TRUE;}
|
|
|
|
void ActivateSubSelSet(TSTR &setName);
|
|
|
|
void NewSetFromCurSel(TSTR &setName);
|
|
|
|
void RemoveSubSelSet(TSTR &setName);
|
|
|
|
void SetupNamedSelDropDown();
|
|
|
|
int NumNamedSelSets();
|
|
|
|
TSTR GetNamedSelSetName(int i);
|
|
|
|
void SetNamedSelSetName(int i,TSTR &newName);
|
|
|
|
void NewSetByOperator(TSTR &newName,Tab<int> &sets,int op);
|
|
|
|
BOOL GetUniqueSetName(TSTR &name);
|
|
|
|
int SelectNamedSet();
|
|
|
|
void NSCopy();
|
|
|
|
void NSPaste();
|
|
|
|
void MaybeFixupNamedSels();
|
|
|
|
|
|
|
|
//watje 12-10-98
|
|
|
|
void DoHide(int type);
|
|
|
|
void DoUnHide();
|
|
|
|
void DoPatchHide();
|
|
|
|
void DoVertHide();
|
|
|
|
void DoEdgeHide();
|
|
|
|
|
|
|
|
void DoAddHook(PatchMesh *pMesh, int vert0, int vert1, int vert2, int seg, int config);
|
|
|
|
void DoRemoveHook();
|
|
|
|
|
|
|
|
//watje bevel and extrusion stuff
|
|
|
|
void DoExtrude() ;
|
|
|
|
void BeginExtrude(TimeValue t);
|
|
|
|
void EndExtrude (TimeValue t, BOOL accept=TRUE);
|
|
|
|
void Extrude( TimeValue t, float amount, BOOL useLocalNorm );
|
|
|
|
|
|
|
|
|
|
|
|
void DoBevel() ;
|
|
|
|
void BeginBevel(TimeValue t);
|
|
|
|
void EndBevel (TimeValue t, BOOL accept=TRUE);
|
|
|
|
void Bevel( TimeValue t, float amount, BOOL smoothStart, BOOL smoothEnd );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DoDeleteSelected();
|
|
|
|
void DoVertDelete();
|
|
|
|
void DoEdgeDelete();
|
|
|
|
void DoPatchDelete();
|
|
|
|
void DoPatchAdd(int type);
|
|
|
|
void DoSubdivide(int type);
|
|
|
|
void DoEdgeSubdivide();
|
|
|
|
void DoPatchSubdivide();
|
|
|
|
void DoVertWeld();
|
|
|
|
void DoVertReset();
|
|
|
|
void DoPatchDetach(int copy, int reorient);
|
|
|
|
void DoPatchTurn(bool ccw);
|
|
|
|
|
|
|
|
void ClearPatchDataFlag(ModContextList& mcList,DWORD f);
|
|
|
|
void DeletePatchDataTempData();
|
|
|
|
void CreatePatchDataTempData();
|
|
|
|
|
|
|
|
int NumRefs() { return 0; }
|
|
|
|
RefTargetHandle GetReference(int i) { return NULL; }
|
|
|
|
void SetReference(int i, RefTargetHandle rtarg) {}
|
|
|
|
|
|
|
|
void ChangeRememberedPatch(int type);
|
|
|
|
void ChangeSelPatches(int type);
|
|
|
|
int RememberPatchThere(HWND hWnd, IPoint2 m);
|
|
|
|
void SetRememberedPatchType(int type);
|
|
|
|
void ChangeRememberedVert(int type);
|
|
|
|
void ChangeSelVerts(int type);
|
|
|
|
int RememberVertThere(HWND hWnd, IPoint2 m);
|
|
|
|
void SetRememberedVertType(int type);
|
|
|
|
|
|
|
|
// IO
|
|
|
|
IOResult Save(ISave *isave);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
IOResult SaveLocalData(ISave *isave, LocalModData *ld);
|
|
|
|
IOResult LoadLocalData(ILoad *iload, LocalModData **pld);
|
|
|
|
IOResult LoadNamedSelChunk(ILoad *iload,int level);
|
|
|
|
|
|
|
|
CreateMouseCallBack* GetCreateMouseCallBack() { return NULL; }
|
|
|
|
void BeginEditParams( IObjParam *ip, ULONG flags, Animatable *prev );
|
|
|
|
void EndEditParams( IObjParam *ip, ULONG flags, Animatable *next );
|
|
|
|
RefTargetHandle Clone(RemapDir& remap = DefaultRemapDir());
|
|
|
|
TCHAR *GetObjectName() { return GetString(IDS_TH_EDITPATCH); }
|
|
|
|
void ActivateSubobjSel(int level, XFormModes& modes );
|
|
|
|
int NeedUseSubselButton() { return 0; }
|
|
|
|
void SelectSubComponent( HitRecord *hitRec, BOOL selected, BOOL all, BOOL invert );
|
|
|
|
void ClearSelection(int selLevel);
|
|
|
|
void SelectAll(int selLevel);
|
|
|
|
void InvertSelection(int selLevel);
|
|
|
|
|
|
|
|
void SetDisplaySurface(BOOL sw);
|
|
|
|
void SetDisplayLattice(BOOL sw);
|
|
|
|
void SetPropagate(BOOL sw);
|
|
|
|
BOOL GetPropagate() {return propagate;}
|
|
|
|
void SetMeshSteps(int count);
|
|
|
|
int GetMeshSteps() { return meshSteps; }
|
|
|
|
//3-18-99 to suport render steps and removal of the mental tesselator
|
|
|
|
void SetMeshStepsRender(int count);
|
|
|
|
int GetMeshStepsRender() { return meshStepsRender; }
|
|
|
|
void SetShowInterior(BOOL si);
|
|
|
|
BOOL GetShowInterior() { return showInterior; }
|
|
|
|
void SetTileSteps(int steps);
|
|
|
|
int GetTileLevel() { return tileLevel; }
|
|
|
|
void SetTileMode (bool bTile);
|
|
|
|
bool GetTileMode() { return tileMode; }
|
|
|
|
bool GetIncludeMeshes() { return includeMeshes; }
|
|
|
|
void SetKeepMapping (bool bKeep);
|
|
|
|
bool GetKeepMapping() { return keepMapping; }
|
|
|
|
int GetTransitionLevel() { return transitionType; }
|
|
|
|
void SetTransitionLevel(int transition);
|
|
|
|
|
|
|
|
// Future use (Not used now)
|
|
|
|
// void SetMeshAdaptive(BOOL sw);
|
|
|
|
void SetViewTess(TessApprox &tess);
|
|
|
|
TessApprox GetViewTess() { return viewTess; }
|
|
|
|
void SetProdTess(TessApprox &tess);
|
|
|
|
TessApprox GetProdTess() { return prodTess; }
|
|
|
|
void SetDispTess(TessApprox &tess);
|
|
|
|
TessApprox GetDispTess() { return dispTess; }
|
|
|
|
void SetTessUI(HWND hDlg, TessApprox *tess);
|
|
|
|
BOOL GetViewTessNormals() { return mViewTessNormals; }
|
|
|
|
void SetViewTessNormals(BOOL use);
|
|
|
|
BOOL GetProdTessNormals() { return mProdTessNormals; }
|
|
|
|
void SetProdTessNormals(BOOL use);
|
|
|
|
BOOL GetViewTessWeld() { return mViewTessWeld; }
|
|
|
|
void SetViewTessWeld(BOOL weld);
|
|
|
|
BOOL GetProdTessWeld() { return mProdTessWeld; }
|
|
|
|
void SetProdTessWeld(BOOL weld);
|
|
|
|
|
|
|
|
// Get the commonality of material index for the selection (-1 indicates no commonality)
|
|
|
|
int GetSelMatIndex();
|
|
|
|
void SetSelMatIndex(int index);
|
|
|
|
void SelectByMat(int index,BOOL clear);
|
|
|
|
|
|
|
|
// Tile tess
|
|
|
|
int GetSelTessU ();
|
|
|
|
int GetSelTessV ();
|
|
|
|
void SetSelTess (int nU, int nV);
|
|
|
|
void BalanceSelPatch (int patch, int size, bool balanceU, std::set<int>& visitedU, std::set<int>& visitedV, RPatchMesh* rpatch, PatchMesh *);
|
|
|
|
void BalanceSelPatch ();
|
|
|
|
|
|
|
|
// *** Smooth flags
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return 0 if no edge are selected or no selected edges have the flag set.
|
|
|
|
* Return 1 if all the selected edge have the flag set.
|
|
|
|
* Return 2 if some of the selected edge of the flag set but not all of them.
|
|
|
|
*/
|
|
|
|
int getSmoothFlags ();
|
|
|
|
|
|
|
|
/// Set the smmoth flag for the selected edges.
|
|
|
|
void setSmoothFlags (bool smooth);
|
|
|
|
|
|
|
|
/*void SetTileNum (ULONG nU);
|
|
|
|
ULONG GetTileNum ();
|
|
|
|
void SetTileRot (int nU);
|
|
|
|
int GetTileRot ();*/
|
|
|
|
|
|
|
|
// Smoothing
|
|
|
|
DWORD GetSelSmoothBits(DWORD &invalid);
|
|
|
|
DWORD GetUsedSmoothBits();
|
|
|
|
void SelectBySmoothGroup(DWORD bits,BOOL clear);
|
|
|
|
void SetSelSmoothBits(DWORD bits,DWORD which);
|
|
|
|
|
|
|
|
void PatchSelChanged();
|
|
|
|
|
|
|
|
// from AttachMatDlgUser
|
|
|
|
int GetAttachMat() { return attachMat; }
|
|
|
|
void SetAttachMat(int value) { attachMat = value; }
|
|
|
|
BOOL GetCondenseMat() { return condenseMat; }
|
|
|
|
void SetCondenseMat(BOOL sw) { condenseMat = sw; }
|
|
|
|
|
|
|
|
int DoAttach(INode *node, PatchMesh *attPatch, RPatchMesh *rattPatch, bool & canUndo);
|
|
|
|
|
|
|
|
// Store current topology in the PatchObject
|
|
|
|
void RecordTopologyTags();
|
|
|
|
|
|
|
|
// Re-match named selection sets, etc. with changed topology (Call RecordTopologyTags
|
|
|
|
// before making the changes to the shape, then call this)
|
|
|
|
void ResolveTopoChanges();
|
|
|
|
|
|
|
|
void RescaleWorldUnits(float f);
|
|
|
|
|
|
|
|
int GetSubobjectLevel();
|
|
|
|
void SetSubobjectLevel(int level);
|
|
|
|
void RefreshSelType();
|
|
|
|
void UpdateSelectDisplay();
|
|
|
|
void SetSelDlgEnables();
|
|
|
|
void SetOpsDlgEnables();
|
|
|
|
void SetSurfDlgEnables();
|
|
|
|
void SetTileDlgEnables();
|
|
|
|
void SetEdgeDlgEnables();
|
|
|
|
void SelectionChanged();
|
|
|
|
void InvalidateSurfaceUI();
|
|
|
|
void InvalidateTileUI();
|
|
|
|
void InvalidateEdgeUI();
|
|
|
|
BitArray *GetLevelSelectionSet(PatchMesh *patch, RPatchMesh *rpatch);
|
|
|
|
|
|
|
|
// patch select and operations interfaces, JBW 2/2/99
|
|
|
|
void StartCommandMode(patchCommandMode mode);
|
|
|
|
void ButtonOp(patchButtonOp opcode);
|
|
|
|
|
|
|
|
DWORD GetSelLevel();
|
|
|
|
void SetSelLevel(DWORD level);
|
|
|
|
void LocalDataChanged();
|
|
|
|
|
|
|
|
// ISubMtlAPI methods:
|
|
|
|
MtlID GetNextAvailMtlID(ModContext* mc);
|
|
|
|
BOOL HasFaceSelection(ModContext* mc);
|
|
|
|
void SetSelFaceMtlID(ModContext* mc, MtlID id, BOOL bResetUnsel = FALSE);
|
|
|
|
int GetSelFaceUniqueMtlID(ModContext* mc);
|
|
|
|
int GetSelFaceAnyMtlID(ModContext* mc);
|
|
|
|
int GetMaxMtlID(ModContext* mc);
|
|
|
|
|
|
|
|
// New SubObjType API
|
|
|
|
int NumSubObjTypes();
|
|
|
|
ISubObjType *GetSubObjType(int i);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PickPatchAttach :
|
|
|
|
public PickModeCallback,
|
|
|
|
public PickNodeCallback {
|
|
|
|
public:
|
|
|
|
EditPatchMod *ep;
|
|
|
|
|
|
|
|
PickPatchAttach() {ep=NULL;}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
HCURSOR GetHitCursor(IObjParam *ip);
|
|
|
|
|
|
|
|
BOOL Filter(INode *node);
|
|
|
|
|
|
|
|
PickNodeCallback *GetFilter() {return this;}
|
|
|
|
|
|
|
|
BOOL RightClick(IObjParam *ip,ViewExp *vpt) {return TRUE;}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Table to convert selLevel values to patch selLevel flags.
|
|
|
|
const int patchLevel[] = {PATCH_OBJECT,PATCH_VERTEX,PATCH_EDGE,PATCH_PATCH,PATCH_OBJECT};
|
|
|
|
|
|
|
|
// Get display flags based on selLevel.
|
|
|
|
const DWORD patchLevelDispFlags[] = {0,DISP_VERTTICKS|DISP_SELVERTS,DISP_SELEDGES,DISP_SELPATCHES,0};
|
|
|
|
|
|
|
|
// For hit testing...
|
|
|
|
static int patchHitLevel[] = {0,SUBHIT_PATCH_VERTS | SUBHIT_PATCH_VECS,SUBHIT_PATCH_EDGES,SUBHIT_PATCH_PATCHES, 0};
|
|
|
|
|
|
|
|
class EditPatchClassDesc:public ClassDesc {
|
|
|
|
public:
|
|
|
|
int IsPublic() { return 1; }
|
|
|
|
void * Create(BOOL loading = FALSE )
|
|
|
|
{
|
|
|
|
return new EditPatchMod;
|
|
|
|
}
|
|
|
|
const TCHAR * ClassName() { return "NeL Edit"; }
|
|
|
|
SClass_ID SuperClassID() { return OSM_CLASS_ID; }
|
|
|
|
Class_ID ClassID() { return Class_ID(0x4dd14a3c, 0x4ac23c0c); }
|
|
|
|
const TCHAR* Category() { return "NeL Tools";}
|
|
|
|
void ResetClassParams(BOOL fileReset);
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef Tab<Point3> Point3Tab;
|
|
|
|
|
|
|
|
class XFormProc {
|
|
|
|
public:
|
|
|
|
virtual Point3 proc(Point3& p, Matrix3 &mat, Matrix3 &imat)=0;
|
|
|
|
virtual void SetMat( Matrix3& mat ) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
class MoveXForm : public XFormProc {
|
|
|
|
private:
|
|
|
|
Point3 delta, tdelta;
|
|
|
|
public:
|
|
|
|
Point3 proc(Point3& p, Matrix3 &mat, Matrix3 &imat)
|
|
|
|
{ return p + tdelta; }
|
|
|
|
void SetMat( Matrix3& mat )
|
|
|
|
{ tdelta = VectorTransform(Inverse(mat),delta); }
|
|
|
|
MoveXForm(Point3 d) { delta = d; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class RotateXForm : public XFormProc {
|
|
|
|
private:
|
|
|
|
Matrix3 rot, trot;
|
|
|
|
public:
|
|
|
|
Point3 proc(Point3& p, Matrix3 &mat, Matrix3 &imat)
|
|
|
|
{ return (trot*p)*imat; }
|
|
|
|
void SetMat( Matrix3& mat )
|
|
|
|
{ trot = mat * rot; }
|
|
|
|
RotateXForm(Quat q) { q.MakeMatrix(rot); }
|
|
|
|
};
|
|
|
|
|
|
|
|
class ScaleXForm : public XFormProc {
|
|
|
|
private:
|
|
|
|
Matrix3 scale, tscale;
|
|
|
|
public:
|
|
|
|
Point3 proc(Point3& p, Matrix3 &mat, Matrix3 &imat)
|
|
|
|
{ return (p*tscale)*imat; }
|
|
|
|
void SetMat( Matrix3& mat )
|
|
|
|
{ tscale = mat*scale; }
|
|
|
|
ScaleXForm(Point3 s) { scale = ScaleMatrix(s); }
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef Tab<int> IntTab;
|
|
|
|
|
|
|
|
// General-purpose patch point table -- Maintains point table for each of n polygons
|
|
|
|
class PatchPointTab {
|
|
|
|
public:
|
|
|
|
Point3Tab ptab; // Patch mesh points
|
|
|
|
Point3Tab vtab; // Patch mesh vectors
|
|
|
|
IntTab pttab; // Patch point types
|
|
|
|
PatchPointTab();
|
|
|
|
~PatchPointTab();
|
|
|
|
void Empty();
|
|
|
|
void Zero();
|
|
|
|
void MakeCompatible(PatchMesh& patch, BOOL clear=TRUE);
|
|
|
|
PatchPointTab& operator=(PatchPointTab& from);
|
|
|
|
BOOL IsCompatible(PatchMesh &patch);
|
|
|
|
void RescaleWorldUnits(float f);
|
|
|
|
IOResult Save(ISave *isave);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PatchVertexDelta {
|
|
|
|
public:
|
|
|
|
PatchPointTab dtab;
|
|
|
|
|
|
|
|
void SetSize(PatchMesh &patch, BOOL load=TRUE);
|
|
|
|
void Empty() { dtab.Empty(); }
|
|
|
|
void Zero() { dtab.Zero(); }
|
|
|
|
void SetVert(int i, const Point3& p) { dtab.ptab[i] = p; }
|
|
|
|
void SetVertType(int i, int k) { dtab.pttab[i] = k; }
|
|
|
|
void SetVec(int i, const Point3& p) { dtab.vtab[i] = p; }
|
|
|
|
void MoveVert(int i, const Point3& p) { dtab.ptab[i] += p; }
|
|
|
|
void MoveVec(int i, const Point3& p) { dtab.vtab[i] += p; }
|
|
|
|
void Apply(PatchMesh& patch);
|
|
|
|
void UnApply(PatchMesh& patch);
|
|
|
|
PatchVertexDelta& operator=(PatchVertexDelta& from) { dtab = from.dtab; return *this; }
|
|
|
|
void ApplyHandlesAndZero(PatchMesh &patch, int handleVert);
|
|
|
|
BOOL IsCompatible(PatchMesh &patch) { return dtab.IsCompatible(patch); }
|
|
|
|
void RescaleWorldUnits(float f) { dtab.RescaleWorldUnits(f); }
|
|
|
|
IOResult Save(ISave *isave);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class AdjEdgeList;
|
|
|
|
class EPTempData;
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
// Class for recording changes -- This is used to reconstruct an object from the original whenever
|
|
|
|
// the modifier is re-entered or whenever the system needs to reconstruct an object's cache. This may be
|
|
|
|
// slow if a lot of changes have been recorded, but it's about the only way to properly reconstruct an object
|
|
|
|
// because the output of one operation becomes the input of the next.
|
|
|
|
|
|
|
|
// These are used as follows:
|
|
|
|
// When a user makes a modification to an object, a StartChangeGroup call needs to be made to the EditPatchData
|
|
|
|
// object. Then a change record needs to be added for each sub-operation that makes up the modification. These
|
|
|
|
// records are owned by the EditPatchData object, but they should also be referenced by the undo object for that
|
|
|
|
// operation. If an undo is done, ownership of the modification record transfers to the undo/redo object and the
|
|
|
|
// record is REMOVED (NOT DELETED) from the EditPatchData object. This keeps the record around for a redo operation
|
|
|
|
// but removes it from the list of records for the modifier. If the undo is redone, ownership transfers back to
|
|
|
|
// the modifier, when it is re-added to the modification record list.
|
|
|
|
|
|
|
|
// Note that this class contains load and save methods, necessary because the modifier needs to be able to save
|
|
|
|
// and load them. When you subclass off of this, be sure your load and save methods call the base class's first!
|
|
|
|
|
|
|
|
class PatchRestore;
|
|
|
|
|
|
|
|
class PModRecord {
|
|
|
|
public:
|
|
|
|
virtual BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord)=0;
|
|
|
|
virtual IOResult Load(ILoad *iload)=0;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef PModRecord* PPModRecord;
|
|
|
|
typedef Tab<PPModRecord> ModRecordTab;
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
// Here are the types of modification records we use!
|
|
|
|
|
|
|
|
#define CLEARVERTSELRECORD_CHUNK 0x2000
|
|
|
|
#define SETVERTSELRECORD_CHUNK 0x2001
|
|
|
|
#define INVERTVERTSELRECORD_CHUNK 0x2002
|
|
|
|
#define CLEAREDGESELRECORD_CHUNK 0x2005
|
|
|
|
#define SETEDGESELRECORD_CHUNK 0x2006
|
|
|
|
#define INVERTEDGESELRECORD_CHUNK 0x2007
|
|
|
|
#define CLEARPATCHSELRECORD_CHUNK 0x2010
|
|
|
|
#define SETPATCHSELRECORD_CHUNK 0x2011
|
|
|
|
#define INVERTPATCHSELRECORD_CHUNK 0x2012
|
|
|
|
#define VERTSELRECORD_CHUNK 0x2020
|
|
|
|
#define EDGESELRECORD_CHUNK 0x2025
|
|
|
|
#define PATCHSELRECORD_CHUNK 0x2030
|
|
|
|
#define VERTMOVERECORD_CHUNK 0x2040
|
|
|
|
#define PATCHDELETERECORD_CHUNK 0x2050
|
|
|
|
#define VERTDELETERECORD_CHUNK 0x2060
|
|
|
|
#define PATCHCHANGERECORD_CHUNK 0x2070
|
|
|
|
#define VERTCHANGERECORD_CHUNK 0x2080
|
|
|
|
#define PATCHADDRECORD_CHUNK 0x2090
|
|
|
|
#define EDGESUBDIVIDERECORD_CHUNK 0x20A0
|
|
|
|
#define PATCHSUBDIVIDERECORD_CHUNK 0x20B0
|
|
|
|
#define VERTWELDRECORD_CHUNK 0x20C0
|
|
|
|
#define PATTACHRECORD_CHUNK 0x20D0
|
|
|
|
#define PATCHDETACHRECORD_CHUNK 0x20E0
|
|
|
|
#define PATCHMTLRECORD_CHUNK 0x20F0
|
|
|
|
|
|
|
|
class ClearPVertSelRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BitArray sel; // Old state
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class SetPVertSelRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BitArray sel; // Old state
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class InvertPVertSelRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class ClearPEdgeSelRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BitArray sel; // Old state
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class SetPEdgeSelRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BitArray sel; // Old state
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class InvertPEdgeSelRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class ClearPatchSelRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BitArray sel; // Old state
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class SetPatchSelRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BitArray sel; // Old state
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class InvertPatchSelRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PVertSelRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BitArray oldSel; // Old state
|
|
|
|
BitArray newSel; // New state
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PEdgeSelRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BitArray oldSel; // Old state
|
|
|
|
BitArray newSel; // New state
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PatchSelRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BitArray oldSel; // Old state
|
|
|
|
BitArray newSel; // New state
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PVertMoveRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
PatchVertexDelta delta; // Position changes for each vertex (Wasteful! Change later?)
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PatchDeleteRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
PatchMesh oldPatch; // How the spline looked before the delete
|
|
|
|
RPatchMesh roldPatch; // How the spline looked before the delete
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PVertDeleteRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
PatchMesh oldPatch; // How the patch looked before the delete
|
|
|
|
RPatchMesh roldPatch; // How the patch looked before the delete
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PatchChangeRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
PatchMesh oldPatch; // How the patch mesh looked before the change
|
|
|
|
RPatchMesh roldPatch; // How the patch looked before the delete
|
|
|
|
int index;
|
|
|
|
int type;
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PVertChangeRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
PatchMesh oldPatch; // How the patch mesh looked before the change
|
|
|
|
RPatchMesh roldPatch; // How the patch looked before the delete
|
|
|
|
int index;
|
|
|
|
int type;
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PatchAddRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BOOL postWeld; // Present in MAX 2.0 and up
|
|
|
|
int type; // 3 or 4 sides!
|
|
|
|
PatchMesh oldPatch; // How the patch looked before the addition
|
|
|
|
RPatchMesh roldPatch; // How the patch looked before the delete
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class EdgeSubdivideRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BOOL propagate; // Carry around entire patch mesh?
|
|
|
|
PatchMesh oldPatch; // How the patch looked before the addition
|
|
|
|
RPatchMesh roldPatch; // How the patch looked before the delete
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PatchSubdivideRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
BOOL propagate; // Carry around entire patch mesh?
|
|
|
|
PatchMesh oldPatch; // How the patch looked before the addition
|
|
|
|
RPatchMesh roldPatch; // How the patch looked before the delete
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PVertWeldRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
float thresh; // Weld threshold
|
|
|
|
BOOL propagate; // Carry around entire patch mesh?
|
|
|
|
PatchMesh oldPatch; // How the patch looked before the addition
|
|
|
|
RPatchMesh roldPatch; // How the patch looked before the delete
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PAttachRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
PatchMesh attPatch; // The patch we're attaching
|
|
|
|
int oldPatchCount; // The number of splines present before attaching
|
|
|
|
int mtlOffset;
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
class PatchDetachRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
int copy;
|
|
|
|
PatchMesh oldPatch;
|
|
|
|
RPatchMesh roldPatch; // How the patch looked before the delete
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef Tab<MtlID> MtlIDTab;
|
|
|
|
|
|
|
|
class PatchMtlRecord : public PModRecord {
|
|
|
|
public:
|
|
|
|
MtlIDTab materials; // Materials from selected patches
|
|
|
|
MtlID index; // New material index assigned
|
|
|
|
BOOL Redo(PatchMesh *patch,RPatchMesh *rpatch,int reRecord);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
// Vertex Mapping class -- Gives mapping from vert in original patch to
|
|
|
|
// vert in modified patch
|
|
|
|
|
|
|
|
class EPMapVert {
|
|
|
|
public:
|
|
|
|
BOOL originalStored;
|
|
|
|
int vert;
|
|
|
|
Point3 original; // Original point location
|
|
|
|
Point3 delta; // The delta we've applied
|
|
|
|
EPMapVert() { originalStored = FALSE; vert = 0; original = Point3(0,0,0); delta = Point3(0,0,0); }
|
|
|
|
EPMapVert(int v, Point3 &o, Point3 &d) { vert = v; original = o; delta = d; originalStored = TRUE; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class EPVertMapper {
|
|
|
|
public:
|
|
|
|
int verts;
|
|
|
|
EPMapVert *vertMap;
|
|
|
|
int vecs;
|
|
|
|
EPMapVert *vecMap;
|
|
|
|
EPVertMapper() { verts = vecs = 0; vertMap = vecMap = NULL; }
|
|
|
|
~EPVertMapper();
|
|
|
|
// Set up remap data structures.
|
|
|
|
void Build(PatchMesh &patch);
|
|
|
|
// Update the deltas we have stored, if necessary and apply to output patch mesh.
|
|
|
|
// This is in response to the original shape changing
|
|
|
|
void UpdateAndApplyDeltas(PatchMesh &inPatch, PatchMesh &outPatch);
|
|
|
|
// Recompute the deltas we have stored
|
|
|
|
// This is done after the modifier's user interaction changes the shape
|
|
|
|
void RecomputeDeltas(PatchMesh &patch);
|
|
|
|
// Record the topology tags in the specified shape
|
|
|
|
void RecordTopologyTags(PatchMesh &patch);
|
|
|
|
// Update the topology tag mapping
|
|
|
|
void UpdateMapping(PatchMesh &patch);
|
|
|
|
EPVertMapper& operator=(EPVertMapper &from);
|
|
|
|
void RescaleWorldUnits(float f);
|
|
|
|
IOResult Save(ISave *isave);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
// EditPatchData flags
|
|
|
|
#define EPD_BEENDONE (1<<0)
|
|
|
|
#define EPD_UPDATING_CACHE (1<<1)
|
|
|
|
#define EPD_HASDATA (1<<2)
|
|
|
|
#define EMD_HELD (1<<3) // equivalent to A_HELD
|
|
|
|
|
|
|
|
// This is the data that each mod app will have.
|
|
|
|
class EditPatchData : public LocalModData {
|
|
|
|
public:
|
|
|
|
BOOL handleFlag;
|
|
|
|
int handleVert;
|
|
|
|
|
|
|
|
// Stuff we need to have for the patch's mesh conversion -- These are
|
|
|
|
// Here because they're kind of a global change -- not undoable.
|
|
|
|
int meshSteps;
|
|
|
|
//3-18-99 to suport render steps and removal of the mental tesselator
|
|
|
|
int meshStepsRender;
|
|
|
|
BOOL showInterior;
|
|
|
|
int tileLevel;
|
|
|
|
bool tileMode;
|
|
|
|
bool includeMeshes;
|
|
|
|
bool keepMapping;
|
|
|
|
int transitionType;
|
|
|
|
|
|
|
|
BOOL meshAdaptive; // Future use (Not used now)
|
|
|
|
TessApprox viewTess;
|
|
|
|
TessApprox prodTess;
|
|
|
|
TessApprox dispTess;
|
|
|
|
BOOL mViewTessNormals; // use normals from the tesselator
|
|
|
|
BOOL mProdTessNormals; // use normals from the tesselator
|
|
|
|
BOOL mViewTessWeld; // Weld the mesh after tessellation
|
|
|
|
BOOL mProdTessWeld; // Weld the mesh after tessellation
|
|
|
|
BOOL displaySurface;
|
|
|
|
BOOL displayLattice;
|
|
|
|
|
|
|
|
DWORD flags;
|
|
|
|
|
|
|
|
// This records the changes to the incoming object.
|
|
|
|
ModRecordTab changes;
|
|
|
|
|
|
|
|
// A pointer to the change record's vertex delta object
|
|
|
|
PatchVertexDelta vdelta;
|
|
|
|
|
|
|
|
// RB: Named selection set lists
|
|
|
|
GenericNamedSelSetList vselSet; // Vertex
|
|
|
|
GenericNamedSelSetList eselSet; // Edge
|
|
|
|
GenericNamedSelSetList pselSet; // Patch
|
|
|
|
|
|
|
|
// While an object is being edited, this exists.
|
|
|
|
EPTempData *tempData;
|
|
|
|
|
|
|
|
// The knot mapping for the edited patch
|
|
|
|
EPVertMapper vertMap;
|
|
|
|
|
|
|
|
// The final edited patch
|
|
|
|
PatchMesh finalPatch;
|
|
|
|
RPatchMesh rfinalPatch;
|
|
|
|
|
|
|
|
EditPatchData(EditPatchMod *mod);
|
|
|
|
EditPatchData(EditPatchData& emc);
|
|
|
|
|
|
|
|
// Applies modifications to a patchObject
|
|
|
|
void Apply(TimeValue t,RPO *patchOb,int selLevel);
|
|
|
|
|
|
|
|
// Invalidates any caches affected by the change.
|
|
|
|
void Invalidate(PartID part,BOOL meshValid=TRUE);
|
|
|
|
|
|
|
|
// If this is the first edit, then the delta arrays will be allocated
|
|
|
|
void BeginEdit(TimeValue t);
|
|
|
|
|
|
|
|
LocalModData *Clone() { return new EditPatchData(*this); }
|
|
|
|
|
|
|
|
void SetFlag(DWORD f,BOOL on)
|
|
|
|
{
|
|
|
|
if ( on ) {
|
|
|
|
flags|=f;
|
|
|
|
} else {
|
|
|
|
flags&=~f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DWORD GetFlag(DWORD f) { return flags&f; }
|
|
|
|
|
|
|
|
EPTempData *TempData(EditPatchMod *mod);
|
|
|
|
|
|
|
|
// Change recording functions:
|
|
|
|
void ClearHandleFlag() { handleFlag = FALSE; }
|
|
|
|
void SetHandleFlag(int vert) { handleVert = vert; handleFlag = TRUE; }
|
|
|
|
BOOL DoingHandles() { return handleFlag; }
|
|
|
|
void ApplyHandlesAndZero(PatchMesh &patch) { vdelta.ApplyHandlesAndZero(patch, handleVert); }
|
|
|
|
void RescaleWorldUnits(float f);
|
|
|
|
|
|
|
|
// MAXr3: New recording system
|
|
|
|
void RecordTopologyTags(PatchMesh *patch);
|
|
|
|
void UpdateChanges(PatchMesh *patch, RPatchMesh *rpatch, BOOL checkTopology=TRUE);
|
|
|
|
|
|
|
|
// Named selection set access
|
|
|
|
GenericNamedSelSetList &GetSelSet(EditPatchMod *mod); // Get the one for the current subobject selection level
|
|
|
|
GenericNamedSelSetList &GetSelSet(int level); // Get the one for the specified subobject selection level
|
|
|
|
|
|
|
|
// IO
|
|
|
|
IOResult Save(ISave *isave);
|
|
|
|
IOResult Load(ILoad *iload);
|
|
|
|
};
|
|
|
|
|
|
|
|
// My generic restore class
|
|
|
|
|
|
|
|
class PatchRestore : public RestoreObj
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
bool RPatchModified;
|
|
|
|
PatchMesh oldPatch, newPatch;
|
|
|
|
RPatchMesh *roldPatch, *rnewPatch; // How the patch looked before the delete
|
|
|
|
BOOL gotRedo;
|
|
|
|
TimeValue t;
|
|
|
|
EditPatchData *epd;
|
|
|
|
EditPatchMod *mod;
|
|
|
|
TSTR where;
|
|
|
|
|
|
|
|
PatchRestore (EditPatchData* pd, EditPatchMod* mod, PatchMesh *patch, RPatchMesh *rpatch, TCHAR *id=_T(""));
|
|
|
|
virtual ~PatchRestore ();
|
|
|
|
|
|
|
|
void Restore(int isUndo);
|
|
|
|
void Redo();
|
|
|
|
int Size() { return 1; }
|
|
|
|
void EndHold() {mod->ClearAFlag(A_HELD);}
|
|
|
|
TSTR Description()
|
|
|
|
{
|
|
|
|
TSTR string;
|
|
|
|
string.printf(_T("Generic patch restore [%s]"),where);
|
|
|
|
return string;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Patch selection restore class
|
|
|
|
|
|
|
|
class PatchSelRestore : public RestoreObj {
|
|
|
|
public:
|
|
|
|
BitArray oldVSel, newVSel;
|
|
|
|
BitArray oldESel, newESel;
|
|
|
|
BitArray oldPSel, newPSel;
|
|
|
|
BOOL gotRedo;
|
|
|
|
TimeValue t;
|
|
|
|
EditPatchData *epd;
|
|
|
|
EditPatchMod *mod;
|
|
|
|
|
|
|
|
PatchSelRestore(EditPatchData* pd, EditPatchMod* mod, PatchMesh *patch);
|
|
|
|
|
|
|
|
void Restore(int isUndo);
|
|
|
|
void Redo();
|
|
|
|
int Size() { return 1; }
|
|
|
|
void EndHold() {mod->ClearAFlag(A_HELD);}
|
|
|
|
TSTR Description() { return TSTR(_T("Patch Select restore")); }
|
|
|
|
};
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
class EPTempData {
|
|
|
|
private:
|
|
|
|
PatchMesh *patch;
|
|
|
|
RPatchMesh *rpatch;
|
|
|
|
Interval patchValid;
|
|
|
|
|
|
|
|
EditPatchMod *mod;
|
|
|
|
EditPatchData *patchData;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
~EPTempData();
|
|
|
|
EPTempData(EditPatchMod *m,EditPatchData *md);
|
|
|
|
void Invalidate(PartID part,BOOL meshValid=TRUE);
|
|
|
|
|
|
|
|
PatchMesh *GetPatch(TimeValue t, RPatchMesh *&rPatch);
|
|
|
|
|
|
|
|
BOOL PatchCached(TimeValue t);
|
|
|
|
void UpdateCache(RPO *patchOb);
|
|
|
|
EditPatchMod *GetMod() { return mod; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class PatchDeleteUser : public EventUser
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
EditPatchMod *ep;
|
|
|
|
public:
|
|
|
|
void Notify() { ep->DoDeleteSelected(); }
|
|
|
|
void SetMod(EditPatchMod *ep) { this->ep = ep; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Patch hit override functions
|
|
|
|
|
|
|
|
extern void SetPatchHitOverride(int value);
|
|
|
|
extern void ClearPatchHitOverride();
|
|
|
|
|
|
|
|
#endif // __EDITPATCH_H__
|