Navigation

    • Register
    • Login
    • Search
    • Categories
    1. Home
    2. C4DS
    3. Topics
    C
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    Topics created by C4DS

    • C

      UNSOLVED Reverse iterators, how to use them?
      Cinema 4D Development • r20 c++ r21 documentation • • C4DS  

      5
      0
      Votes
      5
      Posts
      44
      Views

      C

      I have "unsolved" the topic, as there still is an open point to be clarified. From the documentation: static maxon::details::ReverseIterable<ITERABLE> Reverse ( ITERABLE && iterable ) This function can be used in a range-based for loop to reverse the iteration such that it starts at the last element of the #iterable and moves towards the first element. The function can only be used for iterables which have suitable RBegin and REnd functions, and for C++ arrays. Apparently only the BaseArray can be used with the Iterable::Reserve. Nor HashSet, nor HashMap can be compiled using the reverse iterator, and probably because they have no RBegin() nor REnd(). Still, when I look at the documentation of BaseArray I don't see any RBegin(), nor REnd(). So how to know which collection type can be used with Iterable::Reverse ?
    • C

      UNSOLVED R21 BaseDraw::DrawPointArray draws squares versus circles in R20
      Cinema 4D Development • r20 c++ r21 issue limitation open bug • • C4DS  

      3
      0
      Votes
      3
      Posts
      36
      Views

      M

      hello, To keep you inform, I'm asking the devs and this is taking more time than expected. Sorry for the delay. Cheers, Manuel
    • C

      UNSOLVED R21 GeUserArea in docked GeDialog behaves differently
      Cinema 4D Development • c++ r21 classic api issue open bug • • C4DS  

      2
      0
      Votes
      2
      Posts
      36
      Views

      M

      Hi @C4DS thanks for reaching us. I can indeed confirm the issue. I've reached the development team about, I will let you know about any workaround. Cheers, Maxime.
    • C

      SOLVED DoUndo() issue when using loop selection, ring, ...
      Cinema 4D Development • r20 r19 r21 • • C4DS  

      2
      0
      Votes
      2
      Posts
      40
      Views

      M

      hello, this look awkward. I've opened a bug entry and foward this to the devs. It look like with the c++ API, the object is on a uninitialized state. Just this simple code will make your cinema4D hang (it enter an infinite loop). if (!doc->DoUndo()) { ApplicationOutput("Failed to DoUndo()"); return maxon::OK; } maxon::Int32 polyCnt = op->GetPolygonCount(); The most funny part is that using a python script (that does use the same c++ function) works. And that's why I've opened a bug entry. I'll come back when I got more information. Cheers, Manuel
    • C

      SOLVED CustomGUI gadget triggered by other gadget
      Cinema 4D Development • r20 c++ r19 r21 • • C4DS  

      10
      0
      Votes
      10
      Posts
      111
      Views

      C

      @m_magalhaes Thanks for your message-example. I hadn't quite understood it the first time, and needed a re-trigger. Inspired by your reply I came up with this solution instead. While it still is based on messaging, I preferred to use the SpecialEventAdd. This way, I could pass the type value via a "custom message". Obviously the customgui needs to be set up to react accordingly to this SpecialEventAdd, but this is what I sort of expected to already have been built in into the customgui, in order to be able to react to a trigger to update its additional attributes. Now we only can react to the attribute at constructor time. Maybe a request for a future update/addition? Note for others reading this topic: The code below is just a quick solution, having collected code from different sources and examples. It might obviously be optimized and commented in a better way. Also, make sure to register appropriate pluginIDs, as all ones used here are for demonstration purposes only. For the example below I followed a different route for testing purposes. Obviously it would lead me too far to provide a fully working plugin with NodeData etc ... As such, I wen for a simple CommandData with a GeDialog containing a set of radio buttons and a customgui gadget. The radio buttons allow to switch between black/white and r/g/b and c/m/y/k. With each selection the customgui displays a different set of options, showing a colored rectangle per option. The code is R20, but easily adjustable for R21. Main.cpp // ======================== // Cinema 4D C++ plugin // // PluginName: Test // Dummy "empty" plugin // ======================== // Main.cpp #include "c4d.h" // === Registered pluginIDs === #define MYCOMMAND_PLUGIN_ID 1000000 // DUMMY VALUE for demonstration purposes only !!! #define CUSTOMGUI_GADGET_ID 1000002 // DUMMY VALUE for demonstration purposes only !!! // a specific message ID to trigger the gadget to set its type #define CUSTOMGUI_GADGET_SETTYPEMSG_ID 100 // the gadget IDs #define RADIO_BUTTONS 10000 #define CUSTOMGUI_GADGET 10010 extern Bool RegisterGadget(); // ==================================== // GeDialog // ==================================== class MyDialog : public GeDialog { public: MyDialog(void) {} virtual ~MyDialog(void) {} virtual Bool CreateLayout(void); virtual Bool InitValues(void); virtual void DestroyWindow(void); virtual Bool Command(Int32 id, const BaseContainer& msg); virtual Int32 Message(const BaseContainer& msg, BaseContainer& result); }; Bool MyDialog::CreateLayout(void) { Bool res = GeDialog::CreateLayout(); // when using a GeLoadString(<string-id>) // strings need to be defined in the main string resources, not in the dialogs subfolder SetTitle("Test Dialog"_s); GroupBegin(0, BFH_SCALEFIT | BFV_SCALEFIT, 1, 0, ""_s, 0); { GroupBorderSpace(4, 4, 4, 4); GroupBegin(0, BFH_LEFT, 2, 0, maxon::String(), 0); { // 3 radio buttons vertically AddRadioGroup(RADIO_BUTTONS, BFV_SCALEFIT, 0, 3); AddChild(RADIO_BUTTONS, 2, "BW"_s); AddChild(RADIO_BUTTONS, 3, "RGB"_s); AddChild(RADIO_BUTTONS, 4, "CMYK"_s); // the custom gadget BaseContainer bc; AddCustomGui(CUSTOMGUI_GADGET, CUSTOMGUI_GADGET_ID, String(), 0, 0, 0, bc); } GroupEnd(); } GroupEnd(); return res; } Bool MyDialog::InitValues(void) { // first call the parent instance if (!GeDialog::InitValues()) return false; // do our thing ... Int32 typevalue = 2; SetInt32(RADIO_BUTTONS, typevalue); // set default to black and white // and inform the gadget about it SpecialEventAdd(CUSTOMGUI_GADGET_ID, CUSTOMGUI_GADGET_SETTYPEMSG_ID, typevalue); return true; } void MyDialog::DestroyWindow(void) {} Bool MyDialog::Command(Int32 id, const BaseContainer& msg) { if (id == RADIO_BUTTONS) { Int32 typevalue; GetInt32(RADIO_BUTTONS, typevalue); // send this to the customgui gadget to update its representation, // using an EventAdd will trigger a "regular" EVMSG_CHANGE // but we prefer to provide a SpecialEventAdd, as such we: // 1. avoid that the gadget is triggered by every EVMSG_CHANGE // 2. allow to specify a specific value to change the type to //EventAdd(); SpecialEventAdd(CUSTOMGUI_GADGET_ID, CUSTOMGUI_GADGET_SETTYPEMSG_ID, typevalue); } return true; } Int32 MyDialog::Message(const BaseContainer& msg, BaseContainer& result) { return GeDialog::Message(msg, result); } // ==================================== // CommandData // ==================================== class MyCommand : public CommandData { INSTANCEOF(MyCommand, CommandData) public: MyDialog dlg; public: virtual Bool Execute(BaseDocument* doc); }; Bool MyCommand::Execute(BaseDocument* doc) { if (dlg.IsOpen() == false) dlg.Open(DLG_TYPE::ASYNC, MYCOMMAND_PLUGIN_ID, -1, -1, 300, 200, 0); return true; } Bool RegisterMyCommand(void) { return RegisterCommandPlugin(MYCOMMAND_PLUGIN_ID, "Test"_s, 0, AutoBitmap("icon.png"_s), "Test"_s, NewObjClear(MyCommand)); } // ==================================== // Plugin Main // ==================================== Bool PluginStart(void) { ApplicationOutput("Test"_s); RegisterMyCommand(); RegisterGadget(); return true; } void PluginEnd(void) { } Bool PluginMessage(Int32 id, void * data) { switch (id) { case C4DPL_INIT_SYS: if (!g_resource.Init()) return false; return true; case C4DMSG_PRIORITY: return true; case C4DPL_BUILDMENU: break; case C4DPL_ENDACTIVITY: return true; } return false; } CustomGUI_Gadget.cpp // CustomGUI_Gadget.cpp // The custom gadget is a sort of horizontal graphical radio button group // the number of buttons is dependent the gadget type // type = 0 -> not initialized, no buttons // type = 2 has 2 buttons (black and white) // type = 3 has 3 buttons (red, green, blue) // type = 4 has 4 buttons (cyan, magenta, yellow, black) #include "c4d.h" #include "lib_clipmap.h" const Int32 kItemSize = 30; // the size of each "button" // === Registered pluginIDs === #define CUSTOMGUI_GADGET_ID 1000002 // DUMMY VALUE for demonstration purposes only !!! #define CUSTOMGUI_GADGET_ATTRIBUTE_ID 1000003 // DUMMY VALUE for demonstration purposes only !!! #define USERAREA_ID 10001 // The ID of the UserArea GUI element. // a specific message ID to trigger the gadget to set its type #define CUSTOMGUI_GADGET_SETTYPEMSG_ID 100 //--------------------------- // The user area used to display the custom datatype //--------------------------- class GadgetUserArea : public GeUserArea { public: GadgetUserArea(); virtual ~GadgetUserArea(); virtual Bool Init(); virtual Bool InitValues(); virtual Bool GetMinSize(Int32& w, Int32& h); virtual void DrawMsg(Int32 x1, Int32 y1, Int32 x2, Int32 y2, const BaseContainer& msg); virtual Bool InputEvent(const BaseContainer& msg); Int32 mSelection; Int32 mType; Vector bw[2]; Vector rgb[3]; Vector cmyk[4]; // use a GeClipMap for drawing AutoAlloc<GeClipMap> mClipmap; }; GadgetUserArea::GadgetUserArea() { mSelection = 0; mType = 0; } GadgetUserArea::~GadgetUserArea() { } Bool GadgetUserArea::Init() { bw[0] = Vector(0); bw[1] = Vector(255); rgb[0] = Vector(255, 0, 0); rgb[1] = Vector(0, 255, 0); rgb[2] = Vector(0, 0, 255); cmyk[0] = Vector(0, 255, 255); cmyk[1] = Vector(255, 0, 255); cmyk[2] = Vector(255, 255, 0); cmyk[3] = Vector(0); return true; } Bool GadgetUserArea::InitValues() { return true; } Bool GadgetUserArea::GetMinSize(Int32& w, Int32& h) { w = kItemSize * 4; h = kItemSize; return true; } void GadgetUserArea::DrawMsg(Int32 x1, Int32 y1, Int32 x2, Int32 y2, const BaseContainer& msg) { OffScreenOn(); if (!mClipmap) return; const Int32 w = GetWidth(); const Int32 h = GetHeight(); mClipmap->Init(w, h, 32); mClipmap->BeginDraw(); // background Int32 r, g, b; GetColorRGB(COLOR_BG, r, g, b); mClipmap->SetColor(r, g, b, 255); mClipmap->FillRect(x1, y1, x2, y2); Vector color; if (mType != 0) { // draw the possible options as background, // then draw the current selected option on top switch (mType) { case 2: // black and white { for (Int32 col = 0; col < 2; ++col) { color = bw[col]; mClipmap->SetColor(SAFEINT32(color.x), SAFEINT32(color.y), SAFEINT32(color.z), 255); Int32 x = col * kItemSize; mClipmap->FillRect(x + 2, 2, x + kItemSize - 2, kItemSize - 2); } break; } case 3: // RGB { for (Int32 col = 0; col < 3; ++col) { color = rgb[col]; mClipmap->SetColor(SAFEINT32(color.x), SAFEINT32(color.y), SAFEINT32(color.z), 255); Int32 x = col * kItemSize; mClipmap->FillRect(x + 2, 2, x + kItemSize - 2, kItemSize - 2); } break; } case 4: // CMYK { for (Int32 col = 0; col < 4; ++col) { color = cmyk[col]; mClipmap->SetColor(SAFEINT32(color.x), SAFEINT32(color.y), SAFEINT32(color.z), 255); Int32 x = col * kItemSize; mClipmap->FillRect(x + 2, 2, x + kItemSize - 2, kItemSize - 2); } break; } } if (mSelection >= 0) { // orange "selection" color GetColorRGB(COLOR_TEXTFOCUS, r, g, b); mClipmap->SetColor(r, g, b, 255); Int32 x = mSelection * kItemSize; mClipmap->Rect(x, 0, x + kItemSize, kItemSize); mClipmap->Rect(x + 1, 1, x + kItemSize - 1, kItemSize - 1); } } mClipmap->EndDraw(); DrawBitmap(mClipmap->GetBitmap(), 0, 0, w, h, 0, 0, w, h, BMP_ALLOWALPHA); } Bool GadgetUserArea::InputEvent(const BaseContainer& msg) { // check the input device switch (msg.GetInt32(BFM_INPUT_DEVICE)) { // some mouse interaction case BFM_INPUT_MOUSE: { // get the cursor position Int32 mx = msg.GetInt32(BFM_INPUT_X); Int32 my = msg.GetInt32(BFM_INPUT_Y); Global2Local(&mx, &my); // Note that the origin of a GeUserArea is upperleft // (which is equal to the 4th quadrant of cartesian coordinate system) mSelection = mx / kItemSize; // inform the parent that the data has changed BaseContainer m(BFM_ACTION); m.SetInt32(BFM_ACTION_ID, GetId()); m.SetData(BFM_ACTION_VALUE, mSelection); SendParentMessage(m); //Redraw(); return true; } } return false; } //---------------------------------------------------------------------------------------- // A custom GUI to display the ReferencePoint //---------------------------------------------------------------------------------------- class iGadget : public iCustomGui { INSTANCEOF(iGadget, iCustomGui) private: // The current tristate. Bool mTristate; // instance of the userarea to display the ReferencePointer GadgetUserArea mUA; public: iGadget(const BaseContainer &settings, CUSTOMGUIPLUGIN *plugin); virtual Bool CreateLayout(); virtual Bool InitValues(); virtual Bool Command(Int32 id, const BaseContainer &msg); virtual Int32 Message(const BaseContainer &msg, BaseContainer &result); virtual Bool SetData(const TriState<GeData> &tristate); virtual TriState<GeData> GetData(); virtual void CustomGuiRedraw(); }; iGadget::iGadget(const BaseContainer &settings, CUSTOMGUIPLUGIN *plugin) : iCustomGui(settings, plugin) { mUA.mType = settings.GetInt32(CUSTOMGUI_GADGET_ATTRIBUTE_ID); //mUA.mType = mType; // pass along the type to the userarea // Defining default values mTristate = false; }; Bool iGadget::CreateLayout() { GroupBegin(1000, BFH_SCALEFIT | BFV_FIT, 1, 1, String(), 0); { GroupSpace(0, 0); // Attach the User Area to the custom GUI AddUserArea(USERAREA_ID, BFH_SCALEFIT, 0, 0); AttachUserArea(mUA, USERAREA_ID); } GroupEnd(); return SUPER::CreateLayout(); }; Bool iGadget::InitValues() { // The data and it's tristate are handled automatically. this->SetInt32(USERAREA_ID, mUA.mSelection, mTristate); return true; }; Bool iGadget::Command(Int32 id, const BaseContainer &msg) { switch (id) { case USERAREA_ID: { // The Gadget was changed. // Update GUI this->InitValues(); // Send message to parent object to update the parameter value. BaseContainer m(BFM_ACTION); m.SetInt32(BFM_ACTION_ID, GetId()); m.SetData(BFM_ACTION_VALUE, msg.GetInt32(BFM_ACTION_VALUE)); SendParentMessage(m); return true; break; } } return SUPER::Command(id, msg); } Int32 iGadget::Message(const BaseContainer &msg, BaseContainer &result) { switch (msg.GetId()) { case BFM_CORE_MESSAGE: { if (!CheckCoreMessage(msg)) { break; } else { if (msg.GetInt32(BFM_CORE_ID) == EVMSG_CHANGE) { // get the parameter and update the userarea if needed //ApplicationOutput("iGadget::Message() detected EVMSG_CHANGE"); } if (msg.GetInt32(BFM_CORE_ID) == CUSTOMGUI_GADGET_ID) { UInt par1 = (UInt)msg.GetVoid(BFM_CORE_PAR1); UInt par2 = (UInt)msg.GetVoid(BFM_CORE_PAR2); //ApplicationOutput("iGadget::Message() detected a SpecialEventAdd @ @", par1, par2); if (par1 == CUSTOMGUI_GADGET_SETTYPEMSG_ID) { // The SpecialEventAdd which is responsable for this message // uses the CUSTOMGUI_GADGET_ID as message ID, // a specific value CUSTOMGUI_GADGET_SETTYPEMSG_ID as first parameter to indicate we want to set the gadget's type, // and finally the type value as the second parameter // -> SpecialEventAdd(CUSTOMGUI_GADGET_ID, CUSTOMGUI_GADGET_SETTYPEMSG_ID, typevalue); // accept the type change for the gadget and trigger an update // (see iGadget::Command, where user interaction in the userarea triggers an update) mUA.mType = (Int32)par2; // reset the selection to avoid "out of range" depending the type mUA.mSelection = 0; CustomGuiRedraw(); } } } break; } } return SUPER::Message(msg, result); } Bool iGadget::SetData(const TriState<GeData> &tristate) { // The data is changed from the outside. mUA.mSelection = tristate.GetValue().GetInt32(); mTristate = tristate.GetTri(); this->InitValues(); // need to update the userarea this->mUA.Redraw(); return true; }; TriState<GeData> iGadget::GetData() { // The data is requested from the outside. TriState<GeData> tri; tri.Add(mUA.mSelection); return tri; }; void iGadget::CustomGuiRedraw() { this->mUA.Redraw(); } //---------------------------------------------------------------------------------------- // This CustomGuiData class registers a new custom GUI for the ReferencePoint datatype. //---------------------------------------------------------------------------------------- class Gadget : public CustomGuiData { public: virtual Int32 GetId(); virtual CDialog* Alloc(const BaseContainer& settings); virtual void Free(CDialog* dlg, void* userdata); virtual const Char* GetResourceSym(); virtual CustomProperty* GetProperties(); virtual Int32 GetResourceDataType(Int32*& table); }; static Int32 g_stringtable[] = { DTYPE_LONG }; //< This array defines the applicable datatypes. static CustomProperty g_GadgetType[] = { { CUSTOMTYPE::LONG, CUSTOMGUI_GADGET_ATTRIBUTE_ID, "TYPE" }, { CUSTOMTYPE::END, 0, "" } }; Int32 Gadget::GetId() { return CUSTOMGUI_GADGET_ID; }; CDialog* Gadget::Alloc(const BaseContainer& settings) { // Creates and returns a new sub-dialog. iGadget* dlg = NewObjClear(iGadget, settings, GetPlugin()); if (!dlg) return nullptr; CDialog *cdlg = dlg->Get(); if (!cdlg) return nullptr; return cdlg; }; void Gadget::Free(CDialog* dlg, void* userdata) { // Destroys the given subdialog. if (!dlg || !userdata) return; iGadget* sub = static_cast<iGadget*>(userdata); DeleteObj(sub); }; const Char* Gadget::GetResourceSym() { // Returns the resource symbol. This symbol can be used in resource files in combination with "CUSTOMGUI". return "TYPE"; }; CustomProperty* Gadget::GetProperties() { // This method can return a pointer to a data structure holding various additional properties. return g_GadgetType; }; Int32 Gadget::GetResourceDataType(Int32*& table) { // Returns the applicable datatypes defined in the stringtable array. table = g_stringtable; return sizeof(g_stringtable) / sizeof(Int32); }; Bool RegisterGadget() { // only register the custom GUI when not already registered by another plugin if (IsLibraryInstalled(CUSTOMGUI_GADGET_ID)) return true; static BaseCustomGuiLib myGadgetLib; ClearMem(&myGadgetLib, sizeof(myGadgetLib)); FillBaseCustomGui(myGadgetLib); if (!InstallLibrary(CUSTOMGUI_GADGET_ID, &myGadgetLib, 1000, sizeof(myGadgetLib))) return false; if (!RegisterCustomGuiPlugin(/*GeLoadString(IDS_CUSTOMGUISTRING)*/"Gadget"_s, 0, NewObjClear(Gadget))) return false; return true; } With this I guess the topic can be closed. But feel free to provide further comments if I overlooked something.
    • C

      SOLVED plugins folder, now you see me, now you don't.
      General Programming & Plugin Discussions • r20 r21 general notes • • C4DS  

      16
      0
      Votes
      16
      Posts
      473
      Views

      M

      hello, I confirm it's strange. Could you use the g_console=true and g_logfile=d:\logfile.txt as said in this page (both will contain the same lines) Send us the logfile (sdk_support@maxon.net) if you don't want to share that in public. Cheers, Manuel
    • C

      SOLVED R21 CommandData with option - not working on macOS
      Cinema 4D Development • c++ r21 issue plugin migration apple macos • • C4DS  

      8
      0
      Votes
      8
      Posts
      114
      Views

      Hi Daniel, for the time being I see three options: run Cinema with its own menu bar; drag out the menù containing your CommandData in order to make the cogwheel appear use keyboard modifiers: Alt + LMB -> lunches CommandData::Execute() LMB -> lunches CommandData::ExecuteOptionID() Best, Riccardo
    • C

      UNSOLVED First R21 plugin ... memory leaks and dangling references
      Cinema 4D Development • c++ r21 issue • • C4DS  

      13
      0
      Votes
      13
      Posts
      185
      Views

      C

      @r_gigante Thanks for the feedback. FYI, this wasn't only with R21, had the same issue with R20, since the "old laptop" was restricted to R20 only. But I guess no updates will follow for R20 anymore.
    • C

      SOLVED R21 plugin licensing
      Cinema 4D Development • c++ r21 plugin migration documentation licensing • • C4DS  

      2
      0
      Votes
      2
      Posts
      174
      Views

      S

      Hello, as far as I know the licenseID is a temporary session ID that is only used internally. It has no use for third party developers. The hardware ID is based on the corresponding OS functions. So the hardware ID is the same as long the OS thinks the system is the same. Please also notice that, for internal reasons, the format of any of these IDs may change in future releases. Is it up to the studios to decide how they want to license their software. A typical use case could be that a studio creates a single account that is shared in the company. So there would be one user ID for the whole studio. It is up to you to decide if you want to bind your plugin to that user ID or a system ID. best wishes, Sebastian
    • C

      SOLVED Datastorage unique and ordered
      Cinema 4D Development • r20 c++ r19 classic api • • C4DS  

      8
      0
      Votes
      8
      Posts
      99
      Views

      M

      hello, It's not related to Iterator. This simple example also complain about the default constructor. #include <iostream> class MYINT { public: MYINT(int inInt) { _myint = inInt; }; private: int _myint; }; int main() { MYINT myint; system("pause"); return 0; } It should say 'hey i don't have any constructor with no parameters". But if you give him something to initialize with it understand. MYINT myint = MYINT(10); MYINT myOtherInt = 10; MYINT myThirdInt(10); all this will end with _myint = 10; Cheers Manuel
    • C

      SOLVED HashMap with BaseArray as value
      Cinema 4D Development • c++ r19 classic api • • C4DS  

      3
      0
      Votes
      3
      Posts
      133
      Views

      C

      @r_gigante Thanks for the headsup about FindOrCreateEntry. Since Put does use that method internally, I didn't even consider about trying to use it, as I simply assumed it would have the same issue. Guess I was wrong about not trying it. Problem solved.
    • C

      SOLVED From edge to polygons
      Cinema 4D Development • r20 c++ r19 classic api • • C4DS  

      5
      0
      Votes
      5
      Posts
      226
      Views

      C

      @C4DS said in From edge to polygons: storing a pair of (4 * polygon + edge) values ... it will be. Thanks for the confirmation
    • C

      UNSOLVED BaseContainer and range-based loop
      Cinema 4D Development • r20 c++ r19 classic api • • C4DS  

      7
      0
      Votes
      7
      Posts
      276
      Views

      C

      @m_magalhaes Ah! However, I had preferred it was me who had overlooked these all those years. As this means I will still need to find a different solution for pre-R20 compatibility.
    • C

      SOLVED BaseContainer equality ... are you kidding me
      Cinema 4D Development • r20 c++ • • C4DS  

      10
      0
      Votes
      10
      Posts
      410
      Views

      M

      hello, oupss thanks i got the same warning and forgot to update the code here Cheers Manuel
    • C

      SOLVED Naming: plugin vs plugin
      Cinema 4D Development • feedback • • C4DS  

      5
      0
      Votes
      5
      Posts
      262
      Views

      Hi Daniel, thanks for sharing your further considerations. I see your points and maybe we should consider to update our documentation to reflect the notes above. I will discuss with the team and maybe we could come with a better introduction where the "plugin" term is used in a less generic meaning. Cheers, Riccardo
    • C

      SOLVED Reusing customGUI in different plugins
      Cinema 4D Development • r20 c++ r19 classic api • • C4DS  

      2
      0
      Votes
      2
      Posts
      152
      Views

      M

      hello, while RegisterCustomGuiPlugin could be called in all your plugins, the issue is that you will have a message in the console indicating that the id is already used / in conflict. So you can check, as you stated, if the library is already installed with IsLibraryInstalled or using FindPlugin and only register and install the library if you find nothing. The load order here should not be a problem as all modules should be loaded before you need to call anything related to the UI. Instead of FindPlugin,for CUSTOMDATATYPEPLUGIN or RESOURCEDATATYPEPLUGIN you can use FindCustomDataTypePlugin or FindResourceDataTypePlugin Cheers Manuel
    • C

      SOLVED Ignore missing plugins - NodeData
      Cinema 4D Development • r20 c++ r19 classic api • • C4DS  

      8
      0
      Votes
      8
      Posts
      335
      Views

      S

      Hello, I don't think you have to do anything else in Write(). WriteObject() should only write the nodes that you inserted into the list head. If you don't add outdated nodes to your list head, they are not written into the file. best wishes, Sebastian
    • C

      SOLVED Howto trigger CommandData::GetState()
      Cinema 4D Development • r20 c++ classic api • • C4DS  

      5
      0
      Votes
      5
      Posts
      232
      Views

      C

      I had noticed that the EVMSG_CHANGE was actually triggering the GetState of my CommandDatas, but I was wondering if a different approach was available. Still, I am OK with the EventAdd() solution. Thanks.
    • C

      SOLVED IsEqual not defined
      Cinema 4D Development • r20 c++ • • C4DS  

      3
      0
      Votes
      3
      Posts
      137
      Views

      C

      @m_magalhaes said in IsEqual not defined: MAXON_OPERATOR_EQUALITY(Int32Pair, a, b); Thanks, didn't know about the MAXON_OPERATOR_EQUALITY. Very handy indeed. However, I had already tried providing an equality operator in my Int32Pair class, as such: Bool operator == (const Int32Pair& other) { return (a == other.a) && (b == other.b); } But that still resulted in the "IsEqual not defined" compiler error. The macro, however, is working fine. Looking further at my implementation of operator==, I now notice I didn't declare it as a const method. Adding the const does get rid of the compiler error. Oh boy! Overlooked a minor "typo", with major consequences. Again, thanks for the macro.
    • C

      SOLVED modulo - behind the scenes
      Cinema 4D Development • r20 c++ r19 • • C4DS  

      3
      0
      Votes
      3
      Posts
      168
      Views

      C

      Thanks for the info.