2017-04-17 06:17:10 -06:00

2012 lines
86 KiB
C++
Executable File

/**********************************************************************
*<
FILE: object.h
DESCRIPTION: Defines Object Classes
CREATED BY: Dan Silva
HISTORY: created 9 September 1994
*> Copyright (c) 1994, All Rights Reserved.
**********************************************************************/
#ifndef _OBJECT_
#define _OBJECT_
#include "inode.h"
#include "maxapi.h"
#include "plugapi.h"
#include "snap.h"
#include "genshape.h"
#include <hitdata.h>
#include "imtl.h"
typedef short MtlIndex;
typedef short TextMapIndex;
CoreExport void setHitType(int t);
CoreExport int getHitType(void);
CoreExport BOOL doingXORDraw(void);
// Hit test types:
#define HITTYPE_POINT 1
#define HITTYPE_BOX 2
#define HITTYPE_CIRCLE 3
#define HITTYPE_SOLID 4
#define HITTYPE_FENCE 5
#define HITTYPE_LASSO 6
#define HITTYPE_PAINT 7
// Flags for hit test.
#define HIT_SELONLY (1<<0)
#define HIT_UNSELONLY (1<<2)
#define HIT_ABORTONHIT (1<<3)
#define HIT_SELSOLID (1<<4)
#define HIT_ANYSOLID (1<<5)
#define HIT_TRANSFORMGIZMO (1<<6) // CCJ - 06/29/98 - Hittest transform gizmo
#define HIT_SWITCH_GIZMO (1<<7) // CCJ - 06/29/98 - Switch axis when hit
#define HIT_MANIP_SUBHIT (1<<8) // SCM - 5/31/00 - hit test sub-manipulators
// These are filters for hit testing. They also
// are combined into the flags parameter.
#define HITFLTR_ALL (1<<10)
#define HITFLTR_OBJECTS (1<<11)
#define HITFLTR_CAMERAS (1<<12)
#define HITFLTR_LIGHTS (1<<13)
#define HITFLTR_HELPERS (1<<14)
#define HITFLTR_WSMOBJECTS (1<<15)
#define HITFLTR_SPLINES (1<<16)
#define HITFLTR_BONES (1<<17)
// Starting at this bit through the 31st bit can be used
// by plug-ins for sub-object hit testing
#define HITFLAG_STARTUSERBIT 24
#define VALID(x) (x)
class Modifier;
class Object;
class NameTab;
class ExclList;
class Texmap;
class ISubObjType;
class MaxIcon;
typedef Object* ObjectHandle;
MakeTab(TextMapIndex)
typedef TextMapIndexTab TextTab;
#define BASEOBJAPPDATACID Class_ID(0x48a057d2, 0x44f70d8a)
#define BASEOBJAPPDATALASTSELCID Class_ID(0x1cef158c, 0x1da8486f)
#define BASEOBJAPPDATACURSELCID Class_ID(0x5b3b25fc, 0x35af6260)
#define BASEOBJAPPDATASCID USERDATATYPE_CLASS_ID
//---------------------------------------------------------------
class IdentityTM: public Matrix3 {
public:
IdentityTM() { IdentityMatrix(); }
};
CoreExport extern IdentityTM idTM;
//-------------------------------------------------------------
// This is passed in to GetRenderMesh to allow objects to do
// view dependent rendering.
//
// flag defines for View::flags
#define RENDER_MESH_DISPLACEMENT_MAP 1 // enable displacement mapping
class View : public InterfaceServer{
public:
float screenW, screenH; // screen dimensions
Matrix3 worldToView;
virtual Point2 ViewToScreen(Point3 p)=0;
// the following added for GAP
int projType;
float fov, pixelSize;
Matrix3 affineTM; // worldToCam
DWORD flags;
// Call during render to check if user has cancelled render.
// Returns TRUE iff user has cancelled.
virtual BOOL CheckForRenderAbort() { return FALSE; }
// Generic expansion function
virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) { return 0; }
View() { projType = -1; flags = RENDER_MESH_DISPLACEMENT_MAP; } // projType not set, this is to deal with older renderers.
};
//-------------------------------------------------------------
// Class ID of general deformable object.
extern CoreExport Class_ID defObjectClassID;
//-------------------------------------------------------------
// Class ID of general texture-mappable object.
extern CoreExport Class_ID mapObjectClassID;
//-------------------------------------------------------------
// ChannelMask: bits specific channels in the OSM dataflow.
typedef ULONG_PTR ChannelMask;
// WIN64 Cleanup: Shuler
// an array of channel masks for all the channels *within*
// the Object.
CoreExport extern ChannelMask chMask[];
class Object;
//-- ObjectState ------------------------------------------------------------
// This is what is passed down the pipeline, and ultimately used by the Node
// to Display, Hittest, render:
// flags bits
class ObjectState {
ulong flags;
Matrix3 *tm;
Interval tmvi;
int mtl;
Interval mtlvi;
void AllocTM();
public:
Object *obj; // object: provides interval with obj->ObjectValidity()
CoreExport ObjectState();
CoreExport ObjectState(Object *ob);
CoreExport ObjectState(const ObjectState& os);
CoreExport ~ObjectState();
void OSSetFlag(ulong f) { flags |= f; }
void OSClearFlag(ulong f) { flags &= ~f; }
ulong OSTestFlag(ulong f) const { return flags&f; }
CoreExport void OSCopyFlag(ulong f, const ObjectState& fromos);
CoreExport ObjectState& operator=(const ObjectState& os);
Interval tmValid() const { return tmvi; }
Interval mtlValid() const { return mtlvi; }
CoreExport Interval Validity(TimeValue t) const;
CoreExport int TMIsIdentity() const;
CoreExport void SetTM(Matrix3* mat, Interval iv);
CoreExport Matrix3* GetTM() const;
CoreExport void SetIdentityTM();
CoreExport void ApplyTM(Matrix3* mat, Interval iv);
CoreExport void CopyTM(const ObjectState &fromos);
CoreExport void CopyMtl(const ObjectState &fromos);
CoreExport void Invalidate(ChannelMask channels, BOOL checkLock=FALSE);
CoreExport ChannelMask DeleteObj(BOOL checkLock=FALSE);
};
class INodeTab : public Tab<INode*> {
public:
void DisposeTemporary() {
for (int i=0; i<Count(); i++) (*this)[i]->DisposeTemporary();
}
};
//---------------------------------------------------------------
// A reference to a pointer to an instance of this class is passed in
// to ModifyObject(). The value of the pointer starts out as NULL, but
// the modifier can set it to point at an actual instance of a derived
// class. When the mod app is deleted, if the pointer is not NULL, the
// LocalModData will be deleted - the virtual destructor alows this to work.
class LocalModData : public InterfaceServer {
public:
virtual ~LocalModData() {}
virtual LocalModData *Clone()=0;
using InterfaceServer::GetInterface;
virtual void* GetInterface(ULONG id) { return NULL; } // to access sub-obj selection interfaces, JBW 2/5/99
};
class ModContext : public BaseInterfaceServer {
public:
Matrix3 *tm;
Box3 *box;
LocalModData *localData;
CoreExport ~ModContext();
CoreExport ModContext();
CoreExport ModContext(const ModContext& mc);
CoreExport ModContext(Matrix3 *tm, Box3 *box, LocalModData *localData);
};
class ModContextList : public Tab<ModContext*> {};
class HitRecord;
// Values passed to NewSetByOperator()
#define NEWSET_MERGE 1
#define NEWSET_INTERSECTION 2
#define NEWSET_SUBTRACT 3
// Flags passed to Display()
#define USE_DAMAGE_RECT (1<<0)
#define DISP_SHOWSUBOBJECT (1<<1)
// The base class of Geometric objects, Lights, Cameras, Modifiers,
// Deformation objects--
// --anything with a 3D representation in the UI scene.
class IParamArray;
class BaseObject: public ReferenceTarget {
friend class ModifyTaskImp;
int subObjLevel;
public:
CoreExport void* GetInterface(ULONG id);
virtual BaseInterface* GetInterface(Interface_ID id) { return ReferenceTarget::GetInterface(id); }
CoreExport BaseObject();
virtual int HitTest(TimeValue t, INode* inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt){return 0;};
virtual void SetExtendedDisplay(int flags) {} // for setting mode-dependent display attributes
virtual int Display(TimeValue t, INode* inode, ViewExp *vpt, int flags) { return 0; }; // quick render in viewport, using current TM.
virtual void Snap(TimeValue t, INode* inode, SnapInfo *snap, IPoint2 *p, ViewExp *vpt) {} // Check for snap, updating SnapInfo
virtual void GetWorldBoundBox(TimeValue t, INode * inode, ViewExp* vp, Box3& box ){}; // Box in world coords.
virtual void GetLocalBoundBox(TimeValue t, INode* inode, ViewExp* vp, Box3& box ){}; // box in objects local coords
virtual CreateMouseCallBack* GetCreateMouseCallBack()=0;
// This is the name that will appear in the history browser.
virtual TCHAR *GetObjectName() { return _T("Object"); }
// Sends the REFMSG_IS_OK_TO_CHANGE_TOPOLOGY off to see if any
// modifiers or objects down the pipeline depend on topology.
// modName will be set to the dependent modifier's name if there is one.
CoreExport virtual BOOL OKToChangeTopology(TSTR &modName);
// Return true if this object(or modifier) is cabable of changing
//topology when it's parameters are being edited.
virtual BOOL ChangeTopology() {return TRUE;}
virtual void ForceNotify(Interval& i)
{NotifyDependents(i, PART_ALL,REFMSG_CHANGE);}
// If an object or modifier wishes it can make its parameter block
// available for other plug-ins to access. The system itself doesn't
// actually call this method -- this method is optional.
virtual IParamArray *GetParamBlock() {return NULL;}
// If a plug-in make its parameter block available then it will
// need to provide #defines for indices into the parameter block.
// These defines should probably not be directly used with the
// parameter block but instead converted by this function that the
// plug-in implements. This way if a parameter moves around in a
// future version of the plug-in the #define can be remapped.
// -1 indicates an invalid parameter id
virtual int GetParamBlockIndex(int id) {return -1;}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// The following methods are for sub-object selection. If the
// derived class is NOT a modifier, the modContext pointer passed
// to some of the methods will be NULL.
//
// Affine transform methods
virtual void Move( TimeValue t, Matrix3& partm, Matrix3& tmAxis, Point3& val, BOOL localOrigin=FALSE ){}
virtual void Rotate( TimeValue t, Matrix3& partm, Matrix3& tmAxis, Quat& val, BOOL localOrigin=FALSE ){}
virtual 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 and
// before a hold is in effect
virtual void TransformStart(TimeValue t) {}
// The following is called before the first Move(), Rotate() or Scale() call and
// after a hold is in effect
virtual void TransformHoldingStart(TimeValue t) {}
// The following is called after the user has completed the Move, Rotate or Scale operation and
// before the undo object has been accepted.
virtual void TransformHoldingFinish(TimeValue t) {}
// The following is called after the user has completed the Move, Rotate or Scale operation and
// after the undo object has been accepted.
virtual void TransformFinish(TimeValue t) {}
// The following is called when the transform operation is cancelled by a right-click and
// the undo has been cancelled.
virtual void TransformCancel(TimeValue t) {}
virtual int HitTest(TimeValue t, INode* inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt, ModContext* mc) { return 0; }
virtual int Display(TimeValue t, INode* inode, ViewExp *vpt, int flags, ModContext* mc) { return 0; }; // quick render in viewport, using current TM.
virtual void GetWorldBoundBox(TimeValue t,INode* inode, ViewExp *vpt, Box3& box, ModContext *mc) {}
virtual void CloneSelSubComponents(TimeValue t) {}
virtual void AcceptCloneSelSubComponents(TimeValue t) {}
// Changes the selection state of the component identified by the
// hit record.
virtual void SelectSubComponent(
HitRecord *hitRec, BOOL selected, BOOL all, BOOL invert=FALSE) {}
// Clears the selection for the given sub-object type.
virtual void ClearSelection(int selLevel) {}
virtual void SelectAll(int selLevel) {}
virtual void InvertSelection(int selLevel) {}
// Returns the index of the subobject entity identified by hitRec.
virtual int SubObjectIndex(HitRecord *hitRec) {return 0;}
// This notifies an object being edited that the current sub object
// selection level has changed. level==0 indicates object level selection.
// level==1 or greater refer to the types registered by the object in the
// order they appeared in the list when registered.
// If level >= 1, the object should specify sub-object xform modes in the
// modes structure (defined in cmdmode.h).
virtual void ActivateSubobjSel(int level, XFormModes& modes ) {}
// An object that supports sub-object selection can choose to
// support named sub object selection sets. Methods in the the
// interface passed to objects allow them to add items to the
// sub-object selection set drop down.
// The following methods are called when the user picks items
// from the list.
virtual BOOL SupportsNamedSubSels() {return FALSE;}
virtual void ActivateSubSelSet(TSTR &setName) {}
virtual void NewSetFromCurSel(TSTR &setName) {}
virtual void RemoveSubSelSet(TSTR &setName) {}
// New for version 2. To support the new edit named selections dialog,
// plug-ins must implemented the following methods:
virtual void SetupNamedSelDropDown() {}
virtual int NumNamedSelSets() {return 0;}
virtual TSTR GetNamedSelSetName(int i) {return _T("");}
virtual void SetNamedSelSetName(int i,TSTR &newName) {}
virtual void NewSetByOperator(TSTR &newName,Tab<int> &sets,int op) {}
// New way of dealing with sub object coordinate systems.
// Plug-in enumerates its centers or TMs and calls the callback once for each.
// NOTE:cb->Center() should be called the same number of times and in the
// same order as cb->TM()
// NOTE: The SubObjAxisCallback class is defined in animatable and used in both the
// controller version and this version of GetSubObjectCenters() and GetSubObjectTMs()
virtual void GetSubObjectCenters(SubObjAxisCallback *cb,TimeValue t,INode *node,ModContext *mc) {}
virtual void GetSubObjectTMs(SubObjAxisCallback *cb,TimeValue t,INode *node,ModContext *mc) {}
// Find out if the Object or Modifer is is generating UVW's
// on map channel 1.
virtual BOOL HasUVW () { return 0; }
// or on any map channel:
virtual BOOL HasUVW (int mapChannel) { return (mapChannel==1) ? HasUVW() : FALSE; }
// Change the state of the object's Generate UVW boolean.
// IFF the state changes, the object should send a REFMSG_CHANGED down the pipe.
virtual void SetGenUVW(BOOL sw) { } // applies to mapChannel 1
virtual void SetGenUVW (int mapChannel, BOOL sw) { if (mapChannel==1) SetGenUVW (sw); }
// Notify the BaseObject that the end result display has been switched.
// (Sometimes this is needed for display changes.)
virtual void ShowEndResultChanged (BOOL showEndResult) { }
//
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// This method is called before a modifier or object is collapsed. In case it
// is a modifier, the derObj contains the DerivedObject and the index the
// index of the modifier in the DerivedObject. In case it is a Object, derObj
// is NULL and index is 0.
virtual void NotifyPreCollapse(INode *node, IDerivedObject *derObj, int index){};
// This method is called before a modifier or object is collapsed. In case it
// is a modifier, the derObj contains the DerivedObject and the index the
// index of the modifier in the DerivedObject. In case it is a Object, derObj
// is NULL and index is 0.
virtual void NotifyPostCollapse(INode *node, Object *obj, IDerivedObject *derObj, int index){};
// New in R4. objects and modifiers, that support subobjects have to overwrite
// these 2 methods and return a class derived from ISubObjType in GetSubObjType().
// Developers can use the GenSubObjType for convenience.If the parameter passed
// into GetSubObjType is -1, the system requests a ISubObjType, for the current
// SubObjectLevel that flows up the modifier stack. If the subobject selection
// of the modifier or base object does not affect the subobj selection that
// flows up the stack, the method must return NULL. See meshsel.cpp for a
// sample implementation
virtual int NumSubObjTypes(){ return 0;}
virtual ISubObjType *GetSubObjType(int i) { return NULL; }
// This method returns the subobject level, that the modifier or base
// object is in. The subObjLevel is set by the system. 0 is the object level
// and 1 - n are the subobject levels in the same order as they are
// returned by GetSubObjType(int i) (with an offset of 1 obviously).
CoreExport virtual int GetSubObjectLevel();
// This method return true if GetWorldBoundBox returns different boxes
// for different viewports. It is used to inhibit a caching of the
// bounding box for all viewports. Default implementation returns false.
virtual BOOL HasViewDependentBoundingBox() { return false; }
};
//-------------------------------------------------------------
// Callback object used by Modifiers to deform "Deformable" objects
class Deformer {
public:
virtual Point3 Map(int i, Point3 p) = 0;
void ApplyToTM(Matrix3* tm);
};
// Mapping types passed to ApplyUVWMap()
#define MAP_PLANAR 0
#define MAP_CYLINDRICAL 1
#define MAP_SPHERICAL 2
#define MAP_BALL 3
#define MAP_BOX 4
/*-------------------------------------------------------------------
Object is the class of all objects that can be pointed to by a node:
It INcludes Lights,Cameras, Geometric objects, derived objects,
and deformation Objects (e.g. FFD lattices)
It EXcludes Modifiers
---------------------------------------------------------------------*/
#ifdef _WIN64
#define OBJECT_LOCKED 0x0800000000000000
#else // _WIN32 only
// 32 bit pointers
#define OBJECT_LOCKED 0x08000000
#endif
// WIN64 Cleanup: Shuler
class ShapeObject;
class XTCObject;
class XTCContainer {
public:
XTCObject *obj;
int prio;
int branchID;
XTCContainer(){obj = NULL; prio = 0; branchID = -1;}
};
#define IXTCACCESS_INTERFACE_ID Interface_ID(0x60b033d7, 0x3e1d4d0d)
class IXTCAccess : public BaseInterface
{
public:
virtual Interface_ID GetID() { return IXTCACCESS_INTERFACE_ID; }
virtual LifetimeType LifetimeControl() { return noRelease; }
virtual void AddXTCObject(XTCObject *pObj, int priority = 0, int branchID = -1)=0;
virtual int NumXTCObjects()=0;
virtual XTCObject *GetXTCObject(int index)=0;
virtual void RemoveXTCObject(int index)=0;
virtual void SetXTCObjectPriority(int index,int priority)=0;
virtual int GetXTCObjectPriority(int index)=0;
virtual void SetXTCObjectBranchID(int index,int branchID)=0;
virtual int GetXTCObjectBranchID(int index)=0;
virtual void MergeAdditionalChannels(Object *from, int branchID)=0;
virtual void BranchDeleted(int branchID, bool reorderChannels)=0;
virtual void CopyAdditionalChannels(Object *from, bool deleteOld = true, bool bShallowCopy = false)=0;
virtual void DeleteAllAdditionalChannels()=0;
};
class XTCAccessImp;
class Object: public BaseObject {
ChannelMask locked; // lock flags for each channel + object locked flag
// WIN64 Cleanup: Shuler
Interval noEvalInterval; // used in ReducingCaches
Interval xtcValid;
Tab<XTCContainer *> xObjs;
XTCAccessImp *pXTCAccess;
public:
CoreExport Object();
CoreExport ~Object();
virtual int IsRenderable()=0; // is this a renderable object?
virtual void InitNodeName(TSTR& s)=0;
virtual int UsesWireColor() { return TRUE; } // TRUE if the object color is used for display
virtual int DoOwnSelectHilite() { return 0; }
// This used to be in GeomObject but I realized that other types of objects may
// want this (mainly to participate in normal align) such as grid helper objects.
virtual int IntersectRay(TimeValue t, Ray& r, float& at, Point3& norm) {return FALSE;}
// Objects that don't support IntersectRay() (like helpers) can implement this
// method to provide a default vector for normal align.
virtual BOOL NormalAlignVector(TimeValue t,Point3 &pt, Point3 &norm) {return FALSE;}
// locking of object as whole. defaults to NOT modifiable.
void LockObject() { locked |= OBJECT_LOCKED; }
void UnlockObject() { locked &= ~OBJECT_LOCKED; }
int IsObjectLocked() { return (locked&OBJECT_LOCKED ? 1 : 0); }
// WIN64 Cleanup: Shuler
// the validity intervals are now in the object.
virtual ObjectState Eval(TimeValue t)=0;
// Access the lock flags for th specified channels
void LockChannels(ChannelMask channels) { locked |= channels; }
void UnlockChannels(ChannelMask channels) { locked &= ~channels; }
ChannelMask GetChannelLocks() { return locked; }
void SetChannelLocks(ChannelMask channels) { locked = channels; }
ChannelMask GetChannelLocks(ChannelMask m) { return locked; }
// Can this object have channels cached?
// Particle objects flow up the pipline without making shallow copies of themselves and therefore cannot be cached
virtual BOOL CanCacheObject() {return TRUE;}
// This is called by a node when the node's world space state has
// become invalid. Normally an object does not (and should not) be
// concerned with this, but in certain cases (particle systems) an
// object is effectively a world space object an needs to be notified.
virtual void WSStateInvalidate() {}
// Identifies the object as a world space object. World space
// objects (particles for example) can not be instanced because
// they exist in world space not object space.
virtual BOOL IsWorldSpaceObject() {return FALSE;}
// This is only valid for world-space objects (they must return TRUE for
// the IsWorldSpaceObject method). It locates the node which contains the
// object. Non-world-space objects will return NULL for this!
CoreExport INode *GetWorldSpaceObjectNode();
// Is the derived class derived from ParticleObject?
virtual BOOL IsParticleSystem() {return FALSE;}
// copy specified flags from obj
CoreExport void CopyChannelLocks(Object *obj, ChannelMask needChannels);
// topology has been changed by a modifier -- update mesh strip/edge lists
virtual void TopologyChanged() { }
//
// does this object implement the generic Deformable Object procs?
//
virtual int IsDeformable() { return 0; }
// DeformableObject procs: only need be implemented
// IsDeformable() returns TRUE.
virtual int NumPoints(){ return 0;}
virtual Point3 GetPoint(int i) { return Point3(0,0,0); }
virtual void SetPoint(int i, const Point3& p) {}
// Completes the deformable object access with two methods to
// query point selection.
// IsPointSelected returns a TRUE/FALSE value
// PointSelection returns the weighted point selection, if supported.
// Harry D, 11/98
virtual BOOL IsPointSelected (int i) { return FALSE; }
virtual float PointSelection (int i) {
return IsPointSelected(i) ? 1.0f : 0.0f;
}
// These allow the NURBS Relational weights to be modified
virtual BOOL HasWeights() { return FALSE; }
virtual double GetWeight(int i) { return 1.0; }
virtual void SetWeight(int i, const double w) {}
// Get the count of faces and vertices for the polyginal mesh
// of an object. If it return FALSE, then this function
// isn't supported. Plug-ins should use GetPolygonCount(Object*, int&, int&)
// to count the polys in an arbitrary object
virtual BOOL PolygonCount(TimeValue t, int& numFaces, int& numVerts) { return FALSE; }
// informs the object that its points have been deformed,
// so it can invalidate its cache.
virtual void PointsWereChanged(){}
// deform the object with a deformer.
CoreExport virtual void Deform(Deformer *defProc, int useSel=0);
// box in objects local coords or optional space defined by tm
// If useSel is true, the bounding box of selected sub-elements will be taken.
CoreExport virtual void GetDeformBBox(TimeValue t, Box3& box, Matrix3 *tm=NULL, BOOL useSel=FALSE );
//
// does this object implement the generic Mappable Object procs?
//
virtual int IsMappable() { return 0; }
virtual int NumMapChannels () { return IsMappable(); } // returns number possible.
virtual int NumMapsUsed () { return NumMapChannels(); } // at least 1+(highest channel in use).
// This does the texture map application -- Only need to implement if
// IsMappable returns TRUE
virtual void ApplyUVWMap(int type,
float utile, float vtile, float wtile,
int uflip, int vflip, int wflip, int cap,
const Matrix3 &tm,int channel=1) {}
// Objects need to be able convert themselves
// to TriObjects. Most modifiers will ask for
// Deformable Objects, and triobjects will suffice.
CoreExport virtual int CanConvertToType(Class_ID obtype);
// Developers have to make sure, that the channels, that the BaseObject implements
// (e.g. ExtensionChannels) are copied over to the new object as well. They can do this by simply
// calling CopyXTCObjects(this,false); The validity will be automatically copied with it..
CoreExport virtual Object* ConvertToType(TimeValue t, Class_ID obtype);
// Indicate the types this object can collapse to
virtual Class_ID PreferredCollapseType() {return Class_ID(0,0);}
CoreExport virtual void GetCollapseTypes(Tab<Class_ID> &clist,Tab<TSTR*> &nlist);
virtual Object *CollapseObject() { return this;}
// return the current sub-selection state
virtual DWORD GetSubselState() {return 0;}
virtual void SetSubSelState(DWORD s) {}
// If the requested channels are locked, replace their data
// with a copy/ and unlock them, otherwise leave them alone
CoreExport void ReadyChannelsForMod(ChannelMask channels);
// Virtual methods to be implemented by plug-in object:-----
// NS: 12-14-99 Classes that derive from Object *have* to implement certain
// things to support the new Extension Channel (XTCObject)
// See examples in Triobj.cpp [START]
// access the current validity interval for the nth channel
// For this method, the derived class has to check if the channel is the
// Extension channel and return the base classes ChannelValidity :
// case EXTENSION_CHAN_NUM: return Object::ChannelValidity(t,nchan); break;
CoreExport virtual Interval ChannelValidity(TimeValue t, int nchan);
// The derived class has to simply call the implementation of the baseclass.
CoreExport virtual void SetChannelValidity(int nchan, Interval v);
// invalidate the specified channels
// The derived class has to simply call the implementation of the baseclass.
CoreExport virtual void InvalidateChannels(ChannelMask channels);
// validity interval of Object as a whole at current time
// The derived class has incorporate the BaseClasses validity into the returned validity
CoreExport virtual Interval ObjectValidity(TimeValue t);
// Makes a copy of its "shell" and shallow copies only the
// specified channels. Also copies the validity intervals of
// the copied channels, and sets Invalidates the other intervals.
// The derived class has to call ShallowCopy on the BaseClass, so it can copy all its channels
virtual Object *MakeShallowCopy(ChannelMask channels) { return NULL; }
// Shallow-copies the specified channels from the fromOb to this.
// Also copies the validity intervals.
// The derived class has to simply call the implementation of the baseclass.
CoreExport virtual void ShallowCopy(Object* fromOb, ChannelMask channels);
// Free the specified channels
// The derived class has to simply call the implementation of the baseclass.
CoreExport virtual void FreeChannels(ChannelMask channels);
// This replaces locked channels with newly allocated copies.
// It will only be called if the channel is locked.
// The derived class has to simply call the implementation of the baseclass.
CoreExport virtual void NewAndCopyChannels(ChannelMask channels);
// Allow the object to enlarge its viewport rectangle, if it wants to.
// The derived class has to simply call the implementation of the baseclass.
CoreExport virtual void MaybeEnlargeViewportRect(GraphicsWindow *gw, Rect &rect);
// quick render in viewport, using current TM.
//CoreExport virtual Display(TimeValue t, INode* inode, ViewExp *vpt, int flags) { return 0; };
// NS: 12-14-99 Classes that derive from Object *have* o call the following methods
// See examples in Triobj.cpp [END]
CoreExport bool IsBaseClassOwnedChannel(int nchan) { return (nchan == EXTENSION_CHAN_NUM) ? true : false;}
CoreExport void UpdateValidity(int nchan, Interval v); // AND in interval v to channel validity
Interval GetNoEvalInterval() { return noEvalInterval; }
void SetNoEvalInterval(Interval iv) {noEvalInterval = iv; }
// Give the object chance to reduce its caches,
// depending on the noEvalInterval.
CoreExport virtual void ReduceCaches(TimeValue t);
// Is this object a construction object:
virtual int IsConstObject() { return 0; }
// Retreives sub-object branches from an object that supports branching.
// Certain objects combine a series of input objects (pipelines) into
// a single object. These objects act as a multiplexor allowing the
// user to decide which branch(s) they want to see the history for.
//
// It is up to the object how they want to let the user choose. The object
// may use sub object selection to allow the user to pick a set of
// objects for which the common history will be displayed.
//
// When the history changes for any reason, the object should send
// a notification (REFMSG_BRANCHED_HISTORY_CHANGED) via NotifyDependents.
// The selected parameter is new in Rel. 4 and must be supported by all
// compound objects.
// In case the selected parameter is true the obejct should only return
// the number of pipebranches, that are currently selected in the UI (this
// is the way it worked in R3 and before.
// In case this parameter is false, the object has to return the number of
// *all* branches, no matter if they are selected or not
virtual int NumPipeBranches(bool selected = true) {return 0;}
// The selected parameter is new in Rel. 4 and must be supported by all
// compound objects.
// In case the selected parameter is true the obejct should only consider
// the branches, that are currently selected in the UI (this
// is the way it worked in R3 and before.
// In case this parameter is false, the object has to consider
// *all* branches, no matter if they are selected or not
virtual Object *GetPipeBranch(int i, bool selected = true) {return NULL;}
// When an object has sub-object branches, it is likely that the
// sub-objects are transformed relative to the object. This method
// gives the object a chance to modify the node's transformation so
// that operations (like edit modifiers) will work correctly when
// editing the history of the sub object branch.
// The selected parameter is new in Rel. 4 and must be supported by all
// compound objects.
// In case the selected parameter is true the obejct should only consider
// the branches, that are currently selected in the UI (this
// is the way it worked in R3 and before.
// In case this parameter is false, the object has to consider
// *all* branches, no matter if they are selected or not
virtual INode *GetBranchINode(TimeValue t,INode *node,int i, bool selected = true) {return node;}
// Shape viewports can reference shapes contained within objects, so we
// need to be able to access shapes within an object. The following methods
// provide this access
virtual int NumberOfContainedShapes() { return -1; } // NOT a container!
virtual ShapeObject *GetContainedShape(TimeValue t, int index) { return NULL; }
virtual void GetContainedShapeMatrix(TimeValue t, int index, Matrix3 &mat) {}
virtual BitArray ContainedShapeSelectionArray() { return BitArray(); }
// Return TRUE for ShapeObject class or GeomObjects that are Shapes too
virtual BOOL IsShapeObject() { return FALSE; }
// For debugging only. TriObject inplements this method by making sure
// its face's vert indices are all valid.
virtual BOOL CheckObjectIntegrity() {return TRUE;}
// Find out if the Object is generating UVW's
virtual BOOL HasUVW() { return 0; }
// or on any map channel:
virtual BOOL HasUVW (int mapChannel) { return (mapChannel==1) ? HasUVW() : FALSE; }
// This is overridden by DerivedObjects to search up the pipe for the base object
virtual Object *FindBaseObject() { return this; }
// Access a parametric position on the surface of the object
virtual BOOL IsParamSurface() {return FALSE;}
virtual int NumSurfaces(TimeValue t) {return 1;}
// Single-surface version (surface 0)
virtual Point3 GetSurfacePoint(TimeValue t, float u, float v,Interval &iv) {return Point3(0,0,0);}
// Multiple-surface version (Implement if you override NumSurfaces)
virtual Point3 GetSurfacePoint(TimeValue t, int surface, float u, float v,Interval &iv) {return Point3(0,0,0);}
// Get information on whether a surface is closed (default is closed both ways)
virtual void SurfaceClosed(TimeValue t, int surface, BOOL &uClosed, BOOL &vClosed) {uClosed = vClosed = TRUE;}
// Allow an object to return extended Properties fields
// Return TRUE if you take advantage of these, and fill in all strings
virtual BOOL GetExtendedProperties(TimeValue t, TSTR &prop1Label, TSTR &prop1Data, TSTR &prop2Label, TSTR &prop2Data) {return FALSE;}
// Animatable Overides...
CoreExport SvGraphNodeReference SvTraverseAnimGraph(IGraphObjectManager *gom, Animatable *owner, int id, DWORD flags);
CoreExport bool SvHandleDoubleClick(IGraphObjectManager *gom, IGraphNode *gNode);
CoreExport TSTR SvGetName(IGraphObjectManager *gom, IGraphNode *gNode, bool isBeingEdited);
CoreExport COLORREF SvHighlightColor(IGraphObjectManager *gom, IGraphNode *gNode);
CoreExport bool SvIsSelected(IGraphObjectManager *gom, IGraphNode *gNode);
CoreExport MultiSelectCallback* SvGetMultiSelectCallback(IGraphObjectManager *gom, IGraphNode *gNode);
CoreExport bool SvCanSelect(IGraphObjectManager *gom, IGraphNode *gNode);
//ExtensionChannel Access :
// Adds an extension object into the pipeline. The methods (Display,
// PreChanChangedNotify etc) of higher priority XTCObjects will becalled
// before those of lower priority XTCObjects
CoreExport void AddXTCObject(XTCObject *pObj, int priority = 0, int branchID = -1);
CoreExport int NumXTCObjects();
CoreExport XTCObject *GetXTCObject(int index);
CoreExport void RemoveXTCObject(int index);
CoreExport void SetXTCObjectPriority(int index,int priority);
CoreExport int GetXTCObjectPriority(int index);
CoreExport void SetXTCObjectBranchID(int index,int branchID);
CoreExport int GetXTCObjectBranchID(int index);
// This method has to be called whenever the CompoundObject updates a branch
// (calling Eval on it). Object *from is the object returned from Eval
// (os.obj);branchID is an int, that specifies that branch. The extension
// channel will get a callback to RemoveXTCObjectOnMergeBranches and MergeXTCObject.
// By default it returns true to RemoveXTCObjectOnMergeBranches, which means,
// that the existing XTCObjects with that branchID will be deleted. The method
// MergeXTCObject simply copies the XTCObjects from the incoming branch into the
// compound object.
CoreExport void MergeAdditionalChannels(Object *from, int branchID);
// This method has to be called on the CompoundObject, so it can delete the
// XTCObjects for the specific branch. The XTCObject will have again the final
// decision if the XTCObject gets really deleted or not in a callback to
// RemoveXTCObjectOnBranchDeleted(), which will return true, if the XTCOject
// should be removed.
CoreExport void BranchDeleted(int branchID, bool reorderChannels);
// This method copies all extension objects from the "from" objects into the
// current object. In case deleteOld is false, the objects will be appended.
// In case it is true, the old XTCObjects will be deleted.
CoreExport void CopyAdditionalChannels(Object *from, bool deleteOld = true, bool bShallowCopy = false);
CoreExport void DeleteAllAdditionalChannels();
// If this return FALSE, then no selection brackets are displayed on the object
virtual BOOL UseSelectionBrackets() { return TRUE; }
// returns TRUE for manipulator objcts and FALSE for all others
virtual BOOL IsManipulator() { return FALSE; }
void* GetInterface(ULONG id) { return BaseObject::GetInterface(id);}
CoreExport BaseInterface* GetInterface(Interface_ID id);
};
// This function should be used to count polygons in an object.
// It uses Object::PolygonCount() if it is supported, and converts to
// a TriObject and counts faces and vertices otherwise.
CoreExport void GetPolygonCount(TimeValue t, Object* pObj, int& numFaces, int& numVerts);
// This function to count trifaces of a mesh
// It works just like GetPolygonCount, where GetPolygonCount will count EditablePoly object's Polys as 1 Poly,
// instead of several trifaces. It also will not count splines unless their renderable property is true
CoreExport void GetTriMeshFaceCount(TimeValue t, Object* pObj, int& numFaces, int& numVerts);
// mjm - begin - 07.17.00
class CameraObject;
// -------------------------------
// multi-pass render camera effect
// -------------------------------
class IMultiPassCameraEffect : public ReferenceTarget
{
public:
// allows effect to declare it's compatibility with the current camera object
virtual bool IsCompatible(CameraObject *pCameraObject) = 0;
// indicates that the renderer should display each pass as it is rendered (not used by viewport renderer)
virtual bool DisplayPasses(TimeValue renderTime) = 0;
// indicates the total number of passes to be rendered
virtual int TotalPasses(TimeValue renderTime) = 0;
// called for each render pass. the effect can alter the camera node, camera object, or override the render time
virtual ViewParams *Apply(INode *pCameraNode, CameraObject *pCameraObject, int passNum, TimeValue &overrideRenderTime) = 0;
// allows the effect to blend its own passes (not used by the viewport renderer)
virtual void AccumulateBitmap(Bitmap *pDest, Bitmap *pSrc, int passNum, TimeValue renderTime) = 0;
// convenience function, called after all passes have been rendered. can be ignored.
virtual void PostRenderFrame() = 0;
// from class ReferenceMaker
virtual RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message) { return REF_SUCCEED; }
// from class Animatable
virtual SClass_ID SuperClassID() { return MPASS_CAM_EFFECT_CLASS_ID; }
virtual void BeginEditParams(IObjParam *ip, ULONG flags, Animatable *prev=NULL) {}
virtual void EndEditParams(IObjParam *ip, ULONG flags, Animatable *next=NULL) {}
};
// mjm - end
// ------------
// CameraObject
// ------------
#define CAM_HITHER_CLIP 1
#define CAM_YON_CLIP 2
#define ENV_NEAR_RANGE 0
#define ENV_FAR_RANGE 1
struct CameraState {
inline CameraState() {cbStruct = sizeof(CameraState);}
DWORD cbStruct;
BOOL isOrtho; // true if cam is ortho, false for persp
float fov; // field-of-view for persp cams, width for ortho cams
float tdist; // target distance for free cameras
BOOL horzLine; // horizon line display state
int manualClip;
float hither;
float yon;
float nearRange;
float farRange;
};
class CameraObject : public Object
{
public:
SClass_ID SuperClassID() { return CAMERA_CLASS_ID; }
int IsRenderable() { return(0);}
virtual void InitNodeName(TSTR& s) { s = _T("Camera"); }
virtual int UsesWireColor() { return FALSE; } // TRUE if the object color is used for display
// Methods specific to cameras:
//*************************************************************
// NOTE:
//
// To ensure that the camera has a valid targDist during
// network rendering, be sure to call:
//
// UpdateTargDistance( TimeValue t, INode* inode );
//
// This call should be made PRIOR to cameraObj->EvalWorldState(...)
//*************************************************************
virtual RefResult EvalCameraState(TimeValue time, Interval& valid, CameraState* cs)=0;
virtual void SetOrtho(BOOL b)=0;
virtual BOOL IsOrtho()=0;
virtual void SetFOV(TimeValue time, float f)=0;
virtual float GetFOV(TimeValue t, Interval& valid = Interval(0,0))=0;
virtual void SetTDist(TimeValue time, float f)=0;
virtual float GetTDist(TimeValue t, Interval& valid = Interval(0,0))=0;
virtual int GetManualClip()=0;
virtual void SetManualClip(int onOff)=0;
virtual float GetClipDist(TimeValue t, int which, Interval &valid=Interval(0,0))=0;
virtual void SetClipDist(TimeValue t, int which, float val)=0;
virtual void SetEnvRange(TimeValue time, int which, float f)=0;
virtual float GetEnvRange(TimeValue t, int which, Interval& valid = Interval(0,0))=0;
virtual void SetEnvDisplay(BOOL b, int notify=TRUE)=0;
virtual BOOL GetEnvDisplay(void)=0;
virtual void RenderApertureChanged(TimeValue t)=0;
virtual void UpdateTargDistance(TimeValue t, INode* inode) { }
// mjm - begin - 07.17.00
virtual void SetMultiPassEffectEnabled(TimeValue t, BOOL enabled) { }
virtual BOOL GetMultiPassEffectEnabled(TimeValue t, Interval& valid) { return FALSE; }
virtual void SetMPEffect_REffectPerPass(BOOL enabled) { }
virtual BOOL GetMPEffect_REffectPerPass() { return FALSE; }
virtual void SetIMultiPassCameraEffect(IMultiPassCameraEffect *pIMultiPassCameraEffect) { }
virtual IMultiPassCameraEffect *GetIMultiPassCameraEffect() { return NULL; }
// mjm - end
};
/*-------------------------------------------------------------------
LightObject:
---------------------------------------------------------------------*/
#define LIGHT_ATTEN_START 0
#define LIGHT_ATTEN_END 1
struct LightState {
LightType type;
Matrix3 tm;
Color color;
float intens; // multiplier value
float hotsize;
float fallsize;
int useNearAtten;
float nearAttenStart;
float nearAttenEnd;
int useAtten;
float attenStart;
float attenEnd;
int shape;
float aspect;
BOOL overshoot;
BOOL shadow;
BOOL on; // light is on
BOOL affectDiffuse;
BOOL affectSpecular;
BOOL ambientOnly; // affect only ambient component
DWORD extra;
};
class LightDesc;
class RendContext;
// This is a callback class that can be given to a ObjLightDesc
// to have a ray traced through the light volume.
class LightRayTraversal {
public:
// This is called for every step (return FALSE to halt the integration).
// t0 and t1 define the segment in terms of the given ray.
// illum is the light intensity over the entire segment. It can be
// assumed that the light intensty is constant for the segment.
virtual BOOL Step(float t0, float t1, Color illum, float distAtten)=0;
};
// Flags passed to TraverseVolume
#define TRAVERSE_LOWFILTSHADOWS (1<<0)
#define TRAVERSE_HIFILTSHADOWS (1<<1)
#define TRAVERSE_USESAMPLESIZE (1<<2)
////////////////////////////////////////////////////////////////////////
// The following classes, IlluminateComponents & IlluminationComponents,
// have been added in 3ds max 4.2. If your plugin utilizes this new
// mechanism, be sure that your clients are aware that they
// must run your plugin with 3ds max version 4.2 or higher.
// Extension to provide the components of the Illuminate function to
// Shaders, materials & render elements
// This class holds the output components of illuminate
class IlluminateComponents : public BaseInterfaceServer {
public:
Point3 L; // light vector
float NL; // N dot L
// these are the attenuations due to the light
float geometricAtten; // final constrast applied to N.L
float shapeAtten; // due to cone(s) falloff
float distanceAtten; // attenuation due to distance, falloff
// this is the composite attenuation due to all shadowing objects
// transparent bojects may supply some shadowAtten as well as filterAtten
float shadowAtten; // 0 == all shadow, 1 == all light
// these allow smooth control over how the light
// affects these basic shading components
float ambientAtten; // 0 == no ambient, 1 = all ambient
float diffuseAtten; // 0 == no diffuse, 1 = all diffuse
float specularAtten; // 0 == no specular, 1 = all specular
// The complete amount of light falling on the point sc.P() orientied
// in the direction sc.N() is the filteredColor. if( rawColor!=filteredColor)
// then it's filtered, else unfiltered
// light color modulated by map value,
// unattenuated, w/ raw light if no map
Color rawColor;
// light color modulated by map value,
// then filtered by a transparent object,
// raw color * filterAtten, otherwise unattenuated,
Color filteredColor;
// color due to user shadow color, modulated by a possible map,
// attenuated by 1-shadowAtten
Color shadowColor;
// these are the combined light colors modulated by the ambientAtten'uators
// they can be used by shaders to compute diffuse & specular shading
// complete component color is e.g. lightDiffuseColor+shadowColor
// NB: the geometric atten is to be applied by the shader, not the light
// e.g. lightAmbientColor =
// ambientAtten * (shapeAtten*distAtten*shadowAtten)
// * filteredColor;
Color lightAmbientColor; // ambient color due to light, attenuated, w/o shadow color
Color lightDiffuseColor; // diffuse color due to light, attenuated, w/o shadow color
Color lightSpecularColor; // specular color due to light, attenuated, w/o shadow color
// these are equivalent to 4.0 final illumination color, with & without shadows
// finalColor = shadowColor + (shapeAtten * distAtten * shadowAtten)
// * filteredColor;
Color finalColor;
// Like final color but no shadow attenuation applied & no shadowColor
// finalColorNS = (shapeAtten * distAtten) * filteredColor;
Color finalColorNS;
// user extensible component outputs, name matched
int nUserIllumOut; // one set of names for all illum params instances
TCHAR** userIllumNames; // we just keep ptr to shared name array, never destroyed
Color* userIllumOut; // the user illum color array, new'd & deleted w/ the class
IlluminateComponents(): nUserIllumOut(0),userIllumOut(NULL),userIllumNames(NULL) {}
~IlluminateComponents(){if(userIllumOut) delete userIllumOut; };
// returns number of user illum channels for this material
int nUserIllumChannels(){ return nUserIllumOut; }
// returns null if no name array specified
TCHAR* GetUserIllumName( int n ) {
DbgAssert( n < nUserIllumOut );
if( userIllumNames )
return userIllumNames[n];
return NULL;
}
// render elements, mtls & shaders can use this to find the index associated with a name
// returns -1 if it can't find the name
int FindUserIllumName( TCHAR* name ){
int n = -1;
for( int i = 0; i < nUserIllumOut; ++i ){
DbgAssert( userIllumNames );
if( _tcscmp( name, userIllumNames[i] ) == 0 ){
n = i;
break;
}
}
return n;
}
// knowing the index, these set/get the user illum output color
void SetUserIllumOutput( int n, Color& out ){
DbgAssert( n < nUserIllumOut );
userIllumOut[n] = out;
}
Color GetUserIllumOutput( int n ){
DbgAssert( n < nUserIllumOut );
return userIllumOut[n];
}
void Reset(){
NL = geometricAtten = shapeAtten = distanceAtten = shadowAtten
= ambientAtten = diffuseAtten = specularAtten = 0.0f;
rawColor.Black();
filteredColor.Black();
lightAmbientColor.Black();
lightDiffuseColor.Black();
lightSpecularColor.Black();
shadowColor.Black();
finalColor.Black();
finalColorNS.Black();
L = Point3( 0,0,0 );
if(nUserIllumOut>0 && userIllumOut){
for(int i=0; i<nUserIllumOut; ++i )
userIllumOut[i].Black();
}
}
}; // end, IlluminateComponents
// must be greater than I_USERINTERFACE in maxsdk/include/animtbl.h
#define IID_IIlluminationComponents Interface_ID(0xdae00001, 0x0)
// this is the interface to use illumination by components
// this may be supported by a light object
// returned by lightObjDesc::GetInterface( IID_IIlluminationComponents );
class IIlluminationComponents : public BaseInterface {
public:
virtual BOOL Illuminate(ShadeContext& sc, Point3& normal, IlluminateComponents& illumComp )=0;
};
// End of IlluminateComponents & IlluminationComponent 3ds max 4.2 Extension
// A light must be able to create one of these to give to the renderer.
// The Illuminate() method (inherited from LightDesc) is called by the renderer
// to illuminate a surface point.
class ObjLightDesc : public LightDesc {
public:
// This data will be set up by the default implementation of Update()
LightState ls;
INode *inode;
BOOL uniformScale; // for optimizing
Point3 lightPos;
Matrix3 lightToWorld;
Matrix3 worldToLight;
Matrix3 lightToCam; // updated in UpdateViewDepParams
Matrix3 camToLight; // updated in UpdateViewDepParams
int renderNumber; // set by the renderer. Used in RenderInstance::CastsShadowsFrom()
CoreExport ObjLightDesc(INode *n);
CoreExport virtual ~ObjLightDesc();
virtual ExclList* GetExclList() { return NULL; }
// update light state that depends on position of objects&lights in world.
CoreExport virtual int Update(TimeValue t, const RendContext &rc, RenderGlobalContext *rgc, BOOL shadows, BOOL shadowGeomChanged);
// update light state that depends on global light level.
CoreExport virtual void UpdateGlobalLightLevel(Color globLightLevel) {}
// update light state that depends on view matrix.
CoreExport virtual int UpdateViewDepParams(const Matrix3& worldToCam);
// default implementation
CoreExport virtual Point3 LightPosition() { return lightPos; }
// This function traverses a ray through the light volume.
// 'ray' defines the parameter line that will be traversed.
// 'minStep' is the smallest step size that caller requires, Note that
// the callback may be called in smaller steps if they light needs to
// take smaller steps to avoid under sampling the volume.
// 'tStop' is the point at which the traversal will stop (ray.p+tStop*ray.dir).
// Note that the traversal can terminate earlier if the callback returns FALSE.
// 'proc' is the callback object.
//
// attenStart/End specify a percent of the light attenuation distances
// that should be used for lighting durring the traversal.
//
// The shade context passed in should only be used for state (like are
// shadows globaly disabled). The position, normal, etc. serve no purpose.
virtual void TraverseVolume(
ShadeContext& sc,
const Ray &ray, int samples, float tStop,
float attenStart, float attenEnd,
DWORD flags,
LightRayTraversal *proc) {}
};
// Values returned from GetShadowMethod()
#define LIGHTSHADOW_NONE 0
#define LIGHTSHADOW_MAPPED 1
#define LIGHTSHADOW_RAYTRACED 2
class LightObject: public Object {
public:
SClass_ID SuperClassID() { return LIGHT_CLASS_ID; }
int IsRenderable() { return(0);}
virtual void InitNodeName(TSTR& s) { s = _T("Light"); }
// Methods specific to Lights:
virtual RefResult EvalLightState(TimeValue time, Interval& valid, LightState *ls)=0;
virtual ObjLightDesc *CreateLightDesc(INode *n, BOOL forceShadowBuffer=FALSE) {return NULL;}
//JH 06/03/03 new api to pass globalRenderContext
virtual ObjLightDesc *CreateLightDesc(RenderGlobalContext *rgc, INode *inode, BOOL forceShadowBuf=FALSE ){return NULL;}
virtual void SetUseLight(int onOff)=0;
virtual BOOL GetUseLight(void)=0;
virtual void SetHotspot(TimeValue time, float f)=0;
virtual float GetHotspot(TimeValue t, Interval& valid = Interval(0,0))=0;
virtual void SetFallsize(TimeValue time, float f)=0;
virtual float GetFallsize(TimeValue t, Interval& valid = Interval(0,0))=0;
virtual void SetAtten(TimeValue time, int which, float f)=0;
virtual float GetAtten(TimeValue t, int which, Interval& valid = Interval(0,0))=0;
virtual void SetTDist(TimeValue time, float f)=0;
virtual float GetTDist(TimeValue t, Interval& valid = Interval(0,0))=0;
virtual void SetConeDisplay(int s, int notify=TRUE)=0;
virtual BOOL GetConeDisplay(void)=0;
virtual int GetShadowMethod() {return LIGHTSHADOW_NONE;}
virtual void SetRGBColor(TimeValue t, Point3& rgb) {}
virtual Point3 GetRGBColor(TimeValue t, Interval &valid = Interval(0,0)) {return Point3(0,0,0);}
virtual void SetIntensity(TimeValue time, float f) {}
virtual float GetIntensity(TimeValue t, Interval& valid = Interval(0,0)) {return 0.0f;}
virtual void SetAspect(TimeValue t, float f) {}
virtual float GetAspect(TimeValue t, Interval& valid = Interval(0,0)) {return 0.0f;}
virtual void SetUseAtten(int s) {}
virtual BOOL GetUseAtten(void) {return FALSE;}
virtual void SetAttenDisplay(int s) {}
virtual BOOL GetAttenDisplay(void) {return FALSE;}
virtual void Enable(int enab) {}
virtual void SetMapBias(TimeValue t, float f) {}
virtual float GetMapBias(TimeValue t, Interval& valid = Interval(0,0)) {return 0.0f;}
virtual void SetMapRange(TimeValue t, float f) {}
virtual float GetMapRange(TimeValue t, Interval& valid = Interval(0,0)) {return 0.0f;}
virtual void SetMapSize(TimeValue t, int f) {}
virtual int GetMapSize(TimeValue t, Interval& valid = Interval(0,0)) {return 0;}
virtual void SetRayBias(TimeValue t, float f) {}
virtual float GetRayBias(TimeValue t, Interval& valid = Interval(0,0)) {return 0.0f;}
virtual int GetUseGlobal() {return 0;}
virtual void SetUseGlobal(int a) {}
virtual int GetShadow() {return 0;}
virtual void SetShadow(int a) {}
virtual int GetShadowType() {return 0;}
virtual void SetShadowType(int a) {}
virtual int GetAbsMapBias() {return 0;}
virtual void SetAbsMapBias(int a) {}
virtual int GetOvershoot() {return 0;}
virtual void SetOvershoot(int a) {}
virtual int GetProjector() {return 0;}
virtual void SetProjector(int a) {}
virtual ExclList* GetExclList() {return NULL;}
virtual BOOL Include() {return FALSE;}
virtual Texmap* GetProjMap() {return NULL;}
virtual void SetProjMap(Texmap* pmap) {}
virtual void UpdateTargDistance(TimeValue t, INode* inode) {}
};
/*-------------------------------------------------------------------
HelperObject:
---------------------------------------------------------------------*/
class HelperObject: public Object {
public:
SClass_ID SuperClassID() { return HELPER_CLASS_ID; }
int IsRenderable() { return(0); }
virtual void InitNodeName(TSTR& s) { s = _T("Helper"); }
virtual int UsesWireColor() { return FALSE; } // TRUE if the object color is used for display
virtual BOOL NormalAlignVector(TimeValue t,Point3 &pt, Point3 &norm) {pt=Point3(0,0,0);norm=Point3(0,0,-1);return TRUE;}
};
/*-------------------------------------------------------------------
ConstObject:
---------------------------------------------------------------------*/
#define GRID_PLANE_NONE -1
#define GRID_PLANE_TOP 0
#define GRID_PLANE_LEFT 1
#define GRID_PLANE_FRONT 2
#define GRID_PLANE_BOTTOM 3
#define GRID_PLANE_RIGHT 4
#define GRID_PLANE_BACK 5
class ConstObject: public HelperObject {
private:
bool m_transient;
bool m_temporary; // 030730 --prs.
public:
ConstObject() { m_transient = m_temporary = false; }
// Override this function in HelperObject!
int IsConstObject() { return 1; }
// Methods specific to construction grids:
virtual void GetConstructionTM( TimeValue t, INode* inode, ViewExp *vpt, Matrix3 &tm ) = 0; // Get the transform for this view
virtual void SetConstructionPlane(int which, int notify=TRUE) = 0;
virtual int GetConstructionPlane(void) = 0;
virtual Point3 GetSnaps( TimeValue t ) = 0; // Get snap values
virtual void SetSnaps(TimeValue t, Point3 p) = 0;
virtual BOOL NormalAlignVector(TimeValue t,Point3 &pt, Point3 &norm) {pt=Point3(0,0,0);norm=Point3(0,0,-1);return TRUE;}
//JH 09/28/98 for design ver
bool IsTransient()const {return m_transient;}
void SetTransient(bool state = true) {m_transient = state;}
// grid bug fix, 030730 --prs.
bool IsTemporary() const { return m_temporary; }
void SetTemporary(bool state = true) { m_temporary = state; }
//JH 11/16/98
virtual void SetExtents(TimeValue t, Point3 halfbox)=0;
virtual Point3 GetExtents(TimeValue t)=0;
//JH 09/28/98 for design ver
// bool IsImplicit()const {return m_implicit;}
// void SetImplicit(bool state = true) {m_implicit = state;}
};
/*-------------------------------------------------------------------
GeomObject: these are the Renderable objects.
---------------------------------------------------------------------*/
class GeomObject: public Object {
public:
virtual void InitNodeName(TSTR& s) { s = _T("Object"); }
SClass_ID SuperClassID() { return GEOMOBJECT_CLASS_ID; }
virtual int IsRenderable() { return(1); }
// If an object creates different meshes depending on the
// particular instance (view-dependent) it should return 1.
virtual int IsInstanceDependent() { return 0; }
// GetRenderMesh should be implemented by all renderable GeomObjects.
// set needDelete to TRUE if the render should delete the mesh, FALSE otherwise
// Primitives that already have a mesh cached can just return a pointer
// to it (and set needDelete = FALSE).
CoreExport virtual Mesh* GetRenderMesh(TimeValue t, INode *inode, View& view, BOOL& needDelete);
// Objects may now supply multiple render meshes ( e.g. particle systems). If this function
// returns a positive number, then GetMultipleRenderMesh and GetMultipleRenderMeshTM will be
// called for each mesh, instead of calling GetRenderMesh // DS 5/10/00
virtual int NumberOfRenderMeshes() { return 0; } // 0 indicates multiple meshes not supported.
// For multiple render meshes, this method must be implemented.
// set needDelete to TRUE if the render should delete the mesh, FALSE otherwise
// meshNumber specifies which of the multiplie meshes is being asked for.// DS 5/10/00
virtual Mesh* GetMultipleRenderMesh(TimeValue t, INode *inode, View& view, BOOL& needDelete, int meshNumber) { return NULL; }
// For multiple render meshes, this method must be implemented.
// meshTM should be returned with the transform defining the offset of the particular mesh in object space.
// meshTMValid should contain the validity interval of meshTM // DS 5/10/00
virtual void GetMultipleRenderMeshTM(TimeValue t, INode *inode, View& view, int meshNumber,
Matrix3& meshTM, Interval& meshTMValid) { return; }
// If this returns NULL, then GetRenderMesh will be called
CoreExport virtual PatchMesh* GetRenderPatchMesh(TimeValue t, INode *inode, View& view, BOOL& needDelete);
CoreExport Class_ID PreferredCollapseType();
virtual BOOL CanDoDisplacementMapping() { return 0; }
private:
};
//-- Particle Systems ---------------------------------------------------
// A force field can be applied to a particle system by a SpaceWarp.
// The force field provides a function of position in space, velocity
// and time that gives a force.
// The force is then used to compute an acceleration on a particle
// which modifies its velocity. Typically, particles are assumed to
// to have a normalized uniform mass==1 so the acceleration is F/M = F.
class ForceField : public InterfaceServer {
public:
virtual Point3 Force(TimeValue t,const Point3 &pos, const Point3 &vel, int index)=0;
virtual void SetRandSeed(int seed) {}
virtual void DeleteThis() {}
};
// A collision object can be applied to a particle system by a SpaceWarp.
// The collision object checks a particle's position and velocity and
// determines if the particle will colide with it in the next dt amount of
// time. If so, it modifies the position and velocity.
class CollisionObject : public InterfaceServer {
public:
// Check for collision. Return TRUE if there was a collision and the position and velocity have been modified.
virtual BOOL CheckCollision(TimeValue t,Point3 &pos, Point3 &vel, float dt,int index, float *ct=NULL, BOOL UpdatePastCollide=TRUE)=0;
virtual Object *GetSWObject()=0;
virtual void SetRandSeed(int seed) {}
virtual void DeleteThis() {}
};
// Values returned from ParticleCenter()
#define PARTCENTER_HEAD 1 // Particle geometry lies behind the particle position
#define PARTCENTER_CENTER 2 // Particle geometry is centered around particle position
#define PARTCENTER_TAIL 3 // Particle geometry lies in front of the particle position
// The particle system class derived from GeomObject and still has
// GEOMOBJECT_CLASS_ID as its super class.
//
// Given an object, to determine if it is a ParticleObject, call
// GetInterface() with the ID I_PARTICLEOBJ or use the macro
// GetParticleInterface(anim) which returns a ParticleObject* or NULL.
class ParticleObject: public GeomObject {
public:
BOOL IsParticleSystem() {return TRUE;}
virtual void ApplyForceField(ForceField *ff)=0;
virtual BOOL ApplyCollisionObject(CollisionObject *co)=0; // a particle can choose no to support this and return FALSE
// A particle object IS deformable, but does not let itself be
// deformed using the usual GetPoint/SetPoint methods. Instead
// a space warp must apply a force field to deform the particle system.
int IsDeformable() {return TRUE;}
// Particle objects don't actually do a shallow copy and therefore
// cannot be cached.
BOOL CanCacheObject() {return FALSE;}
virtual BOOL NormalAlignVector(TimeValue t,Point3 &pt, Point3 &norm) {pt=Point3(0,0,0);norm=Point3(0,0,-1);return TRUE;}
// These methods provide information about individual particles
virtual Point3 ParticlePosition(TimeValue t,int i) {return Point3(0,0,0);}
virtual Point3 ParticleVelocity(TimeValue t,int i) {return Point3(0,0,0);}
virtual float ParticleSize(TimeValue t,int i) {return 0.0f;}
virtual int ParticleCenter(TimeValue t,int i) {return PARTCENTER_CENTER;}
virtual TimeValue ParticleAge(TimeValue t, int i) {return -1;}
virtual TimeValue ParticleLife(TimeValue t, int i) {return -1;}
// This tells the renderer if the ParticleObject's topology doesn't change over time
// so it can do better motion blur. This means the correspondence of vertex id to
// geometrical vertex must be invariant.
virtual BOOL HasConstantTopology() { return FALSE; }
};
//----------------------------------------------------------------------
/*-------------------------------------------------------------------
ShapeObject: these are the open or closed hierarchical shape objects.
---------------------------------------------------------------------*/
class PolyShape;
class BezierShape;
class MeshCapInfo;
class PatchCapInfo;
class ShapeHierarchy;
// This class may be requested in the pipeline via the GENERIC_SHAPE_CLASS_ID,
// also set up in the Class_ID object genericShapeClassID
// Options for steps in MakePolyShape (>=0: Use fixed steps)
#define PSHAPE_BUILTIN_STEPS -2 // Use the shape's built-in steps/adaptive settings (default)
#define PSHAPE_ADAPTIVE_STEPS -1 // Force adaptive steps
// Parameter types for shape interpolation (Must match types in spline3d.h & polyshp.h)
#define PARAM_SIMPLE 0 // Parameter space based on segments
#define PARAM_NORMALIZED 1 // Parameter space normalized to curve length
// GenerateMesh Options
#define GENMESH_DEFAULT -1 // Use whatever is stored in the ShapeObject's UseViewport flag
#define GENMESH_VIEWPORT 0
#define GENMESH_RENDER 1
// Defines for number of ShapeObject references/subanims
#define SHAPE_OBJ_NUM_REFS 1
#define SHAPE_OBJ_NUM_SUBS 1
class IParamBlock;
class IParamMap;
class ShapeObject: public GeomObject {
friend class SObjRenderingDlgProc;
IObjParam *ip;
IParamBlock *sopblock; // New for r4, renderable version parameter block
static IParamMap *pmap;
int loadVersion;
// Display mesh cache stuff
Mesh meshCache;
Interval cacheValid;
int cacheType;
public:
CoreExport ShapeObject();
CoreExport ~ShapeObject(); // Must call this on destruction
virtual BOOL IsShapeObject() { return TRUE; }
virtual int IntersectRay(TimeValue t, Ray& ray, float& at, Point3& norm) {return FALSE;}
virtual void InitNodeName(TSTR& s) { s = _T("Shape"); }
SClass_ID SuperClassID() { return SHAPE_CLASS_ID; }
CoreExport virtual int IsRenderable();
CoreExport virtual void CopyBaseData(ShapeObject &from);
// Access methods
CoreExport float GetThickness(TimeValue t, Interval &ivalid);
CoreExport int GetSides(TimeValue t, Interval &ivalid);
CoreExport float GetAngle(TimeValue t, Interval &ivalid);
CoreExport float GetViewportThickness();
CoreExport int GetViewportSides();
CoreExport float GetViewportAngle();
CoreExport BOOL GetRenderable();
CoreExport BOOL GetGenUVs();
CoreExport BOOL GetDispRenderMesh();
CoreExport BOOL GetUseViewport();
CoreExport BOOL GetViewportOrRenderer();
CoreExport void SetThickness(TimeValue t, float thick);
CoreExport void SetSides(TimeValue t, int s);
CoreExport void SetAngle(TimeValue t, float a);
CoreExport void SetViewportThickness(float thick);
CoreExport void SetViewportSides(int s);
CoreExport void SetViewportAngle(float a);
CoreExport void SetRenderable(BOOL sw);
CoreExport void SetGenUVs(BOOL sw);
CoreExport void SetDispRenderMesh(BOOL sw);
CoreExport void SetUseViewport(BOOL sw);
CoreExport void SetViewportOrRenderer(BOOL sw);
CoreExport virtual Mesh* GetRenderMesh(TimeValue t, INode *inode, View& view, BOOL& needDelete);
CoreExport virtual void GetRenderMeshInfo(TimeValue t, INode *inode, View& view, int &nverts, int &nfaces); // Get info on the rendering mesh
CoreExport virtual void GenerateMesh(TimeValue t, int option, Mesh *mesh);
virtual int NumberOfVertices(TimeValue t, int curve = -1) { return 0; } // Informational only, curve = -1: total in all curves
virtual int NumberOfCurves()=0; // Number of curve polygons in the shape
virtual BOOL CurveClosed(TimeValue t, int curve)=0; // Returns TRUE if the curve is closed
virtual Point3 InterpCurve3D(TimeValue t, int curve, float param, int ptype=PARAM_SIMPLE)=0; // Interpolate from 0-1 on a curve
virtual Point3 TangentCurve3D(TimeValue t, int curve, float param, int ptype=PARAM_SIMPLE)=0; // Get tangent at point on a curve
virtual float LengthOfCurve(TimeValue t, int curve)=0; // Get the length of a curve
virtual int NumberOfPieces(TimeValue t, int curve)=0; // Number of sub-curves in a curve
virtual Point3 InterpPiece3D(TimeValue t, int curve, int piece, float param, int ptype=PARAM_SIMPLE)=0; // Interpolate from 0-1 on a sub-curve
virtual Point3 TangentPiece3D(TimeValue t, int curve, int piece, float param, int ptype=PARAM_SIMPLE)=0; // Get tangent on a sub-curve
virtual MtlID GetMatID(TimeValue t, int curve, int piece) { return 0; }
virtual BOOL CanMakeBezier() { return FALSE; } // Return TRUE if can turn into a bezier representation
virtual void MakeBezier(TimeValue t, BezierShape &shape) {} // Create the bezier representation
virtual ShapeHierarchy &OrganizeCurves(TimeValue t, ShapeHierarchy *hier=NULL)=0; // Ready for lofting, extrusion, etc.
virtual void MakePolyShape(TimeValue t, PolyShape &shape, int steps = PSHAPE_BUILTIN_STEPS, BOOL optimize = FALSE)=0; // Create a PolyShape representation with optional fixed steps & optimization
virtual int MakeCap(TimeValue t, MeshCapInfo &capInfo, int capType)=0; // Generate mesh capping info for the shape
virtual int MakeCap(TimeValue t, PatchCapInfo &capInfo) { return 0; } // Only implement if CanMakeBezier=TRUE -- Gen patch cap info
virtual BOOL AttachShape(TimeValue t, INode *thisNode, INode *attachNode, BOOL weldEnds=FALSE, float weldThreshold=0.0f) { return FALSE; } // Return TRUE if attached
// UVW Mapping switch access
virtual BOOL HasUVW() { return GetGenUVs(); }
virtual void SetGenUVW(BOOL sw) { SetGenUVs(sw); }
// These handle loading and saving the data in this class. Should be called
// by derived class BEFORE it loads or saves any chunks
CoreExport virtual IOResult Save(ISave *isave);
CoreExport virtual IOResult Load(ILoad *iload);
CoreExport virtual Class_ID PreferredCollapseType();
CoreExport virtual BOOL GetExtendedProperties(TimeValue t, TSTR &prop1Label, TSTR &prop1Data, TSTR &prop2Label, TSTR &prop2Data);
CoreExport virtual void RescaleWorldUnits(float f);
// New reference support for r4
CoreExport virtual RefResult ShapeObject::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message );
CoreExport virtual RefTargetHandle GetReference(int i);
CoreExport virtual void SetReference(int i, RefTargetHandle rtarg);
CoreExport virtual Animatable* SubAnim(int i);
CoreExport virtual TSTR SubAnimName(int i);
CoreExport ParamDimension *GetParameterDim(int pbIndex);
CoreExport TSTR GetParameterName(int pbIndex);
CoreExport virtual int RemapRefOnLoad(int iref);
virtual int NumRefs() {return 1;}
virtual int NumSubs() {return 1;}
CoreExport void BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev);
CoreExport void EndEditParams( IObjParam *ip, ULONG flags,Animatable *next);
// Get the validity of the ShapeObject parts
CoreExport Interval GetShapeObjValidity(TimeValue t);
// The following displays the shape's generated mesh if necessary
CoreExport int Display(TimeValue t, INode *inode, ViewExp* vpt, int flags);
// Get the bounding box for the shape, if it's active. Leaves bbox unchanged if not.
CoreExport virtual Box3 GetBoundingBox(TimeValue t, Matrix3 *tm=NULL);
CoreExport virtual void InvalidateGeomCache();
private:
};
// Set ShapeObject's global Constant Cross-Section angle threshold (angle in radians) --
// Used for renderable shapes.
CoreExport void SetShapeObjectCCSThreshold(float angle);
/*-------------------------------------------------------------------
WSMObject : This is the helper object for the WSM modifier
---------------------------------------------------------------------*/
class WSMObject: public Object {
public:
SClass_ID SuperClassID() { return WSM_OBJECT_CLASS_ID; }
virtual Modifier *CreateWSMMod(INode *node)=0;
virtual int UsesWireColor() { return FALSE; } // TRUE if the object color is used for display
virtual BOOL NormalAlignVector(TimeValue t,Point3 &pt, Point3 &norm) {pt=Point3(0,0,0);norm=Point3(0,0,-1);return TRUE;}
virtual BOOL SupportsDynamics() { return FALSE; } // TRUE if spacewarp or collision object supports Dynamics
virtual ForceField *GetForceField(INode *node) {return NULL;}
virtual CollisionObject *GetCollisionObject(INode *node) {return NULL;}
private:
};
//--- Interface to XRef objects ---------------------------------------------------
class IXRefObject: public Object {
public:
Class_ID ClassID() {return Class_ID(XREFOBJ_CLASS_ID,0);}
SClass_ID SuperClassID() {return SYSTEM_CLASS_ID;}
// Initialize a new XRef object
virtual void Init(TSTR &fname, TSTR &oname, Object *ob, BOOL asProxy=FALSE)=0;
virtual void SetFileName(TCHAR *name, BOOL proxy=FALSE, BOOL update=TRUE)=0;
virtual void SetObjName(TCHAR *name, BOOL proxy=FALSE)=0;
virtual void SetUseProxy(BOOL onOff,BOOL redraw=TRUE)=0;
virtual void SetRenderProxy(BOOL onOff)=0;
virtual void SetUpdateMats(BOOL onOff)=0;
virtual void SetIgnoreAnim(BOOL onOff,BOOL redraw=TRUE)=0;
virtual TSTR GetFileName(BOOL proxy=FALSE)=0;
virtual TSTR GetObjName(BOOL proxy=FALSE)=0;
virtual TSTR &GetCurFileName()=0;
virtual TSTR &GetCurObjName()=0;
virtual BOOL GetUseProxy()=0;
virtual BOOL GetRenderProxy()=0;
virtual BOOL GetUpdateMats()=0;
virtual BOOL GetIgnoreAnim()=0;
// Causes browse dialogs to appear
virtual void BrowseObject(BOOL proxy)=0;
virtual void BrowseFile(BOOL proxy)=0;
// Try to reload ref
virtual void ReloadXRef()=0;
};
//---------------------------------------------------------------------------------
class ControlMatrix3;
// Used with EnumModContexts()
class ModContextEnumProc {
public:
virtual BOOL proc(ModContext *mc)=0; // Return FALSE to stop, TRUE to continue.
};
/*-------------------------------------------------------------------
Modifier: these are the ObjectSpace and World Space modifiers: They are
subclassed off of BaseObject so that they can put up a graphical
representation in the viewport.
---------------------------------------------------------------------*/
class Modifier: public BaseObject {
friend class ModNameRestore;
TSTR modName;
public:
CoreExport virtual TSTR GetName();
CoreExport virtual void SetName(TSTR n);
SClass_ID SuperClassID() { return OSM_CLASS_ID; }
// Disables all mod apps that reference this modifier _and_ have a select
// anim flag turned on.
void DisableModApps() { NotifyDependents(FOREVER,PART_OBJ,REFMSG_DISABLE); }
void EnableModApps() { NotifyDependents(FOREVER,PART_OBJ,REFMSG_ENABLE); }
// This disables or enables the mod. All mod apps referencing will be affected.
void DisableMod() {
SetAFlag(A_MOD_DISABLED);
NotifyDependents(FOREVER,PART_ALL|PART_OBJECT_TYPE,REFMSG_CHANGE);
}
void EnableMod() {
ClearAFlag(A_MOD_DISABLED);
NotifyDependents(FOREVER,PART_ALL|PART_OBJECT_TYPE,REFMSG_CHANGE);
}
int IsEnabled() { return !TestAFlag(A_MOD_DISABLED); }
// Same as above but for viewports only
void DisableModInViews() {
SetAFlag(A_MOD_DISABLED_INVIEWS);
NotifyDependents(FOREVER,PART_ALL|PART_OBJECT_TYPE,REFMSG_CHANGE);
}
void EnableModInViews() {
ClearAFlag(A_MOD_DISABLED_INVIEWS);
NotifyDependents(FOREVER,PART_ALL|PART_OBJECT_TYPE,REFMSG_CHANGE);
}
int IsEnabledInViews() { return !TestAFlag(A_MOD_DISABLED_INVIEWS); }
// Same as above but for renderer only
void DisableModInRender() {
SetAFlag(A_MOD_DISABLED_INRENDER);
NotifyDependents(FOREVER,PART_ALL|PART_OBJECT_TYPE,REFMSG_CHANGE);
}
void EnableModInRender() {
ClearAFlag(A_MOD_DISABLED_INRENDER);
NotifyDependents(FOREVER,PART_ALL|PART_OBJECT_TYPE,REFMSG_CHANGE);
}
int IsEnabledInRender() { return !TestAFlag(A_MOD_DISABLED_INRENDER); }
CoreExport virtual Interval LocalValidity(TimeValue t);
virtual ChannelMask ChannelsUsed()=0;
virtual ChannelMask ChannelsChanged()=0;
// this is used to invalidate cache's in Edit Modifiers:
virtual void NotifyInputChanged(Interval changeInt, PartID partID, RefMessage message, ModContext *mc) {}
// This method indicates if the modifier changes the selection type channel or not.
// If a modifier wants to change dynamically if it changes the subobj sel type
// or not, it can overwrite this method.
// ChannelsChanged() however can not be dynamically implemented.
virtual bool ChangesSelType(){ return ChannelsChanged()&SUBSEL_TYPE_CHANNEL ? true : false;}
// These call ChannelsUsed/Changed() but also OR in GFX_DATA_CHANNEL as appropriate.
CoreExport ChannelMask TotalChannelsUsed();
CoreExport ChannelMask TotalChannelsChanged();
// This is the method that is called when the modifier is needed to
// apply its effect to the object. Note that the INode* is always NULL
// for object space modifiers.
virtual void ModifyObject(TimeValue t, ModContext &mc, ObjectState* os, INode *node)=0;
// this should return FALSE for things like edit modifiers
virtual int NeedUseSubselButton() { return 1; }
// Modifiers that place a dependency on topology should return TRUE
// for this method. An example would be a modifier that stores a selection
// set base on vertex indices.
virtual BOOL DependOnTopology(ModContext &mc) {return FALSE;}
// this can return:
// DEFORM_OBJ_CLASS_ID -- not really a class, but so what
// MAPPABLE_OBJ_CLASS_ID -- ditto
// TRIOBJ_CLASS_ID
// BEZIER_PATCH_OBJ_CLASS_ID
virtual Class_ID InputType()=0;
virtual void ForceNotify(Interval& i)
{NotifyDependents(i,ChannelsChanged(),REFMSG_CHANGE );}
virtual IOResult SaveLocalData(ISave *isave, LocalModData *ld) { return IO_OK; }
virtual IOResult LoadLocalData(ILoad *iload, LocalModData **pld) { return IO_OK; }
// These handle loading and saving the modifier name. Should be called
// by derived class BEFORE it loads or saves any chunks
CoreExport IOResult Save(ISave *isave);
CoreExport IOResult Load(ILoad *iload);
// This will call proc->proc once for each application of the modifier.
CoreExport void EnumModContexts(ModContextEnumProc *proc);
// This method will return the IDerivedObject and index of this modifier
// for a given modifier context.
CoreExport void GetIDerivedObject(ModContext *mc, IDerivedObject *&derObj, int &modIndex);
// In case the modifier changes the object type (basically the os->obj pointer in ModifyObject)
// *and* changes the ExtensionChannel, it has to overwrite this method and copy only the channels
// that it doesn't modify/added already to the new object.
CoreExport virtual void CopyAdditionalChannels(Object *fromObj, Object *toObj) { toObj->CopyAdditionalChannels(fromObj);}
// Animatable Overides...
CoreExport SvGraphNodeReference SvTraverseAnimGraph(IGraphObjectManager *gom, Animatable *owner, int id, DWORD flags);
CoreExport TSTR SvGetName(IGraphObjectManager *gom, IGraphNode *gNode, bool isBeingEdited);
CoreExport bool SvCanSetName(IGraphObjectManager *gom, IGraphNode *gNode);
CoreExport bool SvSetName(IGraphObjectManager *gom, IGraphNode *gNode, TSTR &name);
CoreExport bool SvHandleDoubleClick(IGraphObjectManager *gom, IGraphNode *gNode);
CoreExport COLORREF SvHighlightColor(IGraphObjectManager *gom, IGraphNode *gNode);
CoreExport bool SvIsSelected(IGraphObjectManager *gom, IGraphNode *gNode);
CoreExport MultiSelectCallback* SvGetMultiSelectCallback(IGraphObjectManager *gom, IGraphNode *gNode);
CoreExport bool SvCanSelect(IGraphObjectManager *gom, IGraphNode *gNode);
CoreExport bool SvCanInitiateLink(IGraphObjectManager *gom, IGraphNode *gNode);
CoreExport bool SvCanConcludeLink(IGraphObjectManager *gom, IGraphNode *gNode, IGraphNode *gNodeChild);
CoreExport bool SvLinkChild(IGraphObjectManager *gom, IGraphNode *gNodeThis, IGraphNode *gNodeChild);
CoreExport bool SvCanRemoveThis(IGraphObjectManager *gom, IGraphNode *gNode);
CoreExport bool SvRemoveThis(IGraphObjectManager *gom, IGraphNode *gNode);
private:
};
class OSModifier: public Modifier {
public:
SClass_ID SuperClassID() { return OSM_CLASS_ID; }
};
class WSModifier: public Modifier {
public:
SClass_ID SuperClassID() { return WSM_CLASS_ID; }
};
void CoreExport MakeHitRegion(HitRegion& hr, int type, int crossing, int epsi, IPoint2 *p);
class PolyLineProc {
public:
virtual int proc(Point3 *p, int n)=0;
virtual void SetLineColor(float r, float g, float b) {}
virtual void SetLineColor(Point3 c) {}
virtual void Marker(Point3 *p,MarkerType type) {}
};
class DrawLineProc:public PolyLineProc {
GraphicsWindow *gw;
public:
DrawLineProc() { gw = NULL; }
DrawLineProc(GraphicsWindow *g) { gw = g; }
int proc(Point3 *p, int n) { gw->polyline(n, p, NULL, NULL, 0, NULL); return 0; }
void SetLineColor(float r, float g, float b) {gw->setColor(LINE_COLOR,r,g,b);}
void SetLineColor(Point3 c) {gw->setColor(LINE_COLOR,c);}
void Marker(Point3 *p,MarkerType type) {gw->marker(p,type);}
};
class BoxLineProc:public PolyLineProc {
Box3 box;
Matrix3 *tm;
public:
BoxLineProc() { box.Init();}
BoxLineProc(Matrix3* m) { tm = m; box.Init(); }
Box3& Box() { return box; }
CoreExport int proc(Point3 *p, int n);
CoreExport void Marker(Point3 *p,MarkerType type);
};
// Apply the PolyLineProc to each edge (represented by an array of Point3's) of the box
// after passing it through the Deformer def.
void CoreExport DoModifiedBox(Box3& box, Deformer &def, PolyLineProc& lp);
void CoreExport DoModifiedLimit(Box3& box, float z, int axis, Deformer &def, PolyLineProc& lp);
void CoreExport DrawCenterMark(PolyLineProc& lp, Box3& box );
// Some functions to draw mapping icons
void CoreExport DoSphericalMapIcon(BOOL sel,float radius, PolyLineProc& lp);
void CoreExport DoCylindricalMapIcon(BOOL sel,float radius, float height, PolyLineProc& lp);
void CoreExport DoPlanarMapIcon(BOOL sel,float width, float length, PolyLineProc& lp);
//---------------------------------------------------------------------
// Data structures for keeping log of hits during sub-object hit-testing.
//---------------------------------------------------------------------
class HitLog;
class HitRecord {
friend class HitLog;
HitRecord *next;
public:
INode *nodeRef;
ModContext *modContext;
DWORD distance;
ulong hitInfo;
HitData *hitData;
HitRecord() { next = NULL; modContext = NULL; distance = 0; hitInfo = 0; hitData = NULL;}
HitRecord(INode *nr, ModContext *mc, DWORD d, ulong inf, HitData *hitdat) {
next = NULL;
nodeRef = nr; modContext = mc; distance = d; hitInfo = inf; hitData = hitdat;
}
HitRecord(HitRecord *n,INode *nr, ModContext *mc, DWORD d, ulong inf, HitData *hitdat) {
next = n;
nodeRef = nr; modContext = mc; distance = d; hitInfo = inf; hitData = hitdat;
}
HitRecord * Next() { return next; }
~HitRecord() { if (hitData) { delete hitData; hitData = NULL; } }
};
class HitLog {
HitRecord *first;
int hitIndex;
bool hitIndexReady; // CAL-07/10/03: hitIndex is ready to be increased.
public:
HitLog() { first = NULL; hitIndex = 0; hitIndexReady = false; }
~HitLog() { Clear(); }
CoreExport void Clear();
CoreExport void ClearHitIndex(bool ready = false) { hitIndex = 0; hitIndexReady = ready; }
CoreExport void IncrHitIndex() { if (hitIndexReady) hitIndex++; else hitIndexReady = true; }
HitRecord* First() { return first; }
CoreExport HitRecord* ClosestHit();
CoreExport void LogHit(INode *nr, ModContext *mc, DWORD dist, ulong info, HitData *hitdat = NULL);
};
// Creates a new empty derived object, sets it to point at the given
// object and returns a pointer to the derived object.
CoreExport Object *MakeObjectDerivedObject(Object *obj);
// Category strings for space warp objects:
#define SPACEWARP_CAT_GEOMDEF 1
#define SPACEWARP_CAT_MODBASED 2
#define SPACEWARP_CAT_PARTICLE 3
CoreExport TCHAR *GetSpaceWarpCatString(int id);
// ObjectConverter - allows users to register methods to (for example)
// allow Max to convert TriObjects directly into their plug-in object type.
class ObjectConverter : public InterfaceServer {
public:
virtual Class_ID ConvertsFrom ()=0;
virtual Class_ID ConvertsTo ()=0;
// NOTE: There's a serious problem in that this method does not accept a TimeValue.
// See below for details.
virtual Object *Convert (Object *from)=0;
virtual void DeleteThis () { }
};
// There was a problem in the above ObjectConverter class in that its Convert
// method doesn't accept a time parameter. It's too late to change that, so we've
// implemented the following interface to supply the correct method. Users'
// ObjectConverters should subclass off of both ObjectConverter and
// ITimeBasedConverter. They should implement the GetInterface method as
// follows:
//BaseInterface *MyConverter::GetInterface (Interface_ID id) {
//if (id == INTERFACE_TIME_BASED_CONVERTER) return (ITimeBasedConverter *)this;
//return ObjectConverter::GetInterface (id);
//}
// They should then implement ConvertWithTime properly, and use Convert only
// to call ConvertWithTime with a time of GetCOREInterface()->GetTime().
// Convert should not be called (and won't be called by the system if this
// interface is properly set up).
#define INTERFACE_TIME_BASED_CONVERTER Interface_ID(0x1e064bad,0x716643db)
class ITimeBasedConverter : public BaseInterface {
public:
Interface_ID GetID () { return INTERFACE_TIME_BASED_CONVERTER; }
// This is the method that should be used to do the right conversion:
virtual Object *ConvertWithTime (TimeValue t, Object *from)=0;
};
CoreExport bool RegisterObjectConverter (ObjectConverter *conv);
CoreExport int CanConvertTriObject (Class_ID to);
CoreExport int CanConvertPatchObject (Class_ID to);
CoreExport int CanConvertSplineShape (Class_ID to);
CoreExport void RegisterStaticEditTri (Object *triob);
CoreExport void RegisterCollapseType (Class_ID cid, TSTR name, bool canSelfConvert=false);
// Developers have to return a class derived from this class with implementations for
// all memberfunctions when implementing subobjects for obejcts and modifiers (see GetSubObjType())
class ISubObjType : public InterfaceServer
{
public:
virtual MaxIcon *GetIcon()=0;
virtual TCHAR *GetName()=0;
};
// Generic implementation for subobject types. This SubObjectType will either use the
// SubObjectIcons_16i.bmp and SubObjectIcons_16a.bmp bitmaps in the UI directory
// (for the GenSubObjType(int idx) constructor), or any other bmp file that is specified
// in the GenSubObjType(TCHAR *nm, TCHAR* pFilePrefix, int idx) constructor. The
// bitmap files have to reside in the UI directory.
class GenSubObjType : public ISubObjType {
TSTR name;
MaxIcon *mIcon;
int mIdx;
TSTR mFilePrefix;
public:
GenSubObjType(TCHAR *nm, TCHAR* pFilePrefix, int idx) : name(nm), mIcon(NULL), mIdx(idx), mFilePrefix(pFilePrefix) {}
GenSubObjType(int idx) : mIcon(NULL), mIdx(idx), mFilePrefix(_T("SubObjectIcons")) {}
CoreExport ~GenSubObjType();
void SetName(TCHAR *nm){name = nm;}
TCHAR *GetName() { return name;}
CoreExport MaxIcon *GetIcon();
};
#endif //_OBJECT_