• Sampling effect channel shaders

    r20 c++ sdk
    11
    0 Votes
    11 Posts
    3k Views
    rsodreR
    Thanks Riccardo, I think we reached the bottom of this issue. I just finished implementing a workaround, getting the tag associated with the shader, it's polygon, points and uvw tag, then paint each face with the average vertex value in a bitmap using GeClipMat. Working really good! Best, Roger
  • Phong Break Selection

    python
    4
    0 Votes
    4 Posts
    1k Views
    M
    Hi @merkvilson, this is a limitation actually the tool Phong Break selection and the modeling command MCOMMAND_PHONGTOSELECTION are two completely separate things. So the only solution available to you is to manually break the Phong. I'm sorry we can't help you more on that, Donovan points you to the correct direction with the neighbor class. Cheers, Maxime.
  • ColorDialog Flags

    python
    2
    0 Votes
    2 Posts
    601 Views
    S
    Hello, ColorDialog is just the Python version of C++'s GeChooseColor() function. It uses the flags DR_COLORFIELD_ICC_BASEDOC and DR_COLORFIELD_ICC_BPTEX which just define the proper color profile. Typically is is enough to just set 0. best wishes, Sebastian
  • How can I create a custom Xpresso data type?

    c++
    5
    0 Votes
    5 Posts
    1k Views
    C
    Sorry about that, I'd noticed that the API was literally wired up to return the value from GetId() inside GetValueId() by default, so I figured that was answer enough... though I suppose that's kinda why I was asking in the first place- I wasn't sure what sort of situation would require two separate IDs. Thanks for your response though, that certainly clears up why there's two different functions to handle that. -CMPX
  • Sample the color of a vertex

    Moved r20 c++
    5
    0 Votes
    5 Posts
    1k Views
    R
    It seems quite simple, reading your code. However, that is python and I'm doing it in c++. I was trying to attach the old code I was using, but the uploader only allows for images. However, I'm now trying to make more generic, by internally baking the material, as it allows for more complex material assignments to objects. I'm still struggling but I will try to solve it myself, before coming back here
  • Frame all

    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
  • MCOMMAND_JOIN issue

    python
    10
    0 Votes
    10 Posts
    3k 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
    684 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
    1k Views
    R
    Very cool, thx alot Sebastian rownn
  • Deformer update and Fields

    c++ r20 windows macos
    2
    0 Votes
    2 Posts
    819 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
    1k Views
    O
    Thank you @m_adam It works fine
  • Run Plugin Last

    python r19
    3
    1
    0 Votes
    3 Posts
    840 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
    524 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
    482 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
    600 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
    800 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
    751 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
    967 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