Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Recent
    • Tags
    • Users
    • Register
    • Login

    Sub materials links and undo

    Scheduled Pinned Locked Moved Cinema 4D SDK
    c++windowss26
    5 Posts 2 Posters 58 Views 1 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D Offline
      DronKozy
      last edited by

      Hi!

      I am working on a material plugin (MaterialData).

      Some materials may have links to other materials via BaseContainer links.

      If I change linked materials, I want to update material preview of dependent materials.
      For now I am catching MSG_UPDATE message in the linked materials and searching for all depended materials in the document and call

      bm->Update(true, true);
      bm->Message(MSG_UPDATE);
      bm->SetDirty(DIRTYFLAGS::ALL);
      EventAdd();

      It works well until a user press undo.

      In this case MSG_UPDATE message is not sent, only MSG_CHANGE. And even if I use this message to update the depended materials, their BaseContainer links are pointing to old materials (before undo).

      How can I update all dependent materials in case of undo case?

      Thank you

      ferdinandF 1 Reply Last reply Reply Quote 0
      • D Offline
        DronKozy
        last edited by

        Based on responses I guess I asked some nonsense.

        Let me ask the question in a different way.

        I have two BaseMaterials - Material_1 and Material_2.

        Material_1 has a link to Material_2 in it's BaseContainer.

        If I edit Material_2 and then press undo, it gets replaced with its copy, and Material_1 link is updated with a new Material_2.

        Is there any message/notification regarding such link update?

        Thank you.

        1 Reply Last reply Reply Quote 0
        • ferdinandF Offline
          ferdinand @DronKozy
          last edited by ferdinand

          Hello @DronKozy,

          Welcome to the Maxon developers forum and its community, it is great to have you with us!

          Getting Started

          Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules.

          • Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment.
          • Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support.
          • Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads.

          It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: How to Ask Questions.

          About your First Question

          I am afraid there is no really good way to do what you want to do. Without example code, I also have to somewhat guess what is going on. As lined out in our support procedures, we recommend to always accompany questions with compileable code.

          I it is a bit fuzzy to me what you are doing, please tell me when I got it wrong. You have a BaseMaterial implementation which itself has LINK parameters which link to other materials. You now want to update MATPREVIEW parameter manually when your dependencies update.

          Tracking Changes

          Cinema generally follows an opt-out and not an opt-in update/message model. E.g., all objects get their GetVirtualObjects method called on each scene update, and it is then up to the object to decide if they actually want to update or just keep using their existing cache.

          The evaluation of materials happens at render time, so there is no direct function which is called or message which is sent to your plugin when something in the scene is being updated. The messages you are using somewhat go into that direction, but you misunderstood a bit their purpose. MSG_UPDATE is sent when an external entity wants to inform a node that it modified dependent data and that the node should update its internal data (outside of the general scene state rebuild). It is not a message that is being sent each time the node has been updated. I could for example get a point object, modify its points, and then not send that message and that would be totally valid code. The object would only update once Cinema 4D reevaluates the object on its own, but sometimes this is desirable. For user interactions, Cinema 4D will usually send this message, but its purpose is still a bit different from what you think it is. The same goes for MSG_CHANGE.

          The way to track changes in Cinema 4D, is the dirty system found on C4Datom. Cinema will usually automatically entail updates when the dirtiness of something changed, e.g., when a user changed the parameters of a node. The problem is that for LINK parameters (and also shader links), changes to the linked node do not count towards the data dirtiness of the node. Or in other words, Cinema does not consider a node A to be changed when the node B changed to which A links. For something like objects this is not really a problem due to the out-out update model, for material previews this means you can get event starved. The video below demonstrates the effect.

          Well, how do I solve this?

          What you do - a material that links other materials and in some shape or form drives its own material preview updates - is simply not intended. So, we have to get a bit creative.

          Piggybacking on other messages

          Just hook into a message that is being sent all the time. Objects and tags for example receive MSG_GETREALCAMERADATA and MSG_GETCUSTOMICON_SETTINGS each time a scene update ran. But I think you will not get these messages in a BaseMaterial. As I said, there is a good chance that you get event starved in a material. I would put a print statement into you message function, printing out the message ID, and then just start interacting with the scene, adding a cube, changing your linked material. To see if anything sticks to the wall, if there is a message ID you can piggy back on.

          Event Notifications

          ⚠ Event notifications are private for a reason. You can easily crash Cinema 4D with them when misused. The type of event notifications we use here, message notifications, are however relatively harmless.

          An alternative could be cinema::AddEventNotification. With event notifications, you can hook into the message stream of other nodes among other things. So, the idea would be:

          1. In your MyMaterialData::Message, listen for MSG_DESCRIPTION_POSTSETPARAMETER, to catch the moment when the user sets a new linked material (which will count as an update for your material).
          2. Then call myMaterialNode->AddEventNotification(materialThatHasBeenSet, NOTIFY_EVENT::MESSAGE, NOTIFY_EVENT_FLAG::NONE, nullptr);
          3. In your MyMaterialData::Message, listen for MSG_NOTIFY_EVENT and then do something like this:
          if (type == MSG_NOTIFY_EVENT && data)
          {
              const NotifyEventData* const notifyData = (NotifyEventData*)data;
              if (notifyData->eventid == NOTIFY_EVENT::MESSAGE && notifyData->event_data)
              {
                  NotifyEventMsg* messageData = (NotifyEventMsg*)notifyData->event_data;
          
                  // Now we are basically inside the ::Message function of the linked material #materialThatHasBeenSet. We could 
                  // for example react to a parameter change.
                  if (messageData->msg_id == MSG_DESCRIPTION_POSTSETPARAMETER)
                  {
                      // Do something when the linked material changed
                  }
              }
          }
          

          All in all, this is not a trivial problem to solve. When you run into more issues, please provide a minimal reproducible example code, so we can help you better.

          Cheers,
          Ferdinand

          MAXON SDK Specialist
          developers.maxon.net

          1 Reply Last reply Reply Quote 0
          • D Offline
            DronKozy
            last edited by

            Hi Ferdinand

            Thank you a lot for the reply.

            I am working on a render plugin (FStormRender) for C4D.
            Cinema 4D environment is new for me (after 3ds max), but I am slowly adapting.

            The biggest challenge is how to organize materials/shaders node system.
            I'm trying to choose between a selfmade node system like Corona/Octane and Cinema 4d native one like RedShift.

            Corona/Octane way looks more flexible, where you can connect any materials/textures to any pins (just avoid loop connections), but not native for Cinema 4D, and as you mention, it requires some creativity.

            https://www.facebook.com/groups/FStormGroup/posts/3898598533769869/?__cft__[0]=AZZugQpbOWJ_AdMpyuHPFG_JdGzv7CGcFlz0RwNa4unC0f8gL0N9kP2ZTukclDy3O6uZVUBQrUqp5ll-84Ih8NPf3OhSEe1Xy8tVcdiGzNYB6p1xxebpa61zhal3jAbze46bXzf_riRQrXxD9sTVNk1wiBYA_ZCW8_aqRisa6N-yPUSVE4di7cmaQt--1kvKQ3AmpPF9nINgsCkI2vBO5BZn&__tn__=%2CO%2CP-R

            ferdinandF 1 Reply Last reply Reply Quote 0
            • ferdinandF Offline
              ferdinand @DronKozy
              last edited by

              @DronKozy

              Yeah, I got the general direction, that you are probably implementing a material mixer type of material/shader. When you implement a full render engine binding, you should go the event notification route, as I am sure you can then easily handle the (slight) complexity that comes with them.

              Regarding the architecture, in principle you can do with whatever you want. As Maxon employee I would of course recommend to use our Nodes API (what you call 'native'). The SDK contains both code examples and documentation about this. But this biggest flaw of the Nodes API is probably that it is not entirely non-trivial. But implementing a full node editor also requires a relatively high level of expertise about our APIs, although in different areas.

              Currently Redshift, Vray, Arnold, and CentiLeo use the Nodes API and all other render engines (Corona, Octane, Cycles, etc.) use either a completely custom system or the old Xpresso Nodes API.

              Cheers,
              Ferdinand

              PS: When you are developing a render engine binding, you might want to consider our Maxon Registered Developer Program.

              MAXON SDK Specialist
              developers.maxon.net

              1 Reply Last reply Reply Quote 0
              • First post
                Last post