• Overlaying icons (like Alembic)

    Cinema 4D SDK r20 r21 s22 c++ classic api
    9
    1
    0 Votes
    9 Posts
    1k Views
    fwilleke80F
    OK, I got it. Once it's all figured out, the solution seems laughably simple. In case anybody else needs to maintain R20 compatibility and wants to use custom icon overlays, here's a solution: In MyObject class declaration: (R20 code) class MyObject : public ObjectData { INSTANCEOF(MyObject, ObjectData); // ... private: #if API_VERSION < 21000 BaseBitmap *_customIcon; ///< Used to store a node's custom icon in R20 #endif }; public: #if API_VERSION < 21000 MyObject() : _customIcon(nullptr) { } ~ MyObject() { if (_customIcon) BaseBitmap::Free(_customIcon); } #endif In MyObject::Message(): (R20 code) const BaseContainer &dataRef = op->GetDataInstanceRef(); // // 1. Copy default icon into customIcon // // Load default icon IconData defaultIconData; if (!GetIcon(node->GetType(), &defaultIconData)) return false; // Free _customIcon if it has been allocated before, because // it will now receive the pointer to a newly allocated BaseBitmap. if (_customIcon) BaseBitmap::Free(_customIcon); // Get the actual bitmap that is our icon _customIcon = defaultIconData.GetClonePart(); if (!_customIcon) return false; // // 2. Blit overlay into customIcon // // Load overlay icon IconData overlayIcon; const Int32 overlayIconId = MyFunctionToGetTheIconId(); if (overlayIconId == NOTOK) return false; const Bool overlayIconloaded = GetIcon(overlayIconId, &overlayIcon); if (overlayIconloaded) { BlitOverlayBitmap(overlayIcon.bmp, _customIcon, overlayIcon.x, overlayIcon.y, overlayIcon.w, overlayIcon.h, 32, 32); // // 3. Set cid->dat to use customIcon // cid->dat->bmp = _customIcon; cid->dat->x = 0; cid->dat->y = 0; cid->dat->w = _customIcon->GetBw(); cid->dat->h = _customIcon->GetBh(); cid->filled = true; } And BlitOverlayBitmap(), a variation of your BlitOverlayIcon(): void BlitOverlayBitmap(BaseBitmap *overlay, BaseBitmap *dest, Int32 x, Int32 y, Int32 bw, Int32 bh, Int32 xOffset, Int32 yOffset) { if (!overlay || !dest) return; BaseBitmap *overlayAlpha = overlay->GetInternalChannel(); BaseBitmap *destAlpha = dest->GetInternalChannel(); const Int32 destW = dest->GetBw(); const Int32 destH = dest->GetBh(); if (bw > destW) bw = destW; if (bh + yOffset > destH) bh = destH - yOffset; if (bw + xOffset > destW) bw = destW - xOffset; UInt16 aa, a, rr, r, gg, g, bb, b; aa = a = rr = r = gg = g = bb = b = 0xff; for (Int32 py = 0; py < bh; py++) { for (Int32 px = 0; px < bw; px++) { // get color and alpha from overlay icon overlay->GetPixel(x + px, y + py, &r, &g, &b); overlay->GetAlphaPixel(overlayAlpha, x + px, y + py, &a); // get color and alpha from background icon if available dest->GetPixel(px + xOffset, py + yOffset, &rr, &gg, &bb); if (destAlpha) { dest->GetAlphaPixel(destAlpha, px + xOffset, py + yOffset, &aa); } // blend overlay color against existing icon background color Float blend = a / 255.0; dest->SetPixel(px + xOffset, py + yOffset, (Int32)Blend(rr, r, blend), (Int32)Blend(gg, g, blend), (Int32)Blend(bb, b, blend)); // use only the overlay alpha if the opacity is higher to keep the original icon complete // and only in case the background has an alpha at all if (destAlpha && aa < a) { dest->SetAlphaPixel(destAlpha, px + xOffset, py + yOffset, a); } } } } Thanks for patience & support! Cheers, Frank
  • Changing camera/take/render setting in the render queue

    Cinema 4D SDK
    3
    0 Votes
    3 Posts
    1k Views
    B
    @m_adam Thanks. I gave that a shot, but unfortunately, it's still adding multiple copies of the same camera. Am I doing something wrong? docs = c4d.documents doc = docs.GetActiveDocument() cams = getSelectedCameras(doc.GetActiveObjects(0)) path = doc.GetDocumentPath() cFile = path + '\\' + fName queue = docs.GetBatchRender() queue.Open() base = doc.GetActiveBaseDraw() for cam in cams: docs.LoadDocument(cFile, c4d.SCENEFILTER_OBJECTS | c4d.SCENEFILTER_MATERIALS) base.SetSceneCamera(cam) docs.SaveDocument(doc, cFile, c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST, c4d.FORMAT_C4DEXPORT) queue.AddFile(cFile, queue.GetElementCount())
  • Encrypted Loggers or Custom LoggerTypes?

    Cinema 4D SDK r20 r21 s22 c++
    7
    0 Votes
    7 Posts
    783 Views
    ManuelM
    hi, I've asked the devs. We should have everything needed to do what you want. Encrypting file is builtin with maxon::Url scheme. There's already several algorithm, you just have to specify your CryptoKey. When you create a logger to a file (or it could be a web server), you attach it to a maxon::Url, it should be automatically encrypted. But that's not working and that's why I've asked the devs. I don't know if it's a limitation or a bug. What I wanted to do was create a maxon::LoggerType::EncryptedFile(), but I don't see how to do this. as i said, the encrypted part should be done by the maxon::Url (streaming) part Cheers, Manuel
  • TreeView Multiple Selection With LMB

    Moved Cinema 4D SDK
    13
    0 Votes
    13 Posts
    3k Views
    Danchyg1337D
    @m_adam Now i see the problem. Thanks alot for helping!
  • SDK for node based materials, status?

    Cinema 4D SDK r21 sdk
    3
    1 Votes
    3 Posts
    755 Views
    F
    @r_gigante said in SDK for node based materials, status?: With regard to your question, we confirm that at the moment there are no news concerning this topic but, again, we are aware of the relevance of the request and it will be delivered accordingly to our product development plan. Thanks! On a related note: Is there any statement from MAXON on the future of the old xpresso-style node system? We are looking to implement a node-system in our plugin, and since API for the new node system is not out yet we may consider using the legacy xpresso API instead. On the other hand, it would not be a good idea to invest resources in this if that part of the SDK might be deprecated and replaced with the new node system. I realize that you may not be able to provide much info on the roadmap here, but any information that you can give would be super helpful for making this decision! Cheers /Filip
  • What's the state of Ngons in Python?

    Cinema 4D SDK python classic api r21
    9
    0 Votes
    9 Posts
    2k Views
    CairynC
    @m_magalhaes said in What's the state of Ngons in Python?: About the bugs on the forum, we have introduce few month ago new tags "Bug report" and "Bug Fixed". We are also adding some tag in our bug database to retrieve faster the post on the forum. I know it's not perfect and sometimes we may forgot to add this tag on the first post of the thread. But it's better than nothing. Yeah, I'll try to use that in the future although it probably won't affect existing threads (a lot of valuable knowledge still resides in the "old forum" parts). @Cairyn said in What's the state of Ngons in Python?: Anyway, I don't think this issue is of huge interest as you said there's a replacement in the new kernel already, which will probably come with a diferent tesselation algorithm, so I present it here as a curiosity. Don't get me wrong, all modeling command have been migrated to the new modeling kernel. If you are using SendModelingCommand, it will use the new kernel. So what you see now in S22 and R23 (ok you will see in R23) IS the new kernel. There will be no better tesselation. I consider this as a bug. As a Perpetual user, I'm still on R21 (as tagged) so is this also the new kernel? AFAIK the new kernel has been working behind the API for a while now, being gradually introduced into the functionality, so it's possible that this bug still persists. I can't test it on a demo of S22 for you, as the current licensing does not allow me to install one. The new modeling kernel isn't exposed yet. But it is used. I understand, it's a bit confusing. We are moving Cinema4D to the new core. But as long as some part of Cinema4D are using the old system (object manager for exemple), the new core need to "translate" that to the classic API. (...) I hope it's clear. Sure, I have a few decades of programming under the belt. It's just a bit difficult as non-Maxon developer to see the details. Seeing only the API (and therefore the user-side of the translation layer), I can't always tell what the underlying data model really is; what's stored as attribute, what's calculated on the fly, what's internally cached for fast access, what's abstracted and what's plainly stored... I may make wrong assumptions on the internal workings. this look like a valid ngon but i will ask It probably is valid - I don't see a reason why it should be forbidden. I just notice that the tesselation algorithm tends to avoid such "inner polygons". That may not be intentional (based on a rule) though, but just a consequence of how the algorithm works. Thanks again, -- Cairyn --
  • 0 Votes
    6 Posts
    1k Views
    fwilleke80F
    It works like a charm! Thank you again! I was surprised at how little code was required. Sharing is caring. In case anyone needs it, here's the code: #include "ge_prepass.h" #include "c4d_general.h" #include "c4d_baselinkarray.h" #include "c4d_basedocument.h" /// /// \brief Registers observers and sends messages to them. /// class Observable { public: /// /// \brief Subscribes a new observer. /// /// \param[in] observer Pointer to an AtomGoal /// \param[in] doc The document that owns the AtomGoal /// /// \return A maxon error object if anything went wrong, otherwise maxon::OK /// maxon::Result<void> Subscribe(C4DAtomGoal *observer, BaseDocument *doc); /// /// \brief Unsubscribes an observer /// /// \param[in] observer Pointer to an AtomGoal that has previously been subscribed /// \param[in] doc The document that owns the AtomGoal /// void Unsubscribe(C4DAtomGoal *observer, BaseDocument *doc); /// /// \brief Sends a messages to all subscribed observers /// /// \param[in] type Message type /// \param[in] doc The document that owns the subscribed observers /// \param[in] data Optional message data /// void Message(Int32 type, BaseDocument *doc, void *data = nullptr) const; private: BaseLinkArray _observers; }; maxon::Result<void> Observable::Subscribe(C4DAtomGoal *observer, BaseDocument *doc) { if (!observer) return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Observer must not be nullptr!"_s); // Check if this observer is already registered const Int32 observerIndex = _observers.Find(observer, doc); if (observerIndex != NOTOK) return maxon::OK; // Register new observer if (!_observers.Append(observer)) { return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION, "Failed to add observer to the list!"_s); } return maxon::OK; } void Observable::Unsubscribe(C4DAtomGoal *observer, BaseDocument *doc) { if (observer && doc) { const Int32 observerIndex = _observers.Find(observer, doc); if (observerIndex != NOTOK) { _observers.Remove(observerIndex); } } } void Observable::Message(Int32 type, BaseDocument *doc, void *data) const { for (Int32 i = 0; i < _observers.GetCount(); ++i) { C4DAtomGoal *atom = _observers.GetIndex(i, doc); if (atom) { atom->Message(type, data); } } }
  • 0 Votes
    7 Posts
    1k Views
    CairynC
    yupyup, BaseSelect has no connection to the original object it actually selects from, not even in the cases where you get a pointer to the BaseSelect returned and change the selection directly through it. That's why we need the max parameter for SelectAll and ToggleAll -- the BaseSelect doesn't know what "all" even is. (Not GetLastElement()!) For GetRange() though, that reasoning does not apply. Now let's see whether I can crash C4D with inconsistent edge selections...
  • ToolPlugin Problems

    Cinema 4D SDK python s22 r21 r20 r19
    7
    2
    0 Votes
    7 Posts
    2k Views
    kbarK
    @gheyret great to hear! Looking forward to seeing what it is you are creating.
  • Customgui for ShaderLink

    Cinema 4D SDK maxon api r21
    4
    0 Votes
    4 Posts
    806 Views
    indexofrefractionI
    This is still missing in the Python SDK .....
  • Decoupling source from SDK project

    Cinema 4D SDK
    7
    0 Votes
    7 Posts
    1k Views
    F
    @kbar said in Decoupling source from SDK project: Since Maxon also updates the ProjectTool when a new version of C4D comes out and it may have new flags or optimazations and changes to the project structure for XCode and Visual Studio. From what I can tell it's pretty stable, also I don't mind what someone else thinks my compiler optimisation flags should be. Maintaining your own CMake version going forward for R20, R21, S22, RXX etc... would be a massive pain and just slow you down. Not as painful as you think it might be, also not as slow. Whatever floats your boat.
  • Best way to update objects after preference change?

    Cinema 4D SDK c++ r20 r21 s22
    7
    0 Votes
    7 Posts
    1k Views
    fwilleke80F
    Oh wait, I think I found a way. In case anybody else wants to know, here it is... In the PrefsDialogObject: Bool MyPrefsDialog::SetDParameter(GeListNode *node, const DescID &id,const GeData &t_data,DESCFLAGS_SET &flags) { BaseContainer* bc = MyPlugin::GetPreferences(); if (!bc) SUPER::SetDParameter(node, id, t_data, flags); switch (id[0].id) { // If PREFS_MYPLUGIN_SOMEVALUE was changed, store value and notify plugin objects in all open documents. case PREFS_MYPLUGIN_SOMEVALUE: bc->SetInt32(PREFS_MYPLUGIN_SOMEVALUE, t_data.GetInt32()); flags |= DESCFLAGS_SET::PARAM_SET; // Iterate open documents for (BaseDocument *doc = GetFirstDocument(); doc; doc = doc->GetNext()) { // Send broadcast message to each document, use unique ID doc->MultiMessage(MULTIMSG_ROUTE::BROADCAST, MyPlugin::UNIQUE_ID_PREFS, nullptr); } GeUpdateUI(); return true; } return SUPER::SetDParameter(node, id, t_data, flags); } And then, in the plugin object: Bool MyPluginObject::Message(GeListNode *node, Int32 type, void *data) { if (type == MyPlugin::UNIQUE_ID_PREFS) { GePrint("Aha! My prefs have changed!"_s); return true; } return SUPER::Message(node, type, data); }
  • 0 Votes
    4 Posts
    537 Views
    ferdinandF
    Hi, jeah, that is probably somewhat the reason. Although Python has true statically typed arrays, which also can be used to directly in-place manipulate C arrays (i.e. array.array), from what I understand it is quite cumbersome to achieve such linkage. This is probably the reason why Maxon does not bother in this case and others like for example vertex colors. Including these access points is still a bit puzzling though. Maybe they are somehow used internally? But I cannot think of a case where this would make sense. Cheers, zipit
  • C4D in VirtualBox... no viewport displayed

    Cinema 4D SDK windows r21 s22
    3
    0 Votes
    3 Posts
    610 Views
    fwilleke80F
    I guess VirtualBox is just not a good choice then. Damn. But thanks for the answer! Cheers, Frank
  • 0 Votes
    5 Posts
    679 Views
    B
    @m_magalhaes Thanks! It works as expected. So that's what you mean by UniformToNatural. Basically, even if the segment guides are not the same as spline points, it will conform to its overall shape.
  • Changing Face Normal's Direction?

    Cinema 4D SDK r21 python
    5
    0 Votes
    5 Posts
    1k Views
    ManuelM
    hi, everything have been said, nothing to add here Cheers, Manuel
  • 0 Votes
    3 Posts
    610 Views
    ManuelM
    hi, Since R20, arguments have been added, and the problem is coming from the last one def HeaderClick(self, root, userdata, lColID, lChannel, bDblClk, mouseX, mouseY, ua): I've opened a bug report Cheers, Manuel
  • Camera Position/Rotation to POS/DIR/UP Vectors

    Cinema 4D SDK r21 c++
    5
    0 Votes
    5 Posts
    1k Views
    N
    Hello Manuel, thanks for your input! I got it working correctly with the values you mentioned. Reading through the docs again I feel kinda dumb for not getting it right myself. Thanks to both you and zipit for your great help! Best Regards, Florian
  • Some attempts at nondestructive modeling

    Moved General Talk r21 python
    5
    1
    0 Votes
    5 Posts
    1k Views
    X
    Hi: After a trial run, the script was tested successfully. By setting the name suffix of Python Tag, the problem of repeated running of Tag can be solved. Taking c4d.DIRTYFLAGS_SELECT as an example, if the point, line, and surface selections change, it will execute, otherwise it won't. The Python script code is as follows: import c4d #e-mail: [email protected] def main(): Name = op.GetName() Objects = op.GetObject() Changed = Objects.GetDirty(c4d.DIRTYFLAGS_SELECT) Text = ["xit" + str(Changed)[-1]] if str(Name).count(Text[0][:-1]) != 0 : if str(Name).find(Text[0][:-1]) != str(Name).rfind(Text[0][:-1]) : if str(Name)[str(Name).rfind(Text[0][:-1]):] == Text[0] : if str(Name).find(Text[0][:-1]) <= 0: #Do not execute, exit the program. print ("Does not perform.") op.SetName(str(Text[0])) return else: #Do not execute, exit the program. op.SetName(str(Name)[:str(Name).find(Text[0][:-1])] + str(Text[0])) print ("Does not perform.") return else: if str(Name).find(Text[0][:-1]) <= 0: op.SetName(str(Text[0])) print ("Perform.") else: op.SetName(str(Name)[:str(Name).find(Text[0][:-1])] + str(Text[0])) print ("Perform.") else: if str(Name)[str(Name).rfind(Text[0][:-1]):] == Text[0] : #Do not execute, exit the program. print ("Does not perform.") return else: op.SetName(str(Name)[:str(Name).find(Text[0][:-1])] + str(Text[0])) print ("Perform.") else: print ("Perform.") op.SetName(str(Name) + str(Text[0])) print ("pass") #The next thing to execute.
  • Mute Object Animation

    Cinema 4D SDK r21 python
    5
    0 Votes
    5 Posts
    482 Views
    B
    @zipit Gotcha. Thanks for the reminder