Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware 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
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    id PluginMessage () when the scene loaded

    Cinema 4D SDK
    python sdk
    4
    12
    1.8k
    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.
    • A
      ac3 @C4DS
      last edited by

      @C4DS, Hi!
      it is very sad. I don't really want to rewrite the plugin from Python to C++ 😢

      1 Reply Last reply Reply Quote 0
      • A
        ac3
        last edited by

        @C4DS said in id PluginMessage () when the scene loaded:

        I don't think this will work for a Python plugin, but with C++ you can provide a SceneHook and use message MSG_DOCUMENTINFO_TYPE_LOAD

        Maybe there is another way to start the plugin automatically? Mb is not PluginMessage ()

        1 Reply Last reply Reply Quote 0
        • ManuelM
          Manuel
          last edited by Manuel

          hi,

          you can see in this thread that it's not possible with python.
          But maybe you can use another workflow. You can have another plugin asking for a directory, load every document on that directory, call your script that will work on the document, and close the document.

          You can only write the SceneHookData with c++ and that SceneHookData will call your python command so you don't need to rewrite it.

          Cheers,
          Manuel

          MAXON SDK Specialist

          MAXON Registered Developer

          A 2 Replies Last reply Reply Quote 0
          • A
            ac3 @Manuel
            last edited by ac3

            @m_magalhaes, Hi!
            Thanks for the answer, I will try this and answer later.

            1 Reply Last reply Reply Quote 0
            • A
              ac3 @Manuel
              last edited by

              You can only write the SceneHookData with c++ and that SceneHookData will call your python command so you don't need to rewrite it.

              Hi!
              Do you have examples of a plugin written with SceneHookData? I am more proficient in python than c ++ 😢

              1 Reply Last reply Reply Quote 0
              • A
                ac3
                last edited by

                @m_magalhaes, Hi, can you answer me? plz

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

                  Hi,

                  if my memory does not betray me, MSG_DOCUMENTINFO is being broadcasted to all nodes in the scene. So if you want to stay in Python, you could simply hijack a node type. One promising candidate could be PreferenceData, although I cannot guarantee that Cinema will also send document notifications to these nodes, since they are not part of a scene.

                  Cheers,
                  zipit

                  MAXON SDK Specialist
                  developers.maxon.net

                  1 Reply Last reply Reply Quote -1
                  • ManuelM
                    Manuel
                    last edited by

                    hi,
                    Sorry for the delay.

                    we have this example.
                    The most important is ou c++ documentation

                    you can see an example in the BaseDocument Manual

                    
                    class pc12835_scenehook : public SceneHookData
                    {
                    public:
                    	static NodeData* Alloc() { return NewObjClear(pc12835_scenehook); }
                    	Bool Message(GeListNode* node, Int32 type, void* data) override
                    	{
                    		if (type == MSG_DOCUMENTINFO)
                    		{
                    			DocumentInfoData* const msg = static_cast<DocumentInfoData*>(data);
                    			if (msg == nullptr)
                    				return false;
                    			// switch message sub-type
                    			switch (msg->type)
                    			{
                    				case MSG_DOCUMENTINFO_TYPE_LOAD:
                    				{
                    					ApplicationOutput("document is loaded"_s);
                    					break;
                    				}
                    				case MSG_DOCUMENTINFO_TYPE_UNDO:
                    				case MSG_DOCUMENTINFO_TYPE_REDO:
                    				{
                    					ApplicationOutput("undo or redo done"_s);
                    					break;
                    				}
                    			}
                    			
                    			return true;
                    		}
                    		return SceneHookData::Message(node, type, data);
                    	};
                    
                    };
                    
                    

                    As @zipit said, the message is broadcast to all NodeData so using a PreferenceData.
                    We have an example on github but you don't need all that code.
                    After trying it myself, i couldn't make it work. It seems that the Message function is never called.

                    Cheers,
                    Manuel

                    MAXON SDK Specialist

                    MAXON Registered Developer

                    A 1 Reply Last reply Reply Quote 0
                    • A
                      ac3 @Manuel
                      last edited by

                      @m_magalhaes Hi, where in this code does the script start to run and call the python code? Or did I misunderstand something?

                      1 Reply Last reply Reply Quote 0
                      • ManuelM
                        Manuel
                        last edited by Manuel

                        hi,
                        sorry I was focused on calling a command and not a script.

                        Even if it's pretty simple, it's not as simple as i expected to run a python script, sorry about that.
                        Be careful that you need to create the script and relaunch c4d to be able to find it by its name.

                        The idea is to retrieve the ID of the script and use callCommand to execute it. (as you can do with any commandData IDs)
                        you can retrieve the ScriptList with GetScriptHead witch return a GeListHead

                        So you can retrieve the first with GetFirst and compare the name.
                        If you find one, you can simply return it's IDs using GetDynamicScriptID and return it.

                        You now just have to use CallCommand with this ID. (be aware that this CallCommand will create an undo step in the undo stack)

                        So your script will be executed when a new document is loaded.

                        #include "maxon/apibase.h"
                        #include "maxon/errorbase.h"
                        #include "maxon/errortypes.h"
                        #include "maxon/file_utilities.h"
                        #include "maxon/application.h"
                        
                        #include "c4d_general.h"
                        #include "c4d_commanddata.h"
                        #include "c4d_baseplugin.h"
                        #include "c4d_scenehookdata.h"
                        #include "c4d_baselist.h"
                        
                        static Int32 GetScriptID(const maxon::String& scriptName)
                        {
                        	iferr_scope;
                        	
                        	// check all script
                        	// Retrieves the script head
                        	BaseList2D* scriptHead = static_cast<BaseList2D*>(GetScriptHead(0)->GetFirst());
                        
                        	// for all script
                        	for (BaseList2D* script = scriptHead; script != nullptr; script = script->GetNext())
                        	{
                        		// retrieves the name of the script
                        		maxon::String name = script->GetName();
                        		// if the name match the argument, return the id of the script
                        		if (name.IsEqual(scriptName))
                        			return GetDynamicScriptID(script);
                        	}
                        
                        	// return NOTOK if no script founded.
                        	return NOTOK;
                        }
                        
                        class pc12835_scenehook : public SceneHookData
                        {
                        public:
                        	static NodeData* Alloc() { return NewObjClear(pc12835_scenehook); }
                        	Bool Message(GeListNode* node, Int32 type, void* data) override
                        	{
                        		if (type == MSG_DOCUMENTINFO)
                        		{
                        			DocumentInfoData* const msg = static_cast<DocumentInfoData*>(data);
                        			if (msg == nullptr)
                        				return false;
                        			// switch message sub-type
                        			switch (msg->type)
                        			{
                        				case MSG_DOCUMENTINFO_TYPE_LOAD:
                        				{
                        					// define my script name
                        					maxon::String scriptName = "myscript"_s;
                        					// search the ID of the scrip
                        					const Int32 scriptID = GetScriptID(scriptName);
                        					// if the script have been founded, execute it.
                        					if (scriptID != NOTOK)
                        						CallCommand(scriptID);
                        					break;
                        				}
                        				case MSG_DOCUMENTINFO_TYPE_UNDO:
                        				case MSG_DOCUMENTINFO_TYPE_REDO:
                        				{
                        					ApplicationOutput("undo or redo done"_s);
                        					break;
                        				}
                        			}
                        			
                        			return true;
                        		}
                        		return SceneHookData::Message(node, type, data);
                        	};
                        
                        };
                        
                        

                        Of course you need to register your sceneHookData with RegisterSceneHookPlugin

                        Cheers,
                        Manuel

                        MAXON SDK Specialist

                        MAXON Registered Developer

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