<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Tag plugin general issues (crash, threading, message)]]></title><description><![CDATA[<p dir="auto">Hello <img src="http://developers.maxon.net/forum/assets/plugins/nodebb-plugin-emoji/emoji/android/1f62d.png?v=0b8ddba251d" class="not-responsive emoji emoji-android emoji--sob" style="height:23px;width:auto;vertical-align:middle" title="😭" alt="😭" />,<br />
at the moment I try to create a tag plugin but it seems it is a bit more complicated than with an object plugin :-).</p>
<p dir="auto">I added a small snippet of the plugin as <a href="https://developers.maxon.net/forum/assets/uploads/files/1693321629714-testtrans.zip" target="_blank" rel="noopener noreferrer nofollow ugc">testtrans.zip</a>  zipfile.<br />
In the res-folder is the Cinema4d scene file (crashes) and a json-file.</p>
<p dir="auto">In the layout res-file I created a simple Baselink, Filename , Button(I want avoid) and BaseTime</p>
<p dir="auto"><strong>Function of the test plugin:</strong></p>
<ul>
<li>The user has to drag a pose morph tag into the Baselink.</li>
<li>Then he has to load the json1.json file as link</li>
</ul>
<p dir="auto">The user loads the *.json file (res-folder), I catch this via c4d.MSG_DESCRIPTION_POSTSETPARAMETER and this triggers the function load_transcript() and loads the *.json file content into a member variable self.data.</p>
<p dir="auto"><strong>Questions:</strong></p>
<ul>
<li>
<p dir="auto"><strong>Main Question:</strong> In the Execute(self, tag, doc, op, bt, priority, flags) method I want to to some actions. But here Cinema is crashing. Probably it has something to do with threading and that it asks the tags description.:-).<br />
I commented out the position where it is crashing. So if I replace the tag[PY_SYNC_START] simply with an integer it works</p>
</li>
<li>
<p dir="auto"><strong>Is</strong> the method I used in the Message() method correct to detect the changes in the filename link? It doesn't work so I added a button to load it , then it works, but I want it to load as soon as the user changes the link to the json file. It calls the print() function in the POSTSETPARAMETER thing, but it doesn't trigger the load_transfile() method.</p>
</li>
<li>
<p dir="auto"><strong>Another small bug maybe in Cinema 4D</strong>. When I set the ACCEPT parameter in the Baselink in the res-file to {Tposemorph;} he gives me a ressource error but when I type Tdisplay it works ??????</p>
</li>
</ul>
<p dir="auto">Here is the code:</p>
<pre><code>import c4d
import os
from c4d import bitmaps, gui, plugins
import json

# be sure to use a unique ID obtained from www.plugincafe.com
PLUGIN_ID = 5554443  # just a test ID

# ID's
PY_MORPH_LINK = 10000
PY_TRANSCRIPT_LINK = 10001
PY_SYNC_START = 10018
PY_LOAD_TRANSCRIPT = 10021


# The Plugin Class
class TestTrans(plugins.TagData):

    def __init__(self):       

        self.data = None

    def Init(self, node):

        self.InitAttr(node, c4d.BaseList2D, PY_MORPH_LINK)
        # node[PY_MORPH_LINK] = None

        self.InitAttr(node, str, PY_TRANSCRIPT_LINK)
        # node[PY_TRANSCRIPT_LINK] = ""

        self.InitAttr(node, c4d.BaseTime, PY_SYNC_START)
        node[PY_SYNC_START] = c4d.BaseTime()

        return True
    
    def load_transcript(self, op):

        if op[PY_TRANSCRIPT_LINK] != "":
            with open(op[PY_TRANSCRIPT_LINK], "r") as transfile:
                self.data = json.load(transfile)

    def move2(self, tag, frame, value):
        print("2. Hello in function")

    def Execute(self, tag, doc, op, bt, priority, flags):

        if self.data:

            pose_morph = tag[PY_MORPH_LINK]

            if not pose_morph:
                return c4d.EXECUTIONRESULT_OK

            morph_count = pose_morph.GetMorphCount()
            print(pose_morph)
            print(self.data["words"])

            frame = doc.GetTime().GetFrame(doc.GetFps()) - tag[PY_SYNC_START]  #Here it is crashing
            print(frame)

            if frame == 10:
                print("1. Hello")

            self.move2(tag, frame, 1)

        return c4d.EXECUTIONRESULT_OK
   

    def Message(self, node, type, data):

        if type == c4d.MSG_DESCRIPTION_COMMAND:

            if data["id"][0].id == PY_LOAD_TRANSCRIPT:
                self.load_transcript(node)

        if type == c4d.MSG_DESCRIPTION_POSTSETPARAMETER:
            if data["descid"][0].id == PY_TRANSCRIPT_LINK:
                print("POSTSETPARAMETER")
                self.load_transcript(node)

        return True


# main
if __name__ == "__main__":
    # load icon.tif from res into bmp
    bmp = bitmaps.BaseBitmap()
    dir, file = os.path.split(__file__)
    fn = os.path.join(dir, "res", "icon.tif")
    bmp.InitWith(fn)

    new_bmp = c4d.bitmaps.InitResourceBitmap(1051133)

    # register the plugin
    c4d.plugins.RegisterTagPlugin(id=PLUGIN_ID,
                                  str="Test-Trans",
                                  info=c4d.TAG_EXPRESSION | c4d.TAG_VISIBLE,
                                  description="testtrans",
                                  g=TestTrans, icon=bmp)

</code></pre>
<p dir="auto">res-file:</p>
<pre><code>CONTAINER Testtrans
{
	NAME TESTTRANS;
	INCLUDE Texpression;

	GROUP ID_TAGPROPERTIES
	{
        LINK PY_MORPH_LINK
        {
            ACCEPT { Tbase; }
        }

        FILENAME PY_TRANSCRIPT_LINK
        {
          ANIM ON;
        }

        BASETIME PY_SYNC_START {}


	}
}
</code></pre>
<p dir="auto">header-file:</p>
<pre><code>#ifndef _TESTTRANS_H_
#define _TESTTRANS_H_
enum
{
    PY_MORPH_LINK           = 10000,
    PY_TRANSCRIPT_LINK      = 10001,
    PY_SYNC_START           = 10018,

	//GV_XPEMIT_NODE_DUMMY
};
#endif // ${FILE_NAME}
</code></pre>
<p dir="auto">string-file:</p>
<pre><code>STRINGTABLE Testtrans // derselbe Name wie res-file
{
	TESTTRANS                       "Test-Trans";
	PY_MORPH_LINK                 "Pose-Morph-Tag";
	PY_TRANSCRIPT_LINK            "Transcript";
       PY_SYNC_START                 "Start";

}
</code></pre>
<p dir="auto">Best Regards<br />
Tom</p>
]]></description><link>http://developers.maxon.net/forum/topic/14989/tag-plugin-general-issues-crash-threading-message</link><generator>RSS for Node</generator><lastBuildDate>Tue, 09 Jun 2026 21:16:30 GMT</lastBuildDate><atom:link href="http://developers.maxon.net/forum/topic/14989.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 29 Aug 2023 14:43:32 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Tag plugin general issues (crash, threading, message) on Wed, 30 Aug 2023 16:53:38 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/ferdinand">@<bdi>ferdinand</bdi></a></p>
<p dir="auto">Thank you Ferdinand for your leniency regarding the three questions..<br />
Will take note of that in the future.</p>
<p dir="auto">=====BaseTime=====<br />
Which just surprises me about the BaseTime problem is, that it worked in the Python tag. I didn't get an error message and the prototype worked very well.<br />
So I also tried instead of BaseTime int type value in the plugin, but it  crashed. It confused me a bit. So I try your suggestion.</p>
<pre><code># In the python tag it worked with int
</code></pre>
<pre><code># starf_frame was an int
 frame = doc.GetTime().GetFrame(doc.GetFps()) - op[c4d.ID_USERDATA,start_frame]
</code></pre>
<p dir="auto">====PoseMorph Symbol====<br />
Regarding the posmorph ID, I should have figured that out myself</p>
<p dir="auto">Thanks for your quick respond</p>
<p dir="auto">Tom</p>
]]></description><link>http://developers.maxon.net/forum/post/72345</link><guid isPermaLink="true">http://developers.maxon.net/forum/post/72345</guid><dc:creator><![CDATA[ThomasB]]></dc:creator><pubDate>Wed, 30 Aug 2023 16:53:38 GMT</pubDate></item><item><title><![CDATA[Reply to Tag plugin general issues (crash, threading, message) on Wed, 30 Aug 2023 11:45:26 GMT]]></title><description><![CDATA[<p dir="auto">Hey <a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/thomasb">@<bdi>ThomasB</bdi></a>,</p>
<p dir="auto">Thank you for reaching out to us. Thank you for your very clear posting, but your three questions should have been at least two or better three topics because they are all entirely  different subjects. I did not fork your topic in this case because you did put so much work into your posting, but I would want to give you a gentle reminder that topics should only contain a singular topic.</p>
<h3>About Your Questions</h3>
<h4>Crash in TagData.Execute</h4>
<p dir="auto">No, this has nothing to do with threading and your code is (mostly) correct. There is a bug in 2023 in <a href="https://developers.maxon.net/docs/py/2023_2/modules/c4d/BaseTime/index.html?highlight=basetime#BaseTime.__sub__" target="_blank" rel="noopener noreferrer nofollow ugc">BaseTime.__sub__</a>, it has already been fixed in the API of the upcoming release.</p>
<p dir="auto">Note that we support <code>BaseTime.__sub__</code> with <code>other</code> being an <code>int</code>; this has been added in <code>2023</code> and is the cause of the bug. But we do not support <code>__rsub__</code>. I.e., <code>BaseTime - int</code> (<code>__sub__</code>) is supported but <code>int - BaseTime</code> (<code>__rsub__</code>) is not. The <code>int</code> support has also not yet been documented.</p>
<p dir="auto">When you call <code> frame = doc.GetTime().GetFrame(doc.GetFps()) - tag[PY_SYNC_START]</code> you invoke <code>__rsub__</code> which then defaults to <code>__sub__</code> and triggers the bug. When subtracting an <code>int</code> from a <code>BaseTime</code>, the <code>int</code> is also interpreted as a value in seconds and not as frame value, because a <code>BaseTime</code> has no inherent fps.</p>
<pre><code class="language-py">&gt;&gt; import c4d
&gt;&gt; bt: c4d.BaseTime = c4d.BaseTime(50, 25)
&gt;&gt; bt.Get()
2.0
&gt;&gt; # 1 will be subtracted from the value in seconds which represented by #bt.
&gt;&gt; (bt - 1).Get()
1.0
</code></pre>
<p dir="auto">So, you probably meant here:</p>
<pre><code class="language-py">fps: int = doc.GetFps()
frame: int = doc.GetTime().GetFrame(fps) - tag[PY_SYNC_START].GetFrame(fps)
</code></pre>
<h4>Does not Invoke load_transcript</h4>
<p dir="auto">Well, when your statement <code>print("POSTSETPARAMETER")</code> is being hit, so will be the line after it. The interpreter will not magically not call something. Please also do understand that we cannot debug your code for you.</p>
<p dir="auto">What can happen here is that it looks like that <code>load_transcript</code> is not running because:</p>
<ol>
<li>Your condition <code>op[PY_TRANSCRIPT_LINK] != ""</code> is not being met.</li>
<li>Whatever relies on <code>self.data</code> only later reacts to it being updated or never reacts at all.</li>
<li>You get on <code>NodeData.Message</code> calls that are not on the main thread. All file operations are not thread-safe, you cannot have two things accessing one file at the same time. You should wrap all file operations in a <code>c4d.threading.GeIsMainThread</code> condition.</li>
</ol>
<p dir="auto">In the end, you probably have to do a bit more debugging here.</p>
<p dir="auto">That <code>MSG_DESCRIPTION_POSTSETPARAMETER</code> is not broadcasted for parameter changes of a node that is linked is normal, because you listen here to the messages of your node and not the messages of the linked node.</p>
<h4>Tposemorph Symbol</h4>
<p dir="auto">Yes, you are right, the symbol is not exposed in resources, that is an oversight or bug if you will. You must use the numeric value of <code>Tposemorph</code> instead:</p>
<pre><code class="language-cpp">LINK PY_MORPH_LINK
{
  ANIM OFF;
  ACCEPT { 1024237; } // Value for Tposemorph
}
</code></pre>
<p dir="auto">Cheers,<br />
Ferdinand</p>
]]></description><link>http://developers.maxon.net/forum/post/72342</link><guid isPermaLink="true">http://developers.maxon.net/forum/post/72342</guid><dc:creator><![CDATA[ferdinand]]></dc:creator><pubDate>Wed, 30 Aug 2023 11:45:26 GMT</pubDate></item></channel></rss>