From 95e008ea4b3a9fc28d1c14ae4de5ad177dd356eb Mon Sep 17 00:00:00 2001 From: Frank Willeke Date: Thu, 14 Jan 2021 21:04:59 +0100 Subject: [PATCH 1/2] Added invert option --- res/description/oProjector.h | 3 ++- res/description/oProjector.res | 16 +++++++++------- res/strings_de/description/oProjector.str | 1 + res/strings_us/description/oProjector.str | 1 + source/object/oProjector.cpp | 20 ++++++++++---------- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/res/description/oProjector.h b/res/description/oProjector.h index bc69dff..1c1a0cb 100644 --- a/res/description/oProjector.h +++ b/res/description/oProjector.h @@ -11,7 +11,8 @@ enum PROJECTOR_OFFSET = 10003, // REAL PROJECTOR_BLEND = 10004, // REAL PROJECTOR_GEOMFALLOFF_ENABLE = 10005, // BOOL - PROJECTOR_GEOMFALLOFF_DIST = 10006 // REAL + PROJECTOR_GEOMFALLOFF_DIST = 10006, // REAL + PROJECTOR_INVERT = 10007 // BOOL }; #endif diff --git a/res/description/oProjector.res b/res/description/oProjector.res index 9a0e0f3..de6ef3b 100644 --- a/res/description/oProjector.res +++ b/res/description/oProjector.res @@ -3,12 +3,12 @@ CONTAINER oProjector NAME oProjector; INCLUDE Obase; - GROUP PROJECTOR_GROUP_PARAMS + GROUP PROJECTOR_GROUP_PARAMS { DEFAULT 1; - LINK PROJECTOR_LINK { ACCEPT { Obase; } } - LONG PROJECTOR_MODE + LINK PROJECTOR_LINK { ACCEPT { Obase; } } + LONG PROJECTOR_MODE { CYCLE { @@ -16,10 +16,12 @@ CONTAINER oProjector PROJECTOR_MODE_SPHERICAL; } } - REAL PROJECTOR_OFFSET { UNIT METER; MINSLIDER -50.0; MAXSLIDER 50.0; CUSTOMGUI REALSLIDER; } - REAL PROJECTOR_BLEND { UNIT PERCENT; MIN 0.0; MAX 100.0; CUSTOMGUI REALSLIDER; } + BOOL PROJECTOR_INVERT { } - BOOL PROJECTOR_GEOMFALLOFF_ENABLE { } - REAL PROJECTOR_GEOMFALLOFF_DIST { UNIT METER; MIN 0.0; STEP 1.0; } + REAL PROJECTOR_OFFSET { UNIT METER; MINSLIDER -50.0; MAXSLIDER 50.0; CUSTOMGUI REALSLIDER; } + REAL PROJECTOR_BLEND { UNIT PERCENT; MIN 0.0; MAX 100.0; CUSTOMGUI REALSLIDER; } + + BOOL PROJECTOR_GEOMFALLOFF_ENABLE { } + REAL PROJECTOR_GEOMFALLOFF_DIST { UNIT METER; MIN 0.0; STEP 1.0; } } } diff --git a/res/strings_de/description/oProjector.str b/res/strings_de/description/oProjector.str index dcf3c23..5702fb7 100644 --- a/res/strings_de/description/oProjector.str +++ b/res/strings_de/description/oProjector.str @@ -7,6 +7,7 @@ STRINGTABLE oProjector PROJECTOR_MODE "Modus"; PROJECTOR_MODE_PARALLEL "Parallel"; PROJECTOR_MODE_SPHERICAL "Sph\u00E4risch"; + PROJECTOR_INVERT "Invertieren"; PROJECTOR_OFFSET "Versatz"; PROJECTOR_BLEND "Blenden"; PROJECTOR_GEOMFALLOFF_ENABLE "Geometrie-Falloff"; diff --git a/res/strings_us/description/oProjector.str b/res/strings_us/description/oProjector.str index b6b8e37..b1554cb 100644 --- a/res/strings_us/description/oProjector.str +++ b/res/strings_us/description/oProjector.str @@ -7,6 +7,7 @@ STRINGTABLE oProjector PROJECTOR_MODE "Mode"; PROJECTOR_MODE_PARALLEL "Parallel"; PROJECTOR_MODE_SPHERICAL "Spherical"; + PROJECTOR_INVERT "Invert"; PROJECTOR_OFFSET "Offset"; PROJECTOR_BLEND "Blend"; PROJECTOR_GEOMFALLOFF_ENABLE "Geometry Falloff"; diff --git a/source/object/oProjector.cpp b/source/object/oProjector.cpp index 9603aa7..9eea326 100644 --- a/source/object/oProjector.cpp +++ b/source/object/oProjector.cpp @@ -53,6 +53,7 @@ Bool oProjector::Init(GeListNode *node) bc->SetInt32(PROJECTOR_MODE, PROJECTOR_MODE_PARALLEL); bc->SetFloat(PROJECTOR_OFFSET, 0.0); bc->SetFloat(PROJECTOR_BLEND, 1.0); + bc->SetBool(PROJECTOR_INVERT, false); bc->SetBool(PROJECTOR_GEOMFALLOFF_ENABLE, false); bc->SetFloat(PROJECTOR_GEOMFALLOFF_DIST, 150.0); @@ -137,7 +138,7 @@ DRAWRESULT oProjector::Draw(BaseObject *op, DRAWPASS drawpass, BaseDraw *bd, Bas bd->SetPen(bd->GetObjectColor(bh, op)); // Get projector mode - PROJECTORMODE mode = (PROJECTORMODE)bc->GetInt32(PROJECTOR_MODE, PROJECTOR_MODE_PARALLEL); + const PROJECTORMODE mode = (PROJECTORMODE)bc->GetInt32(PROJECTOR_MODE, PROJECTOR_MODE_PARALLEL); // Draw arrows in parallel mode, or star in spherical mode if (mode == PROJECTORMODE::PARALLEL) @@ -198,11 +199,12 @@ Bool oProjector::ModifyObject(BaseObject *mod, BaseDocument *doc, BaseObject *op } // Get parameters - PROJECTORMODE mode = (PROJECTORMODE)bc->GetInt32(PROJECTOR_MODE, PROJECTOR_MODE_PARALLEL); - Float offset = bc->GetFloat(PROJECTOR_OFFSET, 0.0); - Float blend = bc->GetFloat(PROJECTOR_BLEND, 1.0); - Bool geometryFalloffEnabled = bc->GetBool(PROJECTOR_GEOMFALLOFF_ENABLE, false); - Float geometryFalloffDist = bc->GetFloat(PROJECTOR_GEOMFALLOFF_DIST, 100.0); + const PROJECTORMODE mode = (PROJECTORMODE)bc->GetInt32(PROJECTOR_MODE, PROJECTOR_MODE_PARALLEL); + const Float offset = bc->GetFloat(PROJECTOR_OFFSET, 0.0); + const Float blend = bc->GetFloat(PROJECTOR_BLEND, 1.0); + const Bool geometryFalloffEnabled = bc->GetBool(PROJECTOR_GEOMFALLOFF_ENABLE, false); + const Float geometryFalloffDist = bc->GetFloat(PROJECTOR_GEOMFALLOFF_DIST, 100.0); + const Bool invert = bc->GetBool(PROJECTOR_INVERT, false); // Calculate weight map from vertex maps linked in restriction tag Float32* weightMap = nullptr; @@ -217,7 +219,7 @@ Bool oProjector::ModifyObject(BaseObject *mod, BaseDocument *doc, BaseObject *op return false; // Parameters for projection - wsPointProjectorParams projectorParams(mod->GetMg(), mode, offset, blend, geometryFalloffEnabled, geometryFalloffDist, weightMap, _falloff); + wsPointProjectorParams projectorParams(mod->GetMg(), mode, offset, blend, geometryFalloffEnabled, geometryFalloffDist, invert, weightMap, _falloff); // Perform projection if (!_projector.Project(static_cast(op), projectorParams, thread)) @@ -269,8 +271,7 @@ void oProjector::CheckDirty(BaseObject *op, BaseDocument *doc) // Iterate modifier and its parents and add their dirty checksums dirtyness += AddDirtySums(op, false, dirtyFlags); -#if API_VERSION >= 23000 - // Add falloff dirtiness + // Add falloff/Fields dirtiness if (_falloff) { dirtyness += _falloff->GetDirty(doc); @@ -311,7 +312,6 @@ void oProjector::CheckDirty(BaseObject *op, BaseDocument *doc) } } -#endif // Compare dirty checksum to previous one, set modifier dirty if necessary if (dirtyness != _lastDirtyness + 1) From 16abe91f66951da50d9bba473a7ae86f9a66ab65 Mon Sep 17 00:00:00 2001 From: Frank Willeke Date: Thu, 14 Jan 2021 21:05:08 +0100 Subject: [PATCH 2/2] Added Fields convenience functions --- source/lib/wsFunctions.cpp | 57 +++++++++++++++++++++++++++++++++ source/lib/wsFunctions.h | 6 ++++ source/lib/wsPointProjector.cpp | 17 +++++++--- source/lib/wsPointProjector.h | 5 ++- 4 files changed, 80 insertions(+), 5 deletions(-) diff --git a/source/lib/wsFunctions.cpp b/source/lib/wsFunctions.cpp index 0351b0b..5cfc338 100644 --- a/source/lib/wsFunctions.cpp +++ b/source/lib/wsFunctions.cpp @@ -155,3 +155,60 @@ FieldLayer* IterateNextFieldLayer(FieldLayer* layer) return layer->GetNext(); } + + +Bool IsValidFieldLayer(FieldLayer* fieldLayer, BaseDocument* doc) +{ + // Check pointer + if (!fieldLayer) + return false; + + // Flagged as no-to-be-used (doesn't seem to work, flags are never set) + const FIELDLAYER_FLAG layerFlags = fieldLayer->GetLayerFlags(); + if (layerFlags&FIELDLAYER_FLAG::SKIP || + layerFlags&FIELDLAYER_FLAG::ERRORSKIP || + layerFlags&FIELDLAYER_FLAG::HIDE || + layerFlags&FIELDLAYER_FLAG::TEMPORARY) + return false; + + // Dead link but not a folder (once the flags actually work, the first line can be removed) + if (!fieldLayer->GetLinkedObject(doc)._object && + fieldLayer->GetType() != FLfolder) + return false; + + return true; +} + + +Bool IsActiveFieldLayer(FieldLayer* fieldLayer) +{ + // Check pointer + if (!fieldLayer) + return false; + + // Inactive or not sampling the value (we only need the ones that sample value) + const FIELDLAYER_CHANNELFLAG channelFlags = fieldLayer->GetChannelFlags(); + if (!(channelFlags&FIELDLAYER_CHANNELFLAG::ENABLE)) + return false; + + // We can consider the FieldLayer active + return true; +} + + +Int CountActiveAndValidFieldLayers(FieldList* fieldList, BaseDocument* doc) +{ + if (!fieldList) + return NOTOK; + + GeListHead *listHead = fieldList->GetLayersRoot(); + + Int count = 0; + + for (FieldLayer *fieldLayer = static_cast(listHead->GetFirst()); fieldLayer; fieldLayer = IterateNextFieldLayer(fieldLayer)) + { + if (IsValidFieldLayer(fieldLayer, doc) && IsActiveFieldLayer(fieldLayer)) + ++count; + } + return count; +} diff --git a/source/lib/wsFunctions.h b/source/lib/wsFunctions.h index d2b76e5..e5528c3 100644 --- a/source/lib/wsFunctions.h +++ b/source/lib/wsFunctions.h @@ -42,4 +42,10 @@ UInt32 AddDirtySums(BaseObject *op, Bool goDown, DIRTYFLAGS flags); /// @return The next layer FieldLayer* IterateNextFieldLayer(FieldLayer* layer); +Bool IsValidFieldLayer(FieldLayer* fieldLayer, BaseDocument* doc); + +Bool IsActiveFieldLayer(FieldLayer* fieldLayer); + +Int CountActiveAndValidFieldLayers(FieldList* fieldList, BaseDocument* doc); + #endif // WS_FUNCTIONS_H__ diff --git a/source/lib/wsPointProjector.cpp b/source/lib/wsPointProjector.cpp index 581b464..b41be82 100644 --- a/source/lib/wsPointProjector.cpp +++ b/source/lib/wsPointProjector.cpp @@ -103,7 +103,7 @@ Bool wsPointProjector::Project(PointObject *op, const wsPointProjectorParams &pa // Calculate a ray length. // The resulting length might be a bit too long, but with this we're on the safe side. No ray should ever be too short to reach the collision geometry. - Float rayLength = (collisionObjectMg.off - opMg.off).GetLength() + _collisionObject->GetRad().GetSum()+ op->GetRad().GetSum(); + Float rayLength = (collisionObjectMg.off - opMg.off).GetLength() + _collisionObject->GetRad().GetSum() + op->GetRad().GetSum(); // Iterate points for (Int32 i = 0; i < pointCount; i++) @@ -120,10 +120,19 @@ Bool wsPointProjector::Project(PointObject *op, const wsPointProjectorParams &pa // This needs to be done inside the loop, as the direction is different for each point if (params._mode == PROJECTORMODE::SPHERICAL) { - // Direction points from the modifier to the position of the point - rayDirection = rayPosition - params._modifierMg.off; + + if (params._invert) + { + // Direction points from the position of the point to the modifier + rayDirection = params._modifierMg.off - rayPosition; + } + else + { + // Direction points from the modifier to the position of the point + rayDirection = rayPosition - params._modifierMg.off; + } } - + // Project point, cancel if critical error occurred if (!ProjectPosition(rayPosition, rayDirection, rayLength, collisionObjectMg, collisionObjectMgI, params._offset, params._blend)) return false; diff --git a/source/lib/wsPointProjector.h b/source/lib/wsPointProjector.h index 82b59a1..e49949c 100644 --- a/source/lib/wsPointProjector.h +++ b/source/lib/wsPointProjector.h @@ -26,6 +26,7 @@ struct wsPointProjectorParams Bool _geometryFalloffEnabled = true; ///< Geometry falloff enabled attribute Float _geometryFalloffDist = 0.0_f; ///< Geometry falloff distance attribute Float32* _weightMap = nullptr; ///< Ptr to weight map + Bool _invert = false; C4D_Falloff *_falloff = nullptr; ///< Ptr to falloff /// Default constructor @@ -36,17 +37,19 @@ struct wsPointProjectorParams _geometryFalloffEnabled(false), _geometryFalloffDist(0.0), _weightMap(nullptr), + _invert(false), _falloff(nullptr) { } /// Constructor with parameters - wsPointProjectorParams(const Matrix &modifierMg, PROJECTORMODE mode, Float offset, Float blend, Bool geometryFalloffEnabled, Float geometryFalloffDist, Float32 *weightMap = nullptr, C4D_Falloff *falloff = nullptr) : + wsPointProjectorParams(const Matrix &modifierMg, PROJECTORMODE mode, Float offset, Float blend, Bool geometryFalloffEnabled, Float geometryFalloffDist, Bool invert, Float32 *weightMap = nullptr, C4D_Falloff *falloff = nullptr) : _modifierMg(modifierMg), _mode(mode), _offset(offset), _blend(blend), _geometryFalloffEnabled(geometryFalloffEnabled), _geometryFalloffDist(geometryFalloffDist), + _invert(invert), _weightMap(weightMap), _falloff(falloff) { }