///////////////////////////////////////////////////////////// // CINEMA 4D SDK // ///////////////////////////////////////////////////////////// // (c) MAXON Computer GmbH, all rights reserved // ///////////////////////////////////////////////////////////// #ifndef __C4D_SNAPDATA_H_ #define __C4D_SNAPDATA_H_ #include "ocamera.h" #include "c4d_basedata.h" #include "dmodeling.h" class String; class BaseList2D; class BaseDocument; class BaseDraw; class ViewportSelect; class AtomArray; class BaseThread; class BaseDrawHelp; class BaseBitmap; class BaseContainer; class EditorWindow; class BaseObject; #define ID_SNAPCORE_LIB 440000112 #define PLUGINFLAG_SNAP_INFERRED_POINT (1 << 27) /// Inferred points can be generated by the results of this snap mode (used in registration) #define PLUGINFLAG_SNAP_INFERRED_AXIS (1 << 26) /// Inferred axis can be generated by the results of this snap mode (used in registration) #define PLUGINFLAG_SNAP_MIDPOINT (1 << 25) /// This snap mode is used by the midpoint snap, use the parent id to set which snap it belongs to //---------------------------------------------------------------------------------------- /// Snap Priority /// A higher priority snap will take precedence over a lower priority one when both are within snap range //---------------------------------------------------------------------------------------- enum SNAPPRIORITY { SNAPPRIORITY_0 = 0, /// The lowest priority SNAPPRIORITY_PLANE = 1000, /// Planar snapping e.g. to the workplane or a polygon surface SNAPPRIORITY_GUIDE = 2000, /// Guide snapping lower then edge to allow correct drawing for dynamic guides SNAPPRIORITY_EDGE = 3000, /// Edge snapping is a slightly higher priority and will override planar snapping SNAPPRIORITY_POINT = 4000 /// Point snapping is the highest (default) snapping priority }; // > and < needed so that needs to be left out ENUM_END_LIST(SNAPPRIORITY); //---------------------------------------------------------------------------------------- /// Snap flags, sent during the snap process itself to limit snapping //---------------------------------------------------------------------------------------- enum SNAPFLAGS { SNAPFLAGS_0 = 0, /// No flags SNAPFLAGS_IGNORE_SELECTED = (1 << 0), /// Don't snap to the selected objects or components SNAPFLAGS_IGNORE_AXIS = (1 << 1), /// Don't snap to the active axis SNAPFLAGS_POINTSONLY = (1 << 2), /// Ignore modes with lower priority than points SNAPFLAGS_SURFACEONLY = (1 << 3) /// Ignore modes with higher priority than planes } ENUM_END_FLAGS(SNAPFLAGS); //---------------------------------------------------------------------------------------- /// Inferred guide types. //---------------------------------------------------------------------------------------- enum INFERREDGUIDETYPE { INFERRED_GUIDE_POINT = 0, /// An inferred point or "axis", this will create guides along all perpendicular lines to the point in x, y and z INFERRED_GUIDE_LINE = 1, /// Inferred guide line, this will act just like a normal guide line, e.g. along an edge INFERRED_GUIDE_PLANE = 2 /// Inferred plane, this will act just like a normal guide plane } ENUM_END_LIST(INFERREDGUIDETYPE); //---------------------------------------------------------------------------------------- /// Structure for holding and returning information about the result of a snap /// and the point that's been snapped to //---------------------------------------------------------------------------------------- struct SnapPoint { public: SnapPoint() : target(nullptr), component(NOTOK) { } ~SnapPoint() { } Matrix mat; /// The result position of the snap BaseList2D* target; /// The target object being snapped to Int32 component; /// The component ID being snapped to (e.g. polygon, edge, point, line point) }; //---------------------------------------------------------------------------------------- /// The final result that the user gets when calling Snap::Snap or Snap::Intesect /// user owns the struct //---------------------------------------------------------------------------------------- struct SnapResult : public SnapPoint { public: SnapResult() : SnapPoint(), snapmode(NOTOK), initial_snap(Vector(0.0)) { } ~SnapResult() { } Int32 snapmode; /// The snap mode used Vector initial_snap; /// The snap porition before 2d processing Vector delta; /// The delta between new and old point positions }; //---------------------------------------------------------------------------------------- /// Structure containing relevant context information for the snap system //---------------------------------------------------------------------------------------- struct SnapStruct { public: SnapStruct() : doc(nullptr), bd(nullptr), snap_radius(10.0), excluded_objects(nullptr), object_list(nullptr), bt(nullptr), flags(SNAPFLAGS_0), projection(Pperspective) { } ~SnapStruct() { } BaseDocument* doc; /// The current document BaseDraw* bd; /// The active BaseDraw that snapping will be taking place in Float snap_radius; /// The radius to snap within AtomArray* excluded_objects; /// A list of objects to exclude AtomArray* object_list; /// A list of objects in view BaseThread* bt; /// The current BaseThread SNAPFLAGS flags; /// Flags sent by user calling snap function Int32 projection; /// cached bd->GetProjection() but faster }; //---------------------------------------------------------------------------------------- /// The base virtual class for Snap mode plugins /// For example Polygon Snap, Edge Snap, Spline Snap, Vertex Snap and so on //---------------------------------------------------------------------------------------- class SnapData : public BaseData { public: //---------------------------------------------------------------------------------------- /// Initialize the snap plugin here. /// @return True for success of initializing the plugin. //---------------------------------------------------------------------------------------- virtual Bool Init(void) { return true; } //---------------------------------------------------------------------------------------- /// Free the snap plugin instance here virtual void Free(void) { } //---------------------------------------------------------------------------------------- /// Prepare for snapping to begin. /// @param[in] ss The passed Snap context structure. /// @return true on Success of initializing all snap structures needed. //---------------------------------------------------------------------------------------- virtual Bool InitSnap(const SnapStruct& ss) { return true; } //---------------------------------------------------------------------------------------- /// 3D Snap detection routine. /// @param[in] p The position being snapped to in world coordinates. /// @param[in] ss The passed Snap context structure. /// @param[out] result Contains data about the resulting snap point if one is generated. /// @return True if a snap occurred, false if not. //---------------------------------------------------------------------------------------- virtual Bool Snap(const Vector& p, const SnapStruct& ss, SnapPoint& result) { return false; } //---------------------------------------------------------------------------------------- /// Guide intersection routine. /// @param[in] p The guide normal in world coordinates. /// @param[in] n The guide normal in world coordinates. /// @param[in] plane True if the guide is a plane, false if it's a ray/line. /// @param[in] ss The passed Snap context structure. /// @param[out] result Contains data about the resulting intersection points if they're generated. /// @return True if an intersection occurred, false if not. //---------------------------------------------------------------------------------------- virtual Bool Intersect(const Vector& p, const Vector& n, Bool plane, const SnapStruct& ss, SnapPoint& result){ return false; } //---------------------------------------------------------------------------------------- /// Free any stored data after snapping has occurred /// @param [in] ss The passed Snap context structure. //---------------------------------------------------------------------------------------- virtual void FreeSnap(const SnapStruct& ss) { } //---------------------------------------------------------------------------------------- /// Snap draw routine. /// @param[in] ss The passed Snap context structure. /// @param[in] doc The current Document Passed by the tool. /// @param[in] bd The current BaseDraw passed by the tool. /// @param[in] bh The current BaseDrawHelp passed by the tool. /// @param[in] bt The current BaseThread passed by the tool. /// @return True success of drawing //---------------------------------------------------------------------------------------- virtual Bool Draw(const SnapStruct& ss, BaseDocument* doc, BaseDraw* bd, BaseDrawHelp* bh, BaseThread* bt) { return true; } //---------------------------------------------------------------------------------------- /// Intercepting the GetCursorInfo purely for the snap. /// @param[in] ss The passed Snap context structure. /// @param[in] doc The current Document Passed by the tool. /// @param[in] bd The current BaseDraw passed by the tool. /// @param[in] x Mouse x position passed by the tool. /// @param[in] y Mouse x position passed by the tool. /// @param[out] result The message container passed by the tool. /// @return True if you need to override the active tool otherwise false. //---------------------------------------------------------------------------------------- virtual Bool GetCursorInfo(const SnapStruct& ss, BaseDocument* doc, BaseDraw* bd, Float x, Float y, BaseContainer& result) { return false; } //---------------------------------------------------------------------------------------- /// Intercepting the MouseInput purely for the snap. /// @param[in] ss The passed Snap context structure. /// @param[in] doc The current Document Passed by the tool. /// @param[in] bd The current BaseDraw passed by the tool. /// @param[in] win The current EditorWindow passed by the tool. /// @param[in] msg The message container passed by the tool. /// @return True if you need to override the active tool otherwise false. //---------------------------------------------------------------------------------------- virtual Bool MouseInput(const SnapStruct& ss, BaseDocument* doc, BaseDraw* bd, EditorWindow* win, const BaseContainer& msg){ return false; } //---------------------------------------------------------------------------------------- /// Intercepting the KeyboardInput purely for the snap. /// @param[in] ss The passed Snap context structure. /// @param[in] doc The current Document Passed by the tool. /// @param[in] bd The current BaseDraw passed by the tool. /// @param[in] win The current EditorWindow passed by the tool. /// @param[in] msg The message container passed by the tool. /// @return True if you need to override the active tool otherwise false. //---------------------------------------------------------------------------------------- virtual Bool KeyboardInput(const SnapStruct& ss, BaseDocument* doc, BaseDraw* bd, EditorWindow* win, const BaseContainer& msg) { return false; } }; //---------------------------------------------------------------------------------------- /// The Snap Interface, must be allocated either with AutoAlloc or Alloc and freed after use with Free //---------------------------------------------------------------------------------------- class SnapCore { private: SnapCore(void) { } public: //---------------------------------------------------------------------------------------- /// Snap Initialization routine. /// @param[in] doc The current document. /// @param[in] bd The BaseDraw to initalize. /// @param[in] exclude An array of objects to exclude from being snapped to. /// @return True on success of initializing the snap. //---------------------------------------------------------------------------------------- Bool Init(BaseDocument* doc, BaseDraw* bd, AtomArray* exclude = nullptr); //---------------------------------------------------------------------------------------- /// Updates the snaps to use the current settings. /// @return True on success of updating. //---------------------------------------------------------------------------------------- Bool Update(void); //---------------------------------------------------------------------------------------- /// Snap Initialization routine. /// @param[in] p The position to snap to in global space. /// @param[out] result The position to snap to in global space. /// @param[in] flags The flags to limit snapping on selection or to a spcific type. /// @return True on success of finding a snap point, false if no point was found in range to snap to. //---------------------------------------------------------------------------------------- Bool Snap(const Vector& p, SnapResult& result, SNAPFLAGS flags = SNAPFLAGS_0); //---------------------------------------------------------------------------------------- /// Snap Initialization routine. /// @param[in] p The position to snap to in global space. /// @param[in] n The normal of the guide being intersected with in global space. /// @param[in] plane True if the intersection should be with a plane, false if with a ray/line. /// @param[out] result The result of the successful intersection, user owns this. /// @param[in] flags The flags to limit snapping on selection or to a spcific type. /// @return True on success of finding an intersection, false if no intersection was found in range. //---------------------------------------------------------------------------------------- Bool Intersect(const Vector& p, const Vector& n, Bool plane, SnapResult& result, SNAPFLAGS flags = SNAPFLAGS_0); //---------------------------------------------------------------------------------------- /// Adds an inferred guide point, line or plane to the scene for snapping to. /// @param[in] doc The current document. /// @param[in] mat The matrix for the point (axis), line, or plane, z points along the line or as the normal for the plane. /// @param[in] type The type of inferred guide to add. /// @return True on success of adding the guide, false for a memory error attempting to do so. //---------------------------------------------------------------------------------------- BaseObject* AddInferred(BaseDocument* doc, const Matrix& mat, INFERREDGUIDETYPE type); //---------------------------------------------------------------------------------------- /// Flush Inferred System all guides and inferred elements will be deleted, should be called at mouse release. /// @return True on success of removing all inferred guides. //---------------------------------------------------------------------------------------- Bool FlushInferred(void); //---------------------------------------------------------------------------------------- /// Recive the active object and pass it to SnapHook if is created from current tool important for tool guide. /// @param[in] op The new Object created in the tool. //---------------------------------------------------------------------------------------- void SetToolObject(BaseObject* op); //---------------------------------------------------------------------------------------- /// Standard allocation routine. /// @return Instance of SnapCore. //---------------------------------------------------------------------------------------- static SnapCore* Alloc(void); //---------------------------------------------------------------------------------------- /// Standard freeing routine. /// @param[in] &p The Snap core to Free. //---------------------------------------------------------------------------------------- static void Free(SnapCore*& p); }; //---------------------------------------------------------------------------------------- /// Test if a snap mode is enabled or not. /// @param[in] doc The document you wish to test within. /// @param[in] mode The snapmode's ID to test for. /// @return True if the snap is enabled, false if not. //---------------------------------------------------------------------------------------- Bool IsSnapEnabled(BaseDocument* doc, Int32 mode = NOTOK); //---------------------------------------------------------------------------------------- /// Set the snap enabled status for a particular mode. /// @param[in] state The state to use true for enabled false for disabled. /// @param[in] doc The document to set the snapmode state for. /// @param[in] mode The snapmode to set the enabled state for. //---------------------------------------------------------------------------------------- void EnableSnap(Bool state, BaseDocument* doc, Int32 mode = NOTOK); //---------------------------------------------------------------------------------------- /// Routine to get the snap settings for the current document. /// @param[in] doc The document who's snap settings you wish to retrieve. /// @param[in] snapmode Optionally pick a specific snap mode to get or modify it's specific settings. /// @return A copy of the settings in a BaseContainer form. //---------------------------------------------------------------------------------------- BaseContainer SnapSettings(BaseDocument* doc, Int32 snapmode = NOTOK); //---------------------------------------------------------------------------------------- /// Routine to set the snap settings for the current mode/document. /// @param[in] doc The document you wish to set the snap settings for. /// @param[in] bc The BaseContainer with the settings for this document and/or snapmode. /// @param[in] snapmode Optionally specify which snapmode you wish to set the settings for instead of the global settings. //---------------------------------------------------------------------------------------- void SnapSettings(BaseDocument* doc, const BaseContainer& bc, Int32 snapmode = NOTOK); //---------------------------------------------------------------------------------------- /// Test if quantizing is enabled or not. /// @param[in] doc The document you wish to test within. /// @return True if quantizing is enabled, false if not. //---------------------------------------------------------------------------------------- Bool IsQuantizeEnabled(BaseDocument* doc); //---------------------------------------------------------------------------------------- /// Retrieve the quantize step values from QUANTIZE_MOVE, QUANTIZE_SCALE etc. /// @param[in] doc The document you wish to retrieve parameters for. /// @param[in] bd The viewport that you want to retrieve the correct QUANTIZE_MOVE value for, not relevant for other quantize modes. /// @param[in] quantize_mode The mode you want to retrieve the value for, e.g. QUANTIZE_ROTATE, QUANTIZE_MOVE or QUANTIZE_SCALE. /// @return The real step value. //---------------------------------------------------------------------------------------- Float QuantizeStep(BaseDocument* doc, BaseDraw* bd, Int32 quantize_mode); //---------------------------------------------------------------------------------------- /// Sets the quantize step values for QUANTIZE_MOVE, QUANTIZE_SCALE etc. /// @param[in] doc The document you wish to set parameters for. /// @param[in] bd The viewport that you want to set the correct QUANTIZE_MOVE value for, not relevant for other quantize modes. /// @param[in] quantize_mode The mode you want to set the value for, e.g. QUANTIZE_ROTATE, QUANTIZE_MOVE or QUANTIZE_SCALE. /// @param[in] val The value that you want to set the quantizing step size to. //---------------------------------------------------------------------------------------- void QuantizeStep(BaseDocument* doc, BaseDraw* bd, Int32 quantize_mode, Float val); //---------------------------------------------------------------------------------------- /// Retrieve the viewport workplane and orientation. /// @param[in] bd The viewport you want to get the workplane's matrix from. /// @param[out] mg A passed Matrix used to retrieve the correct workplane matrix, caller owns, pass nullptr to skip. /// @param[out] scale A passed Vector used to retrieve the correct workplane scale, called owns, pass nullptr to skip. /// @param[out] op Will be filled with the workplane object itself, called owns, pass nullptr to skip. /// @return True on success of retrieving the workplane and it's data. //---------------------------------------------------------------------------------------- Bool GetConstructionPlane(BaseDraw* bd, Matrix* mg, Vector* scale, BaseObject** op); //---------------------------------------------------------------------------------------- /// Retrieve the workplane object for the document. /// @param[in] doc The document to retrieve the workplane from. /// @return The workplane object. //---------------------------------------------------------------------------------------- BaseObject* GetWorkplaneObject(BaseDocument* doc); //---------------------------------------------------------------------------------------- /// Get the current workplane locked status. /// @param[in] doc The BaseDocument that the workplane belongs to. /// @return True if the workplane is locked //---------------------------------------------------------------------------------------- Bool WorkplaneLock(BaseDocument* doc); //---------------------------------------------------------------------------------------- /// Set the current workplane locked status. /// @param[in] bd The Viewport that to lock the workplane within. /// @param[in] locked Whether to lock or unlock the workplane. //---------------------------------------------------------------------------------------- void WorkplaneLock(BaseDraw* bd, Bool locked); //---------------------------------------------------------------------------------------- /// Get the current workplane Matrix. /// @param[in] doc The BaseDocument that the workplane belongs to. /// @param[in] bd The viewport you want to get the workplane's matrix from, if nullptr the locked matrix is returned indipendently form view. /// @return The workplane matrix. //---------------------------------------------------------------------------------------- Matrix GetWorkplaneMatrix(BaseDocument* doc, BaseDraw* bd); //---------------------------------------------------------------------------------------- /// Snap registration routines. //---------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------- /// Snap allocator type, used purely in RegisterSnapPlugin. //---------------------------------------------------------------------------------------- typedef SnapData* SnapDataAllocator (void); //---------------------------------------------------------------------------------------- /// Snap registration. /// @param[in] id The unique identifier for this plugin, should be registered on plugincafe.com. /// @param[in] str The name for the snap mode, normally for localization you should use GeLoadString(ID) using c4d_symbols and the strings files in your resource folder. /// @param[in] help A small block of information that will appear in the interface to explain how the snap mode operates. /// @param[in] snapinfo Standard registration flags, this includes PLUGINFLAG_SNAP_INFERRED_POINT and PLUGINFLAG_SNAP_INFERRED_AXIS. /// @param[in] npalloc The allocator, create a static SnapPlugin::Alloc() { return NewObjClear(MySnapMode); } method in your class, then set this to MySnapMode::Alloc. /// @param[in] icon A bitmap icon for the snap mode. /// @param[in] priority The priority of the snap mode, a higher priority will take precedent over other snaps within the radius. /// @param[in] parent_mode An ID for a parent snap mode, this mode then inherits that modes enabled/disabled state. /// @return true on success of registering the new snap mode plugin. //---------------------------------------------------------------------------------------- Bool RegisterSnapPlugin(Int32 id, const String& str, const String& help, Int32 snapinfo, SnapDataAllocator* npalloc, BaseBitmap* icon, SNAPPRIORITY priority = SNAPPRIORITY_EDGE, Int32 parent_mode = NOTOK); #endif