DIRTY LINK!

On 15/07/2017 at 23:21, xxxxxxxx wrote:

Hello everybody! I experiment with the python and there was a small problem. I have a hierarchy of objects and since the python does not show and does not exist inside the plugin objects, I decided to make links. Everything except the update in the viewport works. And the entire branch of the rig is duplicated. I can not figure this out. Help me please. Explain how it works correctly, please. Code below

import os
import sys

folder = os.path.dirname(__file__)
if folder not in sys.path:
    sys.path.insert(0, folder)
from c4d.threading import C4DThread
import math
import c4d
from c4d import plugins, utils, bitmaps, gui, threading
from c4d.modules import *

Dummy_Experement_ID = 1039406
ID_OBJECTPROPERTIES_BC = 3000
BC_VIEW = 3001
BC_RENDER = 3002
BC_LOW_BODY_LINK = 3003
BC_HIGH_BODY_LINK = 3004
BC_BODY_LINK = 3005

pathicons = "res/icons"
baseicon = "icons_base.png"

class Dummy_Experement(c4d.plugins.ObjectData) :

# def __init__(self) :

#     self.SetOptimizeCache(True)

def Build(self, name) :

self.low_body = c4d.BaseObject(1011010)
        self.low_body.SetName('Low Body ' + name.GetName())
        self.low_body[c4d.CONNECTOBJECT_WELD] = 0
        self.low_body[c4d.CONNECTOBJECT_PHONG_MODE] = 0
        self.low_body[c4d.CONNECTOBJECT_CENTERAXIS] = 1

# self.low_body.ChangeNBit(c4d.NBIT_NOSELECT, c4d.NBITCONTROL_SET)
        # self.low_body.ChangeNBit(c4d.NBIT_OHIDE, c4d.NBITCONTROL_SET)
        #
        #
        #
        #
        self.dytag_low_body = self.low_body.MakeTag(180000102)
        self.dytag_low_body.SetName('Dynamics Tag ' + name.GetName())
        # self.dytag_low_body.ChangeNBit(c4d.NBIT_OHIDE, c4d.NBITCONTROL_SET)
        #
        #
        #
        #
        self.high_body = c4d.BaseObject(1011010)
        self.high_body.SetName('High Body ' + name.GetName())
        self.high_body.InsertUnder(self.low_body)
        self.high_body[c4d.CONNECTOBJECT_WELD] = 0
        self.high_body[c4d.CONNECTOBJECT_PHONG_MODE] = 0
        self.high_body[c4d.CONNECTOBJECT_CENTERAXIS] = 1

return self.low_body.GetClone()

def Draw(self, op, drawpass, bd, bh) :

doc = c4d.documents.GetActiveDocument()

self.low_body = doc.SearchObject('Low Body ' + op.GetName())
        self.tag = self.low_body.GetTag(180000102)
        self.high_body = doc.SearchObject('High Body ' + op.GetName())
        
        #
        #
        #
        if op[BC_VIEW] == 0:
            self.low_body[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 1
            self.high_body[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 0
            c4d.EventAdd()

elif op[BC_VIEW] == 1:
            self.low_body[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 0
            self.high_body[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = 1
            c4d.EventAdd()

if op[BC_RENDER] == 0:
            self.low_body[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 1
            self.high_body[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 0
            c4d.EventAdd()

elif op[BC_RENDER] == 1:
            self.low_body[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 0
            self.high_body[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = 1
            c4d.EventAdd()

#
        #
        #
        if op[BC_LOW_BODY_LINK] == None:
            self.low_body[c4d.ID_BASEOBJECT_GENERATOR_FLAG] = 0
            self.tag[c4d.RIGID_BODY_ENABLED] = 0
            c4d.EventAdd()

elif op[BC_LOW_BODY_LINK].GetDown() == None:
            self.low_body[c4d.ID_BASEOBJECT_GENERATOR_FLAG] = 0
            self.tag[c4d.RIGID_BODY_ENABLED] = 0
            c4d.EventAdd()

else:
            self.low_body[c4d.ID_BASEOBJECT_GENERATOR_FLAG] = 1
            self.tag[c4d.RIGID_BODY_ENABLED] = 1
            c4d.EventAdd()
        #
        #
        #
        #
        if op[BC_HIGH_BODY_LINK] == None:
            self.high_body[c4d.ID_BASEOBJECT_GENERATOR_FLAG] = 0
            c4d.EventAdd()

elif op[BC_HIGH_BODY_LINK].GetDown() == None:
            self.high_body[c4d.ID_BASEOBJECT_GENERATOR_FLAG] = 0
            c4d.EventAdd()

else:
            self.high_body[c4d.ID_BASEOBJECT_GENERATOR_FLAG] = 1
            c4d.EventAdd()

self.low_body[c4d.CONNECTOBJECT_LINK] = op[BC_LOW_BODY_LINK]
        self.high_body[c4d.CONNECTOBJECT_LINK] = op[BC_HIGH_BODY_LINK]

return c4d.DRAWRESULT_OK

def Init(self, op) :

self.InitAttr(op, bool, [em.BC_VIEW])
        self.InitAttr(op, bool, [em.BC_RENDER])

op[BC_VIEW] = False
        op[BC_RENDER] = False

return True

def GetVirtualObjects(self, op, hierarchyhelp) :

dirty = op.CheckCache(hierarchyhelp) or op.IsDirty(c4d.DIRTY_DATA)
        if dirty is False:
            return op.GetCache(hierarchyhelp)

link_low = op[BC_LOW_BODY_LINK]
        link_hight = op[BC_HIGH_BODY_LINK]

rig = self.Build(op)
        rig.InsertUnder(op)
        
        self.low_body = doc.SearchObject('Low Body ' + op.GetName())
        self.high_body = doc.SearchObject('High Body ' + op.GetName())

self.low_body[c4d.CONNECTOBJECT_LINK] = link_low
        self.high_body[c4d.CONNECTOBJECT_LINK] = link_hight

op[BC_BODY_LINK] = self.low_body

return c4d.BaseObject(c4d.Onull)

def Reg(self) :

Dummy_Experement_icon = c4d.bitmaps.BaseBitmap()
        Dummy_Experement_icon.InitWith(os.path.join(dir, pathicons, baseicon))
        return plugins.RegisterObjectPlugin(id = Dummy_Experement_ID, str = "Dummy_Experement", g = Dummy_Experement, description = "Dummy_Experement", info = c4d.OBJECT_INPUT | c4d.PLUGINFLAG_HIDEPLUGINMENU , icon = Dummy_Experement_icon )

if __name__ == '__main__':
    dir, file = os.path.split(__file__)
    Dummy_Experement.Reg()

On 17/07/2017 at 05:23, xxxxxxxx wrote:

Hi,

I'm not sure I understand the question. What do you mean with "I have a hierarchy of objects and since the python does not show and does not exist inside the plugin objects"? And what is the actual problem? What update in the viewport? In which scenario?

There are a few issues in your code, which may or may not be related:

You shouldn't (must not) use GetActiveDocument() in a plugin derived from NodeData. For example in rendering context, the active document will be different than the one being rendered. You need to get the document from the node/object via GetDocument().

Please don't do EventAdd() in Draw(). See Threading Information.

On 18/07/2017 at 05:36, xxxxxxxx wrote:

I eliminated those mistakes that were pointed out to me) What about the userdata? Why when I put object in the link box I have a duplicate rig?

link_low = op[BC_LOW_BODY_LINK]Question
link_hight = op[BC_HIGH_BODY_LINK]Question

On 04/08/2017 at 05:19, xxxxxxxx wrote:

Hi,

I'm sorry for not answering here for so long. To be honest, I had hoped, you'd decide to answer at least some of my questions. The SDK Team can help to answer questions and we will try to do so as best as we can, but we are not supposed to debug code. Often we still do, because we really want to help. But we will also need some support... in this case from you. I can't do anything with your code, without the resource files and also a description of what it is supposed to do, how to set up a scene and how to reproduce the issue. I hope you don't mind.

Looking again at your code (the questions from my first post still continue to exist as well) :

Why do you store links to objects during Draw()?
Draw() should be overridden for drawing purposes only, nothing else.

In general storing links to objects in member variables has it's implications, one needs to carefully check. In most cases for example you will need to take care of these member variables in Read(), Write() and CopyTo().

Then you are using op.InsertUnder() during GetVirtualObjects(). That is at least unusual... Actually GetVirtualObjects() is supposed to return objects and that's it. No modifications to the scene should be done during GetVirtualObjects() (inserting or deleting objects, changing parameters of other part of the scene,...). I also suspect this to be the cause of any "duplication" you might experience. I mean, what's with the objects you inserted in the previous call of GetVirtualObjects()?
If you really need to create objects in the scene, other than what you return from GetVirtualObjects(), you'd do so in Message().

The entire thing looks to me design-wise questionable. I don't mean this as an insult.

Maybe that's what we should actually do here:
Discuss what's the best architecture of a plugin for whatever you are trying to achieve? Perhaps you can describe in detail what you want to achieve and then we can provide you with hints on how to do that?