#ifndef __IPAINTERINTERFACE__H #define __IPAINTERINTERFACE__H /******************************************************************************** IPainterInterface contains all the interfaces to let a plugin interact with Maxs Paint system Basically the system consists of 2 components the IPainterInterface and IPainterCanvasInterface For a plugin to use the paint system it must sub class of IPainterCanvasInterface_V5 or greater and implement the virtual methods and be a sub class of ReferenceTarget. A canvas is what the painterInterface paints on. Basically IPainterCanvasInterface_V5 consists of functions to identify the canvas version and functions that are called a as the system paints, basically a start stroke, stroke and endstroke. The IPainterInterface is what does all the hit testing against the mesh using a quad tree. Basically it tells the canvas what the stroke looks like. In addition the canvas can use it do additional hit testing not associated with a stroke. In its simplest from all that needs to be done is 1. Subclass your plugin from IPainterCanvasInterface_V5 and ReferenceTarget 2. Fill out these virtually methods StartStroke() - called when a stroke is started PaintStroke()/PaintStroke(<..>) - called as a stroke is going on EndStroke() - called when the stroke ends and accepted. EndStroke(<...>) - called when the system is set to non interactive mode. CancelStroke() - called if a stroke is canceled. SystemEndPaintSession() - is called when the painter wants to end a paint session for some reason See the header for me description of the parameters You also need to add the painter interface to the GetInterface method from ReferenceTarget. Something along the lines below. This lets the painter set what interfaces the canvas supports. void* PainterTester::GetInterface(ULONG id) { switch(id) { case PAINTERCANVASINTERFACE_V5 : return (IPainterCanvasInterface_V5 *) this; break; default: return ReferenceTarget::GetInterface(id); break; } } 3. In addition to implementing these methods, The plugin needs to hook up to the painterInterface. Using these functions. The pointer to the painter can be gotten by using the CreateInstance(REF_TARGET_CLASS_ID,PAINTERINTERFACE_CLASS_ID). Once that pointer is gotten you need to grab a specific version of the painterInterface using GetPaintInterface. See sample below ReferenceTarget *painterRef = (ReferenceTarge *) GetCOREInterface()->CreateInstance(REF_TARGET_CLASS_ID,PAINTERINTERFACE_CLASS_ID); //set it to the correct verion if (painterRef) IPainterInterface_V5 *painter = (IPainterInterface_V5 *) painterRef->GetInterface(PAINTERINTERFACE_V5); Once you have a valid pointer you need to hook your self up to the Painter using the InitializeCallback method. This is should be done just before you want to start a paint seesion. All you are doing is passing a pointer of yourself to the painter system so it knows where to send the messages. Note yourself to IPainterCanvasInterface since the Painter will interogate you to find out which version of the canvas you are. painter->InitializeCallback((ReferenceTarget *) this); Once you have called InitializedCallback and are ready to start a paint session you need load up which Nodes you want to paint on. This is done with InitializeNodes(int flags, Tab &nodeList). painter->InitializeNodes(0, nodes); Then StartPaintSession() is called. Once this is called everytime the the users drag paints across the nodes the Canvas's StartStroke/PaintStroke/EndStroke will get called. painter->StartPaintSession(); If the canvas changes the topology or geometry of the painted nodes UpdateMeshes() needs to be called so the quad tree gets updated. painter->UpdateMeshes(BOOL updatePoitnCache); Once the canvas is done with the painter it needs to call EndPaintSession() so that all the data can be freed and it can be unhooked. Otherwise the StartStroke/PaintStroke/EndStroke will still be called. painter->EndPaintSession(); You can also bring up the Painters Option dialog using the BringUpOptions(). painter->BringUpOptions() ; In addition there will be some helper functions for gathering points within a stroke and their weigths; and tools for intersecting rays against the quad tree. See the header for more descriptions. See the PaintTester project for a simple implementation of a canvas and interaction with the painter. *********************************************************************************/ #include "iFnPub.h" #include "icurvctl.h" #define PAINTERINTERFACE_V5 0x78ffe181 #define PAINTERINTERFACE_V7 0x78ffe182 #define PAINTERCANVASINTERFACE_V5 0x29ff7ac9 #define PAINTERCANVASINTERFACE_V5_1 0x29ff7ad0 #define PAINTERCANVASINTERFACE_V7 0x1e962374 #define PAINTERINTERFACE_CLASS_ID Class_ID(0x2f2ef7e9, 0x78ffe181) #define PAINTERINTERFACEV5_INTERFACE Interface_ID(0x53b4520c, 0x29ff7ac9) //These are defines used to when mirroring is enabled with point gathering //a point can be hit by the original brush, the mirror brushed, or both #define NO_MIRRROR 0 #define MIRRRORED 1 #define MIRRROR_SHARED 2 //These are IDs for the colors of the brush for use with the color manager #define RINGCOLOR 0x445408e0 #define NORMALCOLOR 0x445408e1 #define RINGPRESSEDCOLOR 0x445408e2 #define NORMALPRESSEDCOLOR 0x445408e3 #define TRACECOLOR 0x445408e4 #define GIZMOCOLOR 0x445408e5 //These are IDs to define what the pressure effects on a stroke #define PRESSURE_AFFECTS_NONE 0 #define PRESSURE_AFFECTS_STR 1 #define PRESSURE_AFFECTS_SIZE 2 #define PRESSURE_AFFECTS_BOTH 3 class IPainterInterface_V5 { public: //these are the esswential tools to get you started //they cover the basics to get you started //the canvas passes a pointer of itself to the painter, so the painter //knows where to send the stroke messages // ReferenceTarget *canvas - is the pointer to the canvas virtual BOOL InitializeCallback(ReferenceTarget *canvas) = 0;//tested //this loads of the nodes that you want to paint on, anytime you want //to add delete a node this must be called // int flags - not yet implemented does nothing but there to allow // flags per node for special conditions // Tab &nodeList - a table of nodes that you want to paint on virtual BOOL InitializeNodes(int flags, Tab &nodeList) = 0;//tested //This forces the quadtree to rebuilt. Any time you change a geometry or togopology //of a node you passed to the InitializedNodes methode this must be called. //Ideally I could listen to the notifyremessage changed and rebuild on that //but the since rebuilding the quad tree is inetensive, I leave it up to the //canvas as to when to rebuild so we can better control the amount of stack reevals // BOOL updatePointGather - determines whether the pointGather data gets updated also // normally if your mesh does not change shape or topo you dont // need to update the pointgather. For instance ifyou rotate a view // your quad tree needs to get updated but not the point list virtual BOOL UpdateMeshes(BOOL updatePointGather) = 0; //This is called when the a canvas wants to start a paint session. virtual BOOL StartPaintSession() = 0;//tested //This is called when the a canvas wants to end a paint session. virtual BOOL EndPaintSession() = 0;//tested //this return whether the user is in the paint mode, so a plugin can //determine how to paint the UI paint button virtual BOOL InPaintMode()=0;//tested //this brings up the Painter Options dialog that lets the users sets various //setting of the painter system virtual BOOL BringUpOptions() = 0;//tested //This lets you access the time stamp of each sample of a stroke. This lets you look at //the acceleration of the mouse as it moves if say you wanted to paint a stroke and use //it for an animation path. virtual int *RetrieveTimeList(int &ct) = 0; //These functions are additional tools to further hit testing and point gathering //to help with finding points on a mesh that are within the stroke and theoir weights //this function lets you hit test against the quad tree given a mouse coord //it returns TRUE if that point insterects the quad tree // IPoint2 mousePos - the position in screen space that you want to hit test agains // Point3 &worldPoint, Point3 &worldNormal - the world hit point normal and position // Point3 &localPoint, Point3 &localNormal - the local hit point normal and position // Point3 &bary - the barycentry coord of the face that was hit // int &index - the index of the face that was hit // INode *node - the node that was hit // BOOL &mirrorOn - whether mirroring was on or off // Point3 &worldMirrorPoint, Point3 &worldMirrorNormal - the world hit point normal and position after it was mirrored // Point3 &localMirrorPoint, Point3 &localMirrorNormal - the local hit point normal and position after it was mirrored virtual BOOL TestHit( IPoint2 mousePos, Point3 &worldPoint, Point3 &worldNormal, Point3 &localPoint, Point3 &localNormal, Point3 &bary, int &index, INode *node, BOOL &mirrorOn, Point3 &worldMirrorPoint, Point3 &worldMirrorNormal, Point3 &localMirrorPoint, Point3 &localMirrorNormal ) = 0; //Retrieves a random hit point around the last hit point or a specified hit point within the brush //Useful if you want to do airbrush type effects or to just sample around the hit point //it returns FALSE if a hit point was not found // Point3 &worldPoint, Point3 &worldNormal - the world hit point normal and position // Point3 &localPoint, Point3 &localNormal - the local hit point normal and position // Point3 &bary - the barycentry coord of the face that was hit // int &index - the index of the face that was hit // float &strFromFalloff - the strength of the point based on the fall off of the brush // INode *node - the node that was hit // BOOL &mirrorOn - whether mirroring was on or off // Point3 &worldMirrorPoint, Point3 &worldMirrorNormal - the world hit point normal and position after it was mirrored // Point3 &localMirrorPoint, Point3 &localMirrorNormal - the local hit point normal and position after it was mirrored // tabIndex is what hit you want to sample around if 0 or less it will hit around the last hit test virtual BOOL RandomHit(Point3 &worldPoint, Point3 &worldNormal, Point3 &localPoint, Point3 &localNormal, Point3 &bary, int &index, float &strFromFalloff, INode *node, BOOL &mirrorOn, Point3 &worldMirrorPoint, Point3 &worldMirrorNormal, Point3 &localMirrorPoint, Point3 &localMirrorNormal, int tabIndex) = 0; //This will do random hit point along the stroke segment //It will return FALSE if it does not find a hit // Point3 &worldPoint, Point3 &worldNormal - the world hit point normal and position // Point3 &localPoint, Point3 &localNormal - the local hit point normal and position // Point3 &bary - the barycentry coord of the face that was hit // int &index - the index of the face that was hit // float &strFromFalloff - the strength of the point based on the fall off of the brush // INode *node - the node that was hit // BOOL &mirrorOn - whether mirroring was on or off // Point3 &worldMirrorPoint, Point3 &worldMirrorNormal - the world hit point normal and position after it was mirrored // Point3 &localMirrorPoint, Point3 &localMirrorNormal - the local hit point normal and position after it was mirrored // tabIndex is what segment you want to sample around if 0 or less it will hit around the last segment virtual BOOL RandomHitAlongStroke(Point3 &worldPoint, Point3 &worldNormal, Point3 &localPoint, Point3 &localNormal, Point3 &bary, int &index, float &strFromFalloff, INode *node, BOOL &mirrorOn, Point3 &worldMirrorPoint, Point3 &worldMirrorNormal, Point3 &localMirrorPoint, Point3 &localMirrorNormal, int tabIndex) = 0; //These next 2 methods are used if you want to do a custom stroke. Say for instance //you wanted to just stroke a straight line, by default the painter uses a path stroke. //so what you do on the PaintStroke method record the first and last mousePos, clear all the //stroke data and then Add your custom stroke to the system. //this clears out all the stroke data for the current stroke virtual BOOL ClearStroke()=0; //this adds a hit test to the current stroke // IPoint2 mousePos the point that want to test to add // BOOL rebuildPointGatherData this determines whether the poing gather data get rebuilt // this allows you to delay the building of the data if you are addding mulitple // points at once // BOOL updateViewport determines if the viewports get updated after this call virtual BOOL AddToStroke(IPoint2 mousePos, BOOL rebuildPointGatherData, BOOL updateViewport)=0; //These are direct to stroke data lists if you are doing your own point gather //Each stroke contains an arrays of data that are used to describe it such as //position, str, radius etc. //returns the number of sample points in the current stroke virtual int GetStrokeCount() = 0; //this returns a pointer to an array of floats where each entry is the str of a point sample virtual float *GetStrokeStr() = 0; //this returns a pointer to an array of floats where each entry is the radius of a point sample virtual float *GetStrokeRadius() = 0; //this returns a pointer to an array of point3s where each entry is the world space hit point of the sample virtual Point3 *GetStrokePointWorld() = 0; //this returns a pointer to an array of point3s where each entry is the world space normal of the sample virtual Point3 *GetStrokeNormalWorld() = 0; //this returns a pointer to an array of point3s where each entry is the world space hit point of the sample after it has been mirrored virtual Point3 *GetStrokePointWorldMirror() = 0; //this returns a pointer to an array of point3s where each entry is the world space normal of the sample after it has been mirrored virtual Point3 *GetStrokeNormalWorldMirror() = 0; //this returns a pointer to an array of floats where each entry is the pressure of a point sample either from a pressure sensitive tablet //or from a predefined presssure graph virtual float *GetStrokePressure() = 0; //this returns a pointer to an array of point3s where each entry is the local space hit point of the sample virtual Point3 *GetStrokePointLocal() = 0; //this returns a pointer to an array of point3s where each entry is the local space normal of the sample virtual Point3 *GetStrokeNormalLocal() = 0; //this returns a pointer to an array of point3s where each entry is the local space hit point of the sample after it has been mirrored virtual Point3 *GetStrokePointLocalMirror() = 0; //this returns a pointer to an array of point3s where each entry is the world space normal of the sample after it has been mirrored virtual Point3 *GetStrokeNormalLocalMirror() = 0; //this returns a pointer to an array of Ipoint2s where each entry is the mouse pos in screen space for the sample virtual IPoint2 *GetStrokeMousePos() = 0; //this returns a pointer to an array of s where each entry is whether the sample hit the mesh or not //the system allows the user to paint off the mesh, where all hitpoint are projected onto a plane //based on the last hit point and norml, virtual BOOL *GetStrokeHitList() = 0; //this returns a pointer to an array of point3s where each entry is the barycentri coords of the sample virtual Point3 *GetStrokeBary() = 0; //this returns a pointer to an array of ints where each entry is the index of the face of the sample virtual int *GetStrokeIndex() = 0; //this returns a pointer to an array of bools where each entry is the state of the shift of the sample virtual BOOL *GetStrokeShift() = 0; //this returns a pointer to an array of bools where each entry is the state of the ctrl of the sample virtual BOOL *GetStrokeCtrl() = 0; //this returns a pointer to an array of bools where each entry is the state of the alt of the sample virtual BOOL *GetStrokeAlt() = 0; //this returns a pointer to an array of INode where each entry is the INode of the sample virtual INode **GetStrokeNode() = 0; //this returns a pointer to an array of ints where each entry is the time stamp of the sample virtual int *GetStrokeTime() = 0; //given a point in world space it returns the str of that point based on the current stroke virtual float GetStrFromPoint(Point3 point) = 0; //These functions let you interogate and set the state of the options dialog //this is used to ask the system if a stroke str or size changes as it is painted //the user can set predetermined shapes graphs and attach them to the str or size //of brush based on the position of the in the curve it is. If you are in an interactive //mode this data will always be changing so you can use this to get the current str/sizes //of th hit points. If you are in a non interactive mode you do not need to call this //since all the correct sizes/str are sent to the end stroke arrays. If the user has not //specified any predetermined graphs the arrays will be NULL // int &ct - count of the arrays // float *radius - array of radii size //these return array of floats one entry for each point on the stroke virtual float *GetPredefineStrStrokeData(int &ct)=0; virtual float *GetPredefineSizeStrokeData(int &ct)=0; //put in access to all the dialog properties //This will build a vertex normal list that you can access through RetrievePointGatherNormals //This is by default is off to save memory. Also if you use a custom point list through //LoadCustomPointGather no normals will be built since there is no topo data to build them from virtual BOOL GetBuildNormalData() = 0; virtual void SetBuildNormalData(BOOL enable) = 0; //These functions deal with the point gather. The painter can automatically determines the weights //of points by using the PointGather //These let turns on/off the point gather and get its stae. If this is enabled, //the points of the mesh will be used as your points virtual BOOL GetEnablePointGather() = 0; virtual void SetEnablePointGather(BOOL enable) = 0;//tested //This lets you set up a custom list of points to weight to override the currentlist //for instance if you have a non mesh you will need to do this since by default the //point gather uses the mesh points to weight // int ct the number of points that you want to add // Point3 *points the points you want to add in world space? // INode *node which node you want to assign them to virtual BOOL LoadCustomPointGather(int ct, Point3 *points, INode *node) = 0;//tested //Once a stroke has started you can retrieve data about you point list such //as weigths, str etc. //This retrieves the weight of the points based on the current stroke // INode *node the node that you want to inspect // int &ct the number of points in the array virtual float *RetrievePointGatherWeights(INode *node, int &ct) = 0; //This retrieves the strength of the points based on the current stroke // INode *node the node that you want to inspect // int &ct the number of points in the array virtual float *RetrievePointGatherStr(INode *node, int &ct) = 0;//tested //This retrieves the whether the point was affected by a mirror stroke // INode *node the node that you want to inspect // int &ct the number of points in the array virtual BOOL *RetrievePointGatherIsMirror(INode *node, int &ct) = 0;//tested //This retrieves the the array of the points // INode *node the node that you want to inspect // int &ct the number of points in the array virtual Point3 *RetrievePointGatherPoints(INode *node, int &ct) = 0;//tested //Normals are in local space and only valid if you do not use a CustomPointGather //This retrieves the the array of the normals // INode *node the node that you want to inspect // int &ct the number of points in the array virtual Point3 *RetrievePointGatherNormals(INode *node, int &ct) = 0; //This retrieves the the array of the U vals, this is how far along the stroke that point is // INode *node the node that you want to inspect // int &ct the number of points in the array virtual float *RetrievePointGatherU(INode *node, int &ct) = 0; //functions to get the mirror plane data //NOTE all mirror function work in world space //returns if the mirror plane is on or off virtual BOOL GetMirrorEnable() = 0 ;//tested //lets you set whether the mirror plane is on/off virtual void SetMirrorEnable(BOOL enable) = 0; //returns the center of the mirror plane in world space coords //the mirror plane is always aligned to the world axis virtual Point3 GetMirrorPlaneCenter() = 0;//tested //returns which mirror axis is active // 0 = x axis // 1 = y axis // 2 = z axis virtual int GetMirrorAxis() = 0;//tested //lets you set the mirror axis where // 0 = x axis // 1 = y axis // 2 = z axis virtual void SetMirrorAxis(int dir) = 0; virtual float GetMirrorOffset() = 0;//tested virtual void SetMirrorOffset(float offset) = 0;//tested //These 2 function let you get and set the quad tree depth //The deeper the quad tree the more memory you consume, but the //more memory you consume (the memory consumption is exponential so becarefule) virtual int GetTreeDepth() = 0;//tested virtual void SetTreeDepth(int depth) = 0;//tested //These 2 function let you get and set the Update on Mouse Up option //When this is enabled you will not get PaintStroke calls. //Instead you will get all the points at the end through the endStoke function virtual BOOL GetUpdateOnMouseUp() = 0; virtual void SetUpdateOnMouseUp(BOOL update) = 0; //These 2 function let you get and set the lag rate //When this is enabled you get PaintStroke delayed by the lag rate calls. //every x(lagrate) stroke points you willget the strokes. virtual int GetLagRate() = 0; virtual void SetLagRate(int lagRate) = 0; //These functions control how the brush behaves //These 4 functions let you set the min/max strength for a brush. //If there is no pressure sensitive device attached only the max str is used virtual float GetMinStr() = 0;//tested virtual void SetMinStr(float str) = 0;//tested virtual float GetMaxStr() = 0;//tested virtual void SetMaxStr(float str) = 0;//tested //These 4 functions let you set the min/max radius for a brush. //If there is no pressure sensitive device attached only the max radius is used virtual float GetMinSize() = 0;//tested virtual void SetMinSize(float str) = 0;//tested virtual float GetMaxSize() = 0;//tested virtual void SetMaxSize(float str) = 0;//tested //These 2 functions get/set the aditive mode //When additive mode is off the weight is absolutely set based on the current stroke hit. //Previous stroke data is over written. In Additive mode the strength is added to current //strength and is not capped. virtual BOOL GetAdditiveMode()=0;//tested virtual void SetAdditiveMode(BOOL enable)=0;//tested //This returns the brush falloff curve if you want to handle the doing the brush //falloff yourself virtual ICurve *GetFalloffGraph()=0; //These functions allow you to control the display of a stroke //Colors are stored in the color manager. See the color ID defines at the top //This lets you get/set whether the ring is drawn around the hit point virtual BOOL GetDrawRing()=0;//tested virtual void SetDrawRing(BOOL draw)=0;//tested //This lets you get/set whether the normal vector is drawn at the hit point virtual BOOL GetDrawNormal()=0;//tested virtual void SetDrawNormal(BOOL draw)=0;//tested //This lets you get/set whether the a line is left behind a stroke as it is drawn virtual BOOL GetDrawTrace()=0;//tested virtual void SetDrawTrace(BOOL draw)=0;//tested //These functions deal with the pressure sensitive devices and mimicing pressure sensitivity //These 2 functions let you get/set whether pressure sensistivity is turned on //when Pressure is enabled it can affect Str, Radius, Both Str and Radius or Nothing //You would nothing fr instance if you wanted to do a custom affect for pressure. virtual BOOL GetPressureEnable()=0;//tested virtual void SetPressureEnable(BOOL enable)=0;//tested //These 2 functions Get/Set what the pressure of a brush affects //You can affact Str. Radius, Str and Radius or None //See the defines at top virtual BOOL GetPressureAffects()=0;//tested virtual void SetPressureAffects(int affect)=0;//tested //These function let you get/set whether a predefined str is enabled for a stroke. //A predefined str stroke lets the user graph the str of stroke over the length of stroke virtual BOOL GetPredefinedStrEnable()=0;//tested virtual void SetPredefinedStrEnable(BOOL enable)=0;//tested //These function let you get/set whether a predefined radius is enabled for a stroke. //A predefined radius stroke lets the user graph the radius of stroke over the length of stroke virtual BOOL GetPredefinedSizeEnable()=0;//tested virtual void SetPredefinedSizeEnable(BOOL enable)=0;//tested virtual ICurve *GetPredefineSizeStrokeGraph()=0; virtual ICurve *GetPredefineStrStrokeGraph()=0; virtual float GetNormalScale() = 0; virtual void SetNormalScale(float scale) = 0; virtual BOOL GetMarkerEnable() = 0; virtual void SetMarkerEnable(BOOL on) = 0; virtual float GetMarker() = 0; virtual void SetMarker(float pos) = 0; // 0 = creates a plance based on your last hit point and normal // 1 = a zdepth into the screen // 2 = a point in world space aligned to current view virtual int GetOffMeshHitType() = 0; virtual void SetOffMeshHitType(int type) = 0; virtual float GetOffMeshHitZDepth() = 0; virtual void SetOffMeshHitZDepth(float depth) = 0; virtual Point3 GetOffMeshHitPos() = 0; virtual void SetOffMeshHitPos(Point3 pos) = 0; }; // This is a class that lets you go from mesh space to patch space // basically the painter only paints on meshes // you can create an array of this type so you can look up a hit face // and then get a patch index from it and the UVW of the hit space on the patch class FaceDataFromPatch { public: int owningPatch; // the patch that own this face Point2 st[3]; // the UVW space of the corners of the patch }; class IPainterRightClickHandler { public: virtual void RightClick ()=0; }; class IPainterInterface_V7 : public IPainterInterface_V5 { public: //this loads of the nodes that you want to paint on, anytime you want //to add delete a node this must be called. This use the object state passed ot it //instead of the one gotten from the node to get the hit mesh. NOTE I do not hang onto //any of the data in the ObjectState. I just get the a copy of the mesh from it. // int flags - not yet implemented does nothing but there to allow // flags per node for special conditions // Tab &nodeList - a table of nodes that you want to paint on // Tab objList - a table of objects states one per node to use as your hit node virtual BOOL InitializeNodesByObjState(int flags, Tab &nodeList, Tab &objList) = 0;//tested //This forces the quadtree to rebuilt. Any time you change a geometry or togopology //of a node you passed to the InitializedNodes methode this must be called. //Ideally I could listen to the notifyremessage changed and rebuild on that //but the since rebuilding the quad tree is inetensive, I leave it up to the //canvas as to when to rebuild so we can better control the amount of stack reevals //NOTE I do not hang onto //any of the data in the ObjectState. I just get the a copy of the mesh from it. // BOOL updatePointGather - determines whether the pointGather data gets updated also // normally if your mesh does not change shape or topo you dont // need to update the pointgather. For instance ifyou rotate a view // your quad tree needs to get updated but not the point list // Tab objList - a table of objects states one per node to use as your hit node virtual BOOL UpdateMeshesByObjState(BOOL updatePointGather, Tab &objList) = 0; //This lets you take a patch and get a list or tri mesh faces wher each tri has an owning //patch index and the UVW space of that face. This lets you get patch UVW space virtual void GetPatchFaceData(PatchMesh &patch, Tab &faceData) = 0; // This overload of the method used to start a paint session allows you to submit a class // which will handle right-click events in the paint mouse proc. // This allows you to end the paint proc however you need to. // If rightClicker is NULL, or if the no-argument version of StartPaintSession is used, // nothing will happen on right-click. virtual BOOL StartPaintSession (IPainterRightClickHandler *rightClicker) = 0; // I have to add this one over again, otherwise it doesn't show up in the V7 interface: //This is called when the a canvas wants to start a paint session. virtual BOOL StartPaintSession() = 0;//tested //this set the str limit min/max for while dragging to chnage the str virtual float GetStrDragLimitMin() = 0; virtual void SetStrDragLimitMin(float l) = 0; virtual float GetStrDragLimitMax() = 0; virtual void SetStrDragLimitMax(float l) = 0; }; //This is the Max5 version of a PainterCanvas. Any plugin that wants to be able to be painted //on must sub class from this class or a later version of it. //Basically this calls contains all the methods that deal with a paint stroke. class IPainterCanvasInterface_V5 { public: // This is called when the user tart a pen stroke virtual BOOL StartStroke() = 0; //This is called as the user strokes across the mesh or screen with the mouse down //This only gets called if the interactive mode is off (the user has turned off Update on Mouse Up) // BOOL hit - if this is a hit or not, since the user can paint off a mesh // IPoint2 mousePos - this is mouse coords of the current hit in view space // Point3 worldPoint - this is the hit point on the painted mesh in world space // Point3 worldNormal - this is the normal of the hit point on the painted mesh in world space // Point3 localPoint - this is the hit point on the painted mesh in local space of the mesh that was hit // Point3 localNormal - this is the normal of the hit point on the painted mesh in local space of the mesh that was hit // Point3 bary - this the barcentric coords of the hit point based on the face that was hit // this may or may not be valid depending on the state of the stack. For instance // if a paint modifier was below a MeshSmooth, the barycentric coords would be based on // the MeshSmooth'ed mesh and not the mesh at the point of the paint modifier // int index - the index of the face that was hit. See the warning in Point3 bary above. // BOOL shift, ctrl, alt - the state of the shift, alt, and ctrl keys when the point was hit // float radius - of the radius of the brush when the point was hit, this is after all modifiers // have been applied like pressure or predefined radius etc // float str - of the strength of the brush when the point was hit, this is after all modifiers // have been applied like pressure or predefined radius etc // float pressure - if a pressure sensitive tablet is used this value will be the pressure of the stroke // ranging from 0 to 1 // INode *node - this node that got hit // BOOL mirrorOn - whther the user had mirror on for the stroke, you can ignore the next for params if false // Point3 worldMirrorPoint, Point3 worldMirrorNormal - the mirrored stroke pos // Point3 localMirrorPoint, Point3 localMirrorNormal - the mirros stroke normals virtual BOOL PaintStroke( BOOL hit, IPoint2 mousePos, Point3 worldPoint, Point3 worldNormal, Point3 localPoint, Point3 localNormal, Point3 bary, int index, BOOL shift, BOOL ctrl, BOOL alt, float radius, float str, float pressure, INode *node, BOOL mirrorOn, Point3 worldMirrorPoint, Point3 worldMirrorNormal, Point3 localMirrorPoint, Point3 localMirrorNormal ) = 0; // This is called as the user ends a strokes when the users has it set to always update virtual BOOL EndStroke() = 0; // This is called as the user ends a strokes when the users has it set to update on mouse up only // the canvas gets a list of all points, normals etc instead of one at a time // int ct - the number of elements in the following arrays // <...> see paintstroke() these are identical except they are arrays of values virtual BOOL EndStroke(int ct, BOOL *hit, IPoint2 *mousePos, Point3 *worldPoint, Point3 *worldNormal, Point3 *localPoint, Point3 *localNormal, Point3 *bary, int *index, BOOL *shift, BOOL *ctrl, BOOL *alt, float *radius, float *str, float *pressure, INode **node, BOOL mirrorOn, Point3 *worldMirrorPoint, Point3 *worldMirrorNormal, Point3 *localMirrorPoint, Point3 *localMirrorNormal ) = 0; // This is called as the user cancels a stroke by right clicking virtual BOOL CancelStroke() = 0; //This is called when the painter want to end a paint session for some reason. virtual BOOL SystemEndPaintSession() = 0; //this is called when the painter updates the view ports //this will let you do custom drawing if you need to virtual void PainterDisplay(TimeValue t, ViewExp *vpt, int flags) = 0; }; //This is the Max5.1 version of a PainterCanvas. //This interface changes how the command mode behaves //It adds the ability to send back to the canvas whether to start or end the paint mode //This bacially replaces the SystemEndPaintSession and also class IPainterCanvasInterface_V5_1 { public: //the painter interface will call these when it wants to start the painter or end it //an example of this is when the user scrubs the time slider whne in a paint session //the system will turn off the paint mode while scrubbing so you will get a CanvasEndPaint //then when the user stops srcubing it will try to turn it back on using CanvasStartPaint //so if you use this interface after you call StartPaintSession() you will imediately get //a CanvasStartPaint callback where all your setup code and UI code shoudl be handled virtual void CanvasStartPaint()=0; virtual void CanvasEndPaint()=0; }; class IPainterCanvasInterface_V7 { public: virtual void OnPaintBrushChanged() = 0; }; #endif