• Frame all

    c++ windows sdk
    5
    0 Votes
    5 Posts
    1k 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
  • MCOMMAND_JOIN issue

    python
    10
    0 Votes
    10 Posts
    2k Views
    a_blockA
    Hi, thanks for pointing out this issue. We'll see if can get a fix for that (not all tags visible, if zooming in with browser). In the end Maxime wasn't referring to tags at all. Instead he was talking about the Q&A Function we have in this forum. I took the freedom to mark this thread as solved (see this shiny green stamp next to the headline ). Cheers, Andreas
  • r20 python Field

    Moved r20 python
    3
    0 Votes
    3 Posts
    640 Views
    M
    Hi @Nenov, first of all, welcome in the plugincafe community. No worry since it's your first post, but I would like to point you to the Q&A Functionality and How to Post Questions especially about categories. I've setup your topic correctly and moved to the correct category. Regarding your issue, this actually the purpose of the example to do a different operation on even and odd clones. With that's said you can find more example in our Github repository especially theses following files: field_python_color_direction.c4d field_pythonmodifier_readcolor.c4d field_pythonmodifier_vertexmap.c4d If you have any question please let me know, Cheers, Maxime.
  • Get clone of group and keep links

    Moved python
    3
    0 Votes
    3 Posts
    926 Views
    R
    Very cool, thx alot Sebastian rownn
  • Deformer update and Fields

    c++ r20 windows macos
    2
    0 Votes
    2 Posts
    800 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); }
  • Adding Bitmap Button to ListView

    c++ r20 sdk
    5
    1
    0 Votes
    5 Posts
    973 Views
    O
    Thank you @m_adam It works fine
  • Run Plugin Last

    python r19
    3
    1
    0 Votes
    3 Posts
    800 Views
    A
    @m_adam Hi Maxime, It works like a treat! I've ended up changing the UI to a treeView and it's still working great. Thank you very much! Andre
  • TreeView Add Data

    6
    0 Votes
    6 Posts
    1k Views
    O
    I passed on the listview for now. I still have to look in more details for the TreeView. Thank you.
  • Seperators in GetSubContainer

    python windows r20
    2
    1
    0 Votes
    2 Posts
    506 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.
  • FILENAME attribute extension filter

    c++
    5
    0 Votes
    5 Posts
    1k Views
    rsodreR
    @s_bach Ok, I can revert the values to the base container. That solves my issue, thanks!
  • Filling vertex_color for SceneHook

    2
    0 Votes
    2 Posts
    465 Views
    a_blockA
    Hi, GeAllocTypeNC() was already removed from the API with version R15 (see API Change List in R15 and maybe more interesting for you Transition to Cinema 4D R15 API). You are already on the right track using NewMem(), now in R20, there's an additional change, which bites you here: The error handling. This indeed is quite an important topic and (of course no bragging involved at all) a really nice feature in the new MAXON API. But it's also the one thing that causes most needed changes for R20. The point is, here at MAXON we do not take error checking lightly. Actually quite the opposite, we enforce error handling where ever we can and our internal developers have no chance to get away without. So, before I provide the solution, here the recommendation to take the time to read the manuals about the Error System. Additionally I recommend the manuals about classic API Entity Creation and Destruction and its MAXON API sibling about Memory Allocation. The additional means you get provided with in the new MAXON API can really make your life easier. I apologize for writing so much before coming to your actual issue. In the end NewMemClear() now returns an Error Result, which basically encapsulates the actual return value and needs to be evaluated in order to get the actual return value. No worries, this is done in a highly optimized form, so it should not impede your code's performance in any way. If you take a look at our SDK examples, you will find quite a few places, where error handling in conjunction with NewMem is demonstrated in various ways. Cheers, Andreas
  • BaseContainer bc = NULL;

    c++ r20
    3
    0 Votes
    3 Posts
    575 Views
    R
    Thank you Andres. I'm going with the boolean variable to flag if a BaseContainer contains something or not.
  • Quicktab Radio Buttons

    2
    0 Votes
    2 Posts
    770 Views
    merkvilsonM
    Seems like this is a way to go. LONG TEST_BUTTONS {CUSTOMGUI QUICKTABRADIO; CYCLE{ TEST_1; TEST_2; TEST_3; }FIT_H;} Previously my mistake was that I was writing CUSTOMGUI QUICKTABRADIOBUTTON instead of CUSTOMGUI QUICKTABRADIO
  • Non blocking modal

    c++
    3
    0 Votes
    3 Posts
    727 Views
    rsodreR
    @m_adam I think that will not be possible for what I want to do. I ended up catching BFM_LOSTFOCUS in the dialog, canceling the process.
  • INCLUDE user-defined res files

    python
    3
    0 Votes
    3 Posts
    917 Views
    a_blockA
    Hi, no, you are not! Really there are no stupid questions and please do not delete such posts. Especially not, if you already invested time in posting the correct answer. We'd rather see this as knowledge others might benefit from in the future. Cheers, Andreas
  • Using maxon::BaseList with a TreeView?

    2
    0 Votes
    2 Posts
    568 Views
    M
    Hi @Kuroyume0161, first of all, welcome back in the plugincafe community, I'm glad to see you here! Unfortunately, this is not possible to use directly a BaseList with a TreeView and as you already figured it out, you have to maintain this list yourself. While it's very nice that a TreeView offer this abstraction level, and allows to make a list from any kind of data, it has the overhead to builds this TreeView layer. Cheers, Maxime.
  • Adding icon to submenu

    python windows r20
    7
    1
    0 Votes
    7 Posts
    1k 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.
  • getline not working

    6
    0 Votes
    6 Posts
    1k Views
    R
    It is so weird that it worked in versions pre R20. Well, I will have to find a new solution, then.
  • GetCache() bug

    python
    4
    0 Votes
    4 Posts
    952 Views
    M
    Hi @merkvilson, this feedback has been communicated to our development team. Cheers, Maxime.
  • Checkmark in submenu list when using GetSubContainer

    python r20
    4
    2
    0 Votes
    4 Posts
    817 Views
    a_blockA
    Yes, that's appropriate. Thanks