Why object don't stay in LinkBox on DestroyWindow?

On 23/10/2016 at 18:43, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   R12+
Platform:   Windows; 
Language(s) :     Python ;

Hi Guys,
New Problem guys,
I'm trying to figure out why the object don't stay in linkbox when DestroyWindow execute?
Can you guys try look or try my code, this is the Example Plugin here. I also show were is the problem.

# | Ashton Plugin Example by Ashton Rolle |
  
# | Imports for Cinema 4D | 
import c4d
import os
import webbrowser
import collections
import urllib
import sys, subprocess
import math, random
from c4d import *
from random import randint
from c4d import plugins, gui, bitmaps, documents, storage
from c4d.plugins import SetWorldPluginData, GetWorldPluginData
#--------------------------------------#
  
# | Initialize StartUp |----| The Plugin ID, Info and Data Type Register |
  
PLUGIN_ID = 1038198                 # Get yours at www.plugincafe.com and Plugin IDs 1000001-1000010 are reserved for development.
  
PLUGIN_NAME = "AP Ashton Plugin Example"      # Your Text String Plugin Name.
  
PLUGIN_INFO_HELP = "AP Ashton needs help with python code." # The plugin help info Text String is on what the plugin does.
  
class PluginExample_Data(c4d.plugins.CommandData) :
  
    dialog = None
  
    def Init(self, op) :
        return True
  
    def Message(self, type, data) :
        return True
  
    def Execute(self, doc) :
        if self.dialog is None:
            self.dialog = PluginExample_Dialog()
            print "AP Ashton Plugin Example is Open Now!"
        return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=400, defaulth=100)
  
    def RestoreLayout(self, sec_ref) :
        if self.dialog is None:
            self.dialog = PluginExample_Dialog()        
        return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)
  
    def ExecuteOptionID(self, doc, plugid, subid) :
        return True
  
if __name__ == '__main__':
    Plugin_Icon = c4d.bitmaps.BaseBitmap()
    dir, file = os.path.split(__file__)
    Image_File_Name = "Your_Icon.png"                                   # Your plugin logo image Icon file name. 
    Folder_File_Name = os.path.join(dir, "res/Icons", Image_File_Name)  # Your plugin logo image Icon file path dir inside the Plugin Folder. 
    Plugin_Icon.InitWith(Folder_File_Name)
    print "----\nPlugin Example Initialized. V1.0.0\n----"              # To show plugin is there and it will show it print inside the C4D Console.
    result = plugins.RegisterCommandPlugin(id=PLUGIN_ID,                # Plugin register ID.
                                           str=PLUGIN_NAME,             # This is for the Plugin Name to show in the Plugins list.
                                           info=0,                      # If you want a option button once you have a ExecuteOptionID in Data Class, then put info=c4d.PLUGINFLAG_COMMAND_OPTION_DIALOG | c4d.PLUGINFLAG_COMMAND_HOTKEY,
                                           icon=Plugin_Icon,            # Plugin Icon Image.
                                           help=PLUGIN_INFO_HELP,       # The plugin help info is on what the plugin does.
                                           dat=PluginExample_Data())     # The plugin data
#-------------------------------------------------------------------------------------------------------------------------------------#
  
# | Main Dialog UI Interface Layout | 
class PluginExample_Dialog(c4d.gui.GeDialog) :
  
    # | ID's for Dialog User Interface, UI Buttons, Check Buttons, and for Coding (it's self.ID - this is When the ID is in a Class) |
    Group_ID = 5000
    UI_0 = 5001
    UI_1 = 5002
    UI_2 = 5003
    UI_3 = 5004
    UI_4 = 5005    
    UI_LvlList = 5006
    UI_BTN_Set = 5007
    UI_ObjectLinkBox = 5008
  
    # | Creating Dialog UI Interface Layout | 
    def CreateLayout(self) :
  
        self.SetTitle(PLUGIN_NAME)   # Your title for the dialog.
  
        self.GroupBegin(self.Group_ID, c4d.BFH_SCALEFIT, 3, 0, "")
        self.rootLinkBaseContainer = c4d.BaseContainer()
        self.linkBox = self.AddCustomGui(self.UI_ObjectLinkBox, c4d.CUSTOMGUI_LINKBOX, "", c4d.BFH_SCALEFIT, 200, 10, self.rootLinkBaseContainer)
        IDList = self.UI_LvlList
        self.AddComboBox(IDList, c4d.BFH_MASK, 40, 0, False)
        self.AddChild(IDList, self.UI_0, '0')
        self.AddChild(IDList, self.UI_1, '1')
        self.AddChild(IDList, self.UI_2, '2')
        self.AddChild(IDList, self.UI_3, '3')
        self.AddChild(IDList, self.UI_4, '4')
        self.AddButton(self.UI_BTN_Set, c4d.BFH_MASK, initw=10, name="Set")
        self.GroupEnd()
        return True
  
    # | Set State of the Layout Dialog UI |
    def __init__(self) :
        super(PluginExample_Dialog, self).__init__()
  
    @classmethod    
    def Load_UI_Settings(cls, instance) :
        bc = c4d.plugins.GetWorldPluginData(PLUGIN_ID)
        bc = bc or c4d.BaseContainer()
        if instance:            
            instance.SetLong(cls.UI_LvlList, bc.GetLong(cls.UI_LvlList, cls.UI_LvlList))                                        
        return bc  
  
    def AutoSave_UI_Settings(self, save=True) :       # For Auto Saving UI Layout Settings.
        data = c4d.BaseContainer()
        data[self.UI_LvlList] = self.GetLong(self.UI_LvlList) #  <----- This working fine.
  
    #   data[self.UI_ObjectLinkBox] = self.GetLink(self.UI_ObjectLinkBox)   # <----- This is my Problem! if this enable its not keep the object or material in the Link Box.
  
        if save:
            c4d.plugins.SetWorldPluginData(PLUGIN_ID, data)
        return data 
  
    def DestroyWindow(self) : # If dialog close or c4d UI layout change then execute [self.AutoSave_UI_Settings()].
        self.AutoSave_UI_Settings()
  
    def InitValues(self) :
        PluginExample_Dialog.Load_UI_Settings(self) 
        return True 
    #-------------------------------------------------------------------------------#
  
    #--| Commands of the UI to execute your Functions you made. |
    def Command (self, id, msg) :
        if (id == self.UI_BTN_Set) :
            doc = c4d.documents.GetActiveDocument()
            obj = self.linkBox.GetLink().GetName()
            LevelListID = self.UI_LvlList
            if self.GetLong(LevelListID)==self.UI_0:
                Link_Object = doc.SearchObject(obj)
                Set_lvl=0.0
                Link_Object[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Y]=Set_lvl
            c4d.EventAdd()                                               
            return True            
        return True
#----------------------------------------------------------------------------------------------------------------------------------------------------------------#
#  | End OF Plugin | #

Any Ideas, that will be appreciative guys,
Cheers,
AP Ashton

On 24/10/2016 at 01:53, xxxxxxxx wrote:

Hi Ashton,

often the solutions are quite simple. Watch the console for errors. :wink:

You are calling GetLink() on a GeDialog instance, which doesn't provide such function. Instead you need to call GetLink()/SetLink() on your linkBox instance and it will work as expected.

One small request from our side:
The less code you post, the easier it is for us to reproduce and check the issue. In the end this provides us with more time to help others or more time to improve the docs. So a little time spent in short meaningful code snippets help everybody.

On 24/10/2016 at 09:09, xxxxxxxx wrote:

hey sorry about not having less code Andreas but I still don't understand GetLink()/SetLink()  do you have a example that I can look at using it in this way, cause I am lost and I think I try everything but no luck,  I a not seeing work on my side. But this works

data[self.UI_LvlList] = self.GetLong(self.UI_LvlList) #  <----- This working fine.

So how do you set it up for a LinkBox.

On 24/10/2016 at 09:32, xxxxxxxx wrote:

Give this version a try.

  
#This Dialog plugin shows how to add data to the world container(the object in a linkbox)  
#Then use it to fill in the dialog's gizmos when the dialog is closed / then re-opened  
#WARNING!!: NEVER add data to the world container like this in public plugins!! It's a very bad practice!!  
#           The data will stay there forever. Without the user's consent!!!  
  
  
import c4d, os  
from c4d import plugins, gui, bitmaps, documents, storage  
from c4d.plugins import SetWorldPluginData, GetWorldPluginData  
  
PLUGIN_ID = 1038198  
PLUGIN_NAME = "World Container Example"  
PLUGIN_INFO_HELP = "AP Ashton needs help with python code."  
  
class PluginExample_Dialog(c4d.gui.GeDialog) :  
  
  Group_ID = 5000  
  UI_0 = 5001  
  UI_1 = 5002  
  UI_2 = 5003  
  UI_3 = 5004  
  UI_4 = 5005      
  UI_LvlList = 5006  
  UI_BTN_Set = 5007  
  UI_ObjectLinkBox = 5008  
  linkbox = None  
  
  def CreateLayout(self) :  
  
      self.SetTitle(PLUGIN_NAME)  
  
      self.GroupBegin(self.Group_ID, c4d.BFH_SCALEFIT, 3, 0, "")  
      self.rootLinkBaseContainer = c4d.BaseContainer()  
      self.linkBox = self.AddCustomGui(self.UI_ObjectLinkBox, c4d.CUSTOMGUI_LINKBOX, "", c4d.BFH_SCALEFIT, 200, 10, self.rootLinkBaseContainer)  
      IDList = self.UI_LvlList  
      self.AddComboBox(IDList, c4d.BFH_MASK, 40, 0, False)  
      self.AddChild(IDList, self.UI_0, '0')  
      self.AddChild(IDList, self.UI_1, '1')  
      self.AddChild(IDList, self.UI_2, '2')  
      self.AddChild(IDList, self.UI_3, '3')  
      self.AddChild(IDList, self.UI_4, '4')  
      self.AddButton(self.UI_BTN_Set, c4d.BFH_MASK, initw=10, name="Set")  
      self.GroupEnd()  
      return True  
  
  
  def __init__(self) :  
      super(PluginExample_Dialog, self).__init__()  
  
  @classmethod      
  def Load_UI_Settings(cls, instance) :  
      bc = c4d.plugins.GetWorldPluginData(PLUGIN_ID)  
      bc = bc or c4d.BaseContainer()  
      if instance:              
          instance.SetLong(cls.UI_LvlList, bc.GetLong(cls.UI_LvlList, cls.UI_LvlList))                                          
      return bc    
  
  def AutoSave_UI_Settings(self, save=True) :   #For saving the plugin's GUI Settings when the dioalog is closed  
    
      #Create a new container and store the gizmo data in it  
      data = c4d.BaseContainer()  
      data[self.UI_LvlList] = self.GetLong(self.UI_LvlList)  
      data[self.UI_ObjectLinkBox] = self.linkBox.GetLink()   
  
      #Save the container in the WorldPluginData container  
      if save:  
          c4d.plugins.SetWorldPluginData(PLUGIN_ID, data)  
            
      return data  
  
  #Close the dialog and save the GUI data  
  def DestroyWindow(self) :  
      self.AutoSave_UI_Settings()  
  
  def InitValues(self) :  
    
      PluginExample_Dialog.Load_UI_Settings(self)   
        
      #Get this plugin from the world container   
      bc = c4d.plugins.GetWorldPluginData(PLUGIN_ID)              
      """for i,v in enumerate(bc) :  
          print i,v"""  
            
      if bc[5008] is not None:   
          self.linkBox.SetLink(bc[5008])  #Insert the object that was in the linkBox gizmo when the dialog was closed  
        
      return True   
        
  def Command (self, id, msg) :      
    
      if (id == self.UI_BTN_Set) :  
          doc = c4d.documents.GetActiveDocument()  
          obj = self.linkBox.GetLink().GetName()  
            
          LevelListID = self.UI_LvlList     
            
          if self.GetLong(LevelListID) == self.UI_0:  
              Link_Object = doc.SearchObject(obj)  
              Set_lvl = 0.0  
              Link_Object[c4d.ID_BASEOBJECT_REL_POSITION,c4d.VECTOR_Y]=Set_lvl  
          c4d.EventAdd()                                                 
          return True   
            
      return True  
        
        
  def Message(self, msg, result) :  
    
      doc = documents.GetActiveDocument()  
        
      if msg.GetId() == c4d.MSG_DESCRIPTION_CHECKDRAGANDDROP:   
          if self.linkBox.GetLink() != None:   
              print self.linkBox.GetLink().GetName()  
            
      return gui.GeDialog.Message(self, msg, result)  
        
class PluginExample_Data(c4d.plugins.CommandData) :  
  
  dialog = None  
  
  def Init(self, op) :  
      return True  
  
  def Message(self, type, data) :  
      return True  
  
  def Execute(self, doc) :  
      if self.dialog is None:  
          self.dialog = PluginExample_Dialog()   
      return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=400, defaulth=100)  
  
  def RestoreLayout(self, sec_ref) :  
      if self.dialog is None:  
          self.dialog = PluginExample_Dialog()          
      return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)  
  
  def ExecuteOptionID(self, doc, plugid, subid) :  
      return True  
  
if __name__ == '__main__':  
  Plugin_Icon = c4d.bitmaps.BaseBitmap()  
  dir, file = os.path.split(__file__)  
  Image_File_Name = "Your_Icon.png"                                   # Your plugin logo image Icon file name.   
  Folder_File_Name = os.path.join(dir, "res/Icons", Image_File_Name)  # Your plugin logo image Icon file path dir inside the Plugin Folder.   
  Plugin_Icon.InitWith(Folder_File_Name)  
  print "----\nPlugin Example Initialized. V1.0.0\n----"              # To show plugin is there and it will show it print inside the C4D Console.  
  result = plugins.RegisterCommandPlugin(id=PLUGIN_ID,                # Plugin register ID.  
                                         str=PLUGIN_NAME,             # This is for the Plugin Name to show in the Plugins list.  
                                         info=0,                      # If you want a option button once you have a ExecuteOptionID in Data Class, then put info=c4d.PLUGINFLAG_COMMAND_OPTION_DIALOG | c4d.PLUGINFLAG_COMMAND_HOTKEY,  
                                         icon=Plugin_Icon,            # Plugin Icon Image.  
                                         help=PLUGIN_INFO_HELP,       # The plugin help info is on what the plugin does.  
                                         dat=PluginExample_Data())     # The plugin data

-ScottA

On 25/10/2016 at 14:08, xxxxxxxx wrote:

I would never think about some like that like that , Thanks ScottA,