• 0 Votes
    3 Posts
    535 Views
    O
    Hello @r_gigante Thank you for your time and answer. I will try the other way then. Best, Ogers
  • EditText: intercept/discard keystrokes

    Cinema 4D SDK python r20 windows
    7
    0 Votes
    7 Posts
    1k Views
    M
    Thank you Maxime. My current solution looks pretty similar to yours and works . Implementing an own gadget is of course out of scope - I don't even get paid for that.
  • Add tooltip to subcommand

    Cinema 4D SDK python windows r20
    3
    0 Votes
    3 Posts
    750 Views
    B
    Thanks for confirming my suspicion
  • Open GeDialog on second screen

    Cinema 4D SDK python windows r20
    3
    0 Votes
    3 Posts
    769 Views
    B
    Ok, thanks!
  • Drawing into Rendering

    Cinema 4D SDK r20 python windows
    7
    0 Votes
    7 Posts
    2k Views
    r_giganteR
    Hi @rownn, thanks for having provided further details. Assuming that you're aware of the limitation in terms of appearance that you might face by using the functionalities delivered by GeClipMap, the only way to go to access a bitmap which is supposed to contain a rendering of the scene in Python is to execute the rendering invoking the BaseDocument::RenderDocument() and pass the BaseBitmap you intend to manipulate via the GeClipMap. Best, Riccardo
  • GetClone() with Fields

    Cinema 4D SDK r20 python windows
    4
    3
    0 Votes
    4 Posts
    1k Views
    GianniG
    Just tried now… It seems to work perfectly! Thank you! I don't want to boring you, but, please, don't disable this super feature in python. Instead you could update the documentation specifying well how to use it.
  • Lots of "unresolved external symbol" errors

    Cinema 4D SDK c++ windows r20
    9
    0 Votes
    9 Posts
    2k Views
    a_blockA
    Hi, we are glad @rui_mac you were able to solve your problem. I'd just like to quickly recap to make this also clear for future readers. Visual Studio has two "concepts" two organize your development work. Projects, which is basically a set of files plus a bunch of configuration options and instructions for the tool chain (compiler, linker,...) to build a binary (in our case here always a plugin library). Solutions, which are collections of above projects plus some additional global configuration data and more important, information on dependencies of the contained projects. Now, our project tool can and does create both projects (for your plugins and for our frameworks) and a solution containing all of the above (actual workflow described in our docs under the links provided by Riccardo earlier on in this thread). So when you open such a solution and build your plugin project, also the frameworks it's depending on should be built.So, this is the way to go (project tool -> solution and projects -> open solution in Visual Studio). But if you instead open just one of the generated projects directly, Visual Studio will implicitly generate a solution for you, but it still lacks the framework projects and the build of the opened project will fail (error: unresolved symbols, i.e. function or class names normally provided by our frameworks and used in the plugins code can not be resolved). I hope this makes it a bit easier to understand. Cheers, Andreas
  • FormatStatement and maxon DataTypes...

    Cinema 4D SDK r20 c++ windows
    5
    0 Votes
    5 Posts
    1k Views
    M
    Ah, thank you. I didn't take a look at vec.h. Meanwhile, I already wrote a conversion unit to handle all sorts of formatting. Thought, it was possible to modify the intern string conversions somehow. But nevermind, all works pretty well. Cheers, Robert
  • Register Plugin during runtime

    Cinema 4D SDK python r20 windows
    3
    0 Votes
    3 Posts
    762 Views
    B
    Ok, thanks Riccardo! I'll register them at the start then.
  • Compatibility between R20 versions

    Cinema 4D SDK c++ windows macos r20
    2
    0 Votes
    2 Posts
    499 Views
    M
    Hi Franck, backward and upward compatibility for the current major release is something we really consider and try our best to not break. Unfortunately, for R20 plugins, they need to be recompiled to make them compatible with R20 SP1. See C++ Index or either in the R20.026 changelog. You may encounter an issue with plugin compiled with R20.011 (see the R20.026 changelog) since you may override maxon dedicated IDs which will break for sure some C4D/plugin stuff. Cheers, Maxime.
  • Get PluginID from within CommandData plugin

    Cinema 4D SDK python r20 windows
    4
    0 Votes
    4 Posts
    1k Views
    B
    I am trying to register multiple plugins that are instances of the same class, but do slightly different stuff (in this case construct different menus). I am getting some external data that I would like to put in a dictionary with the plugin ID as keys. I could then get the correct data set for each plugin by comparing the pluginID from e.g. within execute with the pluginIDs in the dictionary. But for that I would need a way to retrieve the pluginID of the class instance whose execute function was called. Edit: I figured out a way. I can pass the pluginID when initializing the plugin in the register function and save it as a class member in __init__
  • Parameters for commandData Plugin

    Cinema 4D SDK python r20 windows
    3
    0 Votes
    3 Posts
    644 Views
    B
    Hi Sebastian! Thanks for your answer. I was looking for something a little more flexible than registering multiple plugins, but I guess GetSubContainer will have to do
  • MAXON Data Type and explicit constructors

    Cinema 4D SDK c++ r20 windows
    7
    0 Votes
    7 Posts
    2k Views
    M
    Thanks Riccardo! Now I understand - thanks to your side note. And of course I understand, that this goes hand in hand with your guidelines. Cheers, Robert
  • Deformer update and Fields

    Cinema 4D SDK c++ r20 windows macos
    2
    0 Votes
    2 Posts
    842 Views
    ValkaariV
    using the CheckDirty function seem to be the solution. void Spherify::CheckDirty(BaseObject* op, BaseDocument* doc) { if (falloff) { BaseContainer *data = op->GetDataInstance(); Int32 dirty = falloff->GetDirty(doc, data); if (dirty == lastFalloffDirtyCheck) return; op->SetDirty(DIRTYFLAGS::DATA); lastFalloffDirtyCheck = dirty; } } the full code for the spherify deformer : // deformer object example #include "c4d.h" #include "c4d_symbols.h" #include "main.h" #include "ospherifydeformer.h" #include "c4d_falloffdata.h" #define HANDLE_CNT 2 class Spherify : public ObjectData { public: virtual Bool Init(GeListNode* node); virtual Bool Message (GeListNode* node, Int32 type, void* data); virtual void GetDimension (BaseObject* op, Vector* mp, Vector* rad); virtual DRAWRESULT Draw (BaseObject* op, DRAWPASS type, BaseDraw* bd, BaseDrawHelp* bh); virtual void GetHandle (BaseObject* op, Int32 i, HandleInfo& info); virtual Int32 DetectHandle (BaseObject* op, BaseDraw* bd, Int32 x, Int32 y, QUALIFIER qualifier); virtual Bool MoveHandle (BaseObject* op, BaseObject* undo, const Vector& mouse_pos, Int32 hit_id, QUALIFIER qualifier, BaseDraw* bd); virtual Bool ModifyObject (BaseObject* op, BaseDocument* doc, BaseObject* mod, const Matrix& op_mg, const Matrix& mod_mg, Float lod, Int32 flags, BaseThread* thread); AutoAlloc<C4D_Falloff> falloff; Int32 lastFalloffDirtyCheck; virtual Int32 GetHandleCount(BaseObject *op); virtual void SetHandle(BaseObject *op, Int32 i, Vector p, const HandleInfo &info); virtual Bool CopyTo(NodeData *dest, GeListNode *snode, GeListNode *dnode, COPYFLAGS flags, AliasTrans *trn); virtual Bool GetDDescription(GeListNode *node, Description *description, DESCFLAGS_DESC &flags); virtual Bool AddToExecution(BaseObject *op, PriorityList *list); virtual EXECUTIONRESULT Execute(BaseObject *op, BaseDocument *doc, BaseThread *bt, Int32 priority, EXECUTIONFLAGS flags); virtual void CheckDirty(BaseObject* op, BaseDocument* doc); static NodeData* Alloc() { return NewObjClear(Spherify); } }; Int32 Spherify::GetHandleCount(BaseObject *op) { BaseContainer *bc = op->GetDataInstance(); if (!bc) return 0; if (falloff) return falloff->GetHandleCount(bc) + HANDLE_CNT; return 0; } void Spherify::SetHandle(BaseObject *op, Int32 i, Vector p, const HandleInfo &info) { BaseContainer *bc = op->GetDataInstance(); if (!bc) return; if (falloff) falloff->SetHandle(i, p, bc, info); } Bool Spherify::CopyTo(NodeData *dest, GeListNode *snode, GeListNode *dnode, COPYFLAGS flags, AliasTrans *trn) { Spherify *df = (Spherify*)dest; if (!df) return false; if (falloff && df->falloff) if (!falloff->CopyTo(df->falloff)) return false; return ObjectData::CopyTo(dest, snode, dnode, flags, trn); } Bool Spherify::GetDDescription(GeListNode *node, Description *description, DESCFLAGS_DESC &flags) { BaseObject *op = (BaseObject*)node; if (!op) return false; BaseContainer *data = op->GetDataInstance(); if (!data) return false; if (!description->LoadDescription(op->GetType())) return false; //--------------------------------- // Add the falloff interface if (falloff) { if (!falloff->SetMode(FIELDS, data)) // The falloff parameters have to have been setup before it can be added to the description, this like makes sure of that return false; if (!falloff->AddFalloffToDescription(description, data, DESCFLAGS_DESC::NONE)) return false; } flags |= DESCFLAGS_DESC::LOADED; return true; } void Spherify::CheckDirty(BaseObject* op, BaseDocument* doc) { if (falloff) { BaseContainer *data = op->GetDataInstance(); Int32 dirty = falloff->GetDirty(doc, data); if (dirty == lastFalloffDirtyCheck) return; op->SetDirty(DIRTYFLAGS::DATA); lastFalloffDirtyCheck = dirty; } } Bool Spherify::AddToExecution(BaseObject *op, PriorityList *list) { list->Add(op, EXECUTIONPRIORITY_INITIAL, EXECUTIONFLAGS::NONE); return TRUE; } EXECUTIONRESULT Spherify::Execute(BaseObject *op, BaseDocument *doc, BaseThread *bt, Int32 priority, EXECUTIONFLAGS flags) { BaseContainer *data = op->GetDataInstance(); if (!data) return EXECUTIONRESULT::USERBREAK; if (falloff) if (!falloff->InitFalloff(data, doc, op)) return EXECUTIONRESULT::OUTOFMEMORY; return EXECUTIONRESULT::OK; } Bool Spherify::Message(GeListNode* node, Int32 type, void* data) { if (type == MSG_MENUPREPARE) { ((BaseObject*)node)->SetDeformMode(true); } return true; } Bool Spherify::ModifyObject(BaseObject* mod, BaseDocument* doc, BaseObject* op, const Matrix& op_mg, const Matrix& mod_mg, Float lod, Int32 flags, BaseThread* thread) { BaseContainer* data = mod->GetDataInstance(); Vector p, *padr = nullptr; Matrix m, im; Int32 i, pcnt; Float rad = data->GetFloat(SPHERIFYDEFORMER_RADIUS), strength = data->GetFloat(SPHERIFYDEFORMER_STRENGTH); Float s; Float32* weight = nullptr; if (!op->IsInstanceOf(Opoint)) return true; padr = ToPoint(op)->GetPointW(); pcnt = ToPoint(op)->GetPointCount(); if (!pcnt) return true; FieldInput inputs(padr, pcnt, op_mg); Bool outputsOK = falloff->PreSample(doc, mod, inputs, FIELDSAMPLE_FLAG::VALUE); Float fallOffSampleValue(1.0); weight = ToPoint(op)->CalcVertexMap(mod); m = (~mod_mg) * op_mg; // op -> world -> modifier im = ~m; for (i = 0; i < pcnt; i++) { if (thread && !(i & 63) && thread->TestBreak()) break; p = m * padr[i]; s = strength; if (weight) s *= weight[i]; if (outputsOK) falloff->Sample(p, &fallOffSampleValue, true, 0.0, nullptr, i); s *= fallOffSampleValue; p = s * (!p * rad) + (1.0 - s) * p; padr[i] = im * p; } DeleteMem(weight); op->Message(MSG_UPDATE); return true; } void Spherify::GetDimension(BaseObject* op, Vector* mp, Vector* rad) { BaseContainer* data = op->GetDataInstance(); *mp = Vector(0.0); *rad = Vector(data->GetFloat(SPHERIFYDEFORMER_RADIUS)); } DRAWRESULT Spherify::Draw(BaseObject* op, DRAWPASS drawpass, BaseDraw* bd, BaseDrawHelp* bh) { if (!op->GetDeformMode()) return DRAWRESULT::SKIP; BaseContainer *bc = op->GetDataInstance(); if (!bc) return DRAWRESULT::FAILURE; if (falloff) falloff->Draw(bd, bh, drawpass, bc); if (drawpass == DRAWPASS::OBJECT) { BaseContainer* data = op->GetDataInstance(); Float rad = data->GetFloat(SPHERIFYDEFORMER_RADIUS); Matrix m = bh->GetMg(); m.sqmat *= rad; bd->SetMatrix_Matrix(nullptr, Matrix()); bd->SetPen(bd->GetObjectColor(bh, op)); bd->DrawCircle(m); maxon::Swap(m.sqmat.v2, m.sqmat.v3); bd->DrawCircle(m); maxon::Swap(m.sqmat.v1, m.sqmat.v3); bd->DrawCircle(m); } else if (drawpass == DRAWPASS::HANDLES) { Int32 i; Int32 hitid = op->GetHighlightHandle(bd); HandleInfo info; bd->SetPen(GetViewColor(VIEWCOLOR_ACTIVEPOINT)); bd->SetMatrix_Matrix(op, bh->GetMg()); for (i = 0; i < HANDLE_CNT; i++) { GetHandle(op, i, info); if (hitid == i) bd->SetPen(GetViewColor(VIEWCOLOR_SELECTION_PREVIEW)); else bd->SetPen(GetViewColor(VIEWCOLOR_ACTIVEPOINT)); bd->DrawHandle(info.position, DRAWHANDLE::BIG, 0); } GetHandle(op, 1, info); bd->SetPen(GetViewColor(VIEWCOLOR_ACTIVEPOINT)); bd->DrawLine(info.position, Vector(0.0), 0); } return DRAWRESULT::OK; } void Spherify::GetHandle(BaseObject* op, Int32 i, HandleInfo& info) { BaseContainer* data = op->GetDataInstance(); if (!data) return; if (falloff) falloff->GetHandle(i, data, info); switch (i) { case 0: info.position.x = data->GetFloat(SPHERIFYDEFORMER_RADIUS); info.direction.x = 1.0; info.type = HANDLECONSTRAINTTYPE::LINEAR; break; case 1: info.position.x = data->GetFloat(SPHERIFYDEFORMER_STRENGTH) * 1000.0; info.direction.x = 1.0; info.type = HANDLECONSTRAINTTYPE::LINEAR; break; default: break; } } Int32 Spherify::DetectHandle(BaseObject* op, BaseDraw* bd, Int32 x, Int32 y, QUALIFIER qualifier) { if (qualifier & QUALIFIER::CTRL) return NOTOK; HandleInfo info; Matrix mg = op->GetMg(); Int32 i, ret = NOTOK; Vector p; for (i = 0; i < HANDLE_CNT; i++) { GetHandle(op, i, info); if (bd->PointInRange(mg * info.position, x, y)) { ret = i; if (!(qualifier & QUALIFIER::SHIFT)) break; } } return ret; } Bool Spherify::MoveHandle(BaseObject* op, BaseObject* undo, const Vector& mouse_pos, Int32 hit_id, QUALIFIER qualifier, BaseDraw* bd) { BaseContainer* dst = op->GetDataInstance(); HandleInfo info; Float val = mouse_pos.x; GetHandle(op, hit_id, info); if (bd) { Matrix mg = op->GetUpMg() * undo->GetMl(); Vector pos = bd->ProjectPointOnLine(mg * info.position, mg.sqmat * info.direction, mouse_pos.x, mouse_pos.y); val = Dot(~mg * pos, info.direction); } switch (hit_id) { case 0: dst->SetFloat(SPHERIFYDEFORMER_RADIUS, ClampValue(val, 0.0_f, (Float) MAXRANGE)); break; case 1: dst->SetFloat(SPHERIFYDEFORMER_STRENGTH, Clamp01(val * 0.001)); break; default: break; } return true; } Bool Spherify::Init(GeListNode* node) { BaseObject* op = (BaseObject*)node; BaseContainer* data = op->GetDataInstance(); data->SetFloat(SPHERIFYDEFORMER_RADIUS, 200.0); data->SetFloat(SPHERIFYDEFORMER_STRENGTH, 0.5); if (falloff) { if (!falloff->InitFalloff(nullptr, nullptr, op)) return false; lastFalloffDirtyCheck = -1; } return true; } // be sure to use a unique ID obtained from www.plugincafe.com #define ID_SPHERIFYOBJECT 1001158 Bool RegisterSpherify() { return RegisterObjectPlugin(ID_SPHERIFYOBJECT, GeLoadString(IDS_SPHERIZE), OBJECT_MODIFIER | OBJECT_CALL_ADDEXECUTION, Spherify::Alloc, "Ospherifydeformer"_s, AutoBitmap("spherify.tif"_s), 0); }
  • SaveDocument() file name character limit?

    Cinema 4D SDK python windows r19
    3
    0 Votes
    3 Posts
    814 Views
    .
    Problem was with the total path length versus the file name length. 256 characters for the entire path and filename.
  • Seperators in GetSubContainer

    Cinema 4D SDK python windows r20
    2
    1
    0 Votes
    2 Posts
    536 Views
    M
    Hi @Boony2000 In a GetSubContainer, to insert a separator use InsData(0, "") The ID used should always be 0. As described in ShowPopupDialog Example. Which give us def GetSubContainer(self, doc, submenu) : menuItems = [["name1"], ["name2", "hasIcon"], ["name3"]] for i, data in enumerate(menuItems) : if len(data) > 1: submenu.SetString(i+1000, data[0] + "&i" + str(c4d.IDM_KEY_NEXT) + "&") submenu.InsData(0, "") else: submenu.SetString(i+1000, data[0]) return True Cheers, Maxime.
  • 0 Votes
    8 Posts
    2k Views
    CairynC
    Hi again; just to close off the topic here's what I ultimately found: A lot of the delay that causes the choppyness of the motion is apparently an issue with EventAdd(). I require this call to update the Attribute Manager for the current camera, and to start the recalculation of the interactive render region. But as it seems to refresh about everything, the call causes a noticeable delay before the next viewport refresh comes through. (It is surprising that this call takes longer than a redraw of the viewport, and it is very hard to time as EventAdd() just posts a message to the queue, so I cannot actually measure the execution duration.) The scene camera is slower than the viewport camera. CollieMouse treats both the same, in fact, all handling is done through a CameraObject that I get in a similar way as the one you posted above. Yet, the redraw is slightly slower by itself, and there are apparently things indirectly happening for a scene camera that take even more time (even when expressions are switched off). There is not much I can do about that except allow the user to suppress certain refreshs for the sake of a smoother Space Navigator experience. I'm still not sure what some of the DrawViews() flags exactly mean, by the way. I guess I can ignore the HIGHLIGHT ones for now, but what are INDRAG, INMOVE and FORCEFULLREDRAW really doing, and when do I need to use them? I see that you use INMOVE in your code (but not NO_EXPRESSIONS which surprises me).
  • 3D Mouse Slider Focus

    Cinema 4D SDK python windows r19 maxon api
    13
    1
    0 Votes
    13 Posts
    4k Views
    CairynC
    @charly CollieMouse rotates around the current selection or the explicit rotation center (the one you set with the INS shortcut). It will not rotate around the mouse pointer (I think... I implemented so many modes over time that I tend to forget the options...). The mouse pointer only exists in 2D space anyway so the actual rotation would happen around a projection of the mouse position into the scene, and if you move the mouse, the rotational center would change... not sure whether that is even a usable mode. The mode I'd recommend would be around the explicit center: Position the mouse, press INS (or whatever shortcut you use), and then use the 3D mouse to rotate around that. C4D shows the explicit center as green cross so you always know where it is. At the moment there is no R2023 version of CollieMouse anyway, so the point is moot. But you can reach me under cairyn (at) tigress (dot) com if you require specialty development.
  • Frame all

    Cinema 4D SDK c++ windows sdk
    5
    0 Votes
    5 Posts
    2k Views
    r_giganteR
    Hi WickedP, sorry for no bringing good news, but the architecture of the CommandData doesn't allow to "piggyback" off the "Frame All" command nor I've evidences of messages being sent around to have the "Frame All" to take place. The only, but maybe non-trivial, way to go is to write your own function based on the currently active rendering-camera in your "in-memory" document. Cheers, Riccardo
  • Adding icon to submenu

    Cinema 4D SDK python windows r20
    7
    1
    0 Votes
    7 Posts
    2k Views
    B
    Thanks, Maxime! I will use that in the meantime. Edit: Why can't I flag your posts as the correct answer? I can only flag my own.