How to handle "preset://" in filenames

On 02/06/2013 at 03:22, xxxxxxxx wrote:

I am dragging a Content browser file to a customgui file input.
However, when I drag e.g. "preset://broadcast.lib4d/Resources/Images/pictures/IMG_0605.jpg" to this field, the input is displayed in the field, but the length is 0.

I think this has to do again with "preset://".
Because when I delete that part manual from the input file, the length is >0 (thus ok).

So, how to handle this sort of filenames?

GUI part
        self.file = self.AddCustomGui(MY_HDRFILE, c4d.CUSTOMGUI_FILENAME, "", c4d.BFH_SCALEFIT, 0, 0)  
  
Input part
        if (id == MY_HDRFILE) :
            hdrfilename = self.GetString(MY_HDRFILE)
            print "hdrfilename: ", hdrfilename, len(hdrfilename)
            return True

On 02/06/2013 at 06:44, xxxxxxxx wrote:

After some more testing, I think, it could en another issue / I'm doing something wrong.
So, not 'preset://" related, but a functionality issues.

The thing is, I drag the file to the CUSTOMGUI_FILENAME field.
And it seems that dragging into the field is not recognized.
Typing or selecting is ok, but dragging apprently not.

I used the CUSTOMGUI_FILENAME because I want to drag the to a link field.
In the normal link field you can only drag objects and materials into the field.

All I want is to drag a picture from the content browser into my plugin / my linkfield.
It should be possible. The Material manager is doing it too.

On 02/06/2013 at 07:30, xxxxxxxx wrote:

Call manually GeDialog.Command() with the filename ID in your dialog when you recieve a 
drag and drop message for your filename gadget.

On 02/06/2013 at 08:10, xxxxxxxx wrote:

Ok, I tried it. See below.
But (of course?) it started looping.
I guess this is not what you mean?

    def Command(self, id, msg) :
        print id                     #Prints the ID of the UA
  
        if (id == 1012) :
            print "file: ", self.GetString (1012)
            self.Command(1012, msg)
            return True

On 02/06/2013 at 08:43, xxxxxxxx wrote:

Not in the Command() , in the Message() method.

def Message(self, msg, res) :
	if msg.GetId() == c4d.MSG_DRAGANDDROP:
		self.Command(c4d.MSG_DRAGANDDROP, c4d.BaseContainer())
	[...]
  
def Command(self, id, msg) :
	if id == c4d.MSG_DRAGANDDROP:
		# do something
	[...]

Something like this. This will call Command() each time a gadget receives a drag and drop 
message in your dialog. To only react to a specific gadgets you have to unpack the msg 
container in the message method and then pass that id to command.

On 02/06/2013 at 10:07, xxxxxxxx wrote:

Here my code.
What I see:
- Message never receives a drag&drop id
"Dragged" is never printed on the console.

import c4d
from c4d import bitmaps, gui, plugins, utils
import collections, os
  
### Dailoog test ###
# Add / remove GUI fields.
#
PLUGIN_ID = 14500110 #TestID only!!!!!!!!!!!!
  
class MyDialog(gui.GeDialog) :
  
    def CreateLayout(self) :
        self.SetTitle("Test Dialoog.")
        
        settings = c4d.BaseContainer()
        settings.SetBool(c4d.FILENAME_TEXTURE, True)
        settings.SetBool (c4d.DRAGANDDROP_FLAG_MSGVALID, True)		#required?
        
        self.element = self.AddStaticText(id=1011, flags=c4d.BFH_MASK, initw=150, name="Select Input File:", borderstyle=c4d.BORDER_NONE)
        self.file = self.AddCustomGui(1012, c4d.CUSTOMGUI_FILENAME, "", c4d.BFH_SCALEFIT, 0, 0, settings)
        return True
  
    def Command(self, id, msg) :
        if (id == 1012) :                               #not working, drag and drop not recognized
            print "file: ", self.GetString (1012)
            return True
 
        if (id == c4d.MSG_DRAGANDDROP) :
            print "file drag: ", self.GetString (1012)
            return True       
       
    def Message(self, msg, result) :
  
        if (msg.GetId() == c4d.MSG_DRAGANDDROP) :
            print "Dragged"
            self.Command(self, 1012, c4d.BaseContainer())  #c4d.MSG_DRAGANDDROP or 1012?
        return gui.GeDialog.Message(self, msg, result)
        
        return True
  
class TestDialoog(plugins.CommandData) :
    
    dialog = None
       
    def Execute(self, doc) :
        if self.dialog is None: self.dialog = MyDialog()
        return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=PLUGIN_ID, defaultw=500, defaulth=500)
    def RestoreLayout(self, sec_ref) :
        if self.dialog is None: self.dialog = MyDialog()
        return self.dialog.Restore(pluginid=PLUGIN_ID, secret=sec_ref)
  
if __name__ == "__main__":
     bmp = bitmaps.BaseBitmap()
     dir, f = os.path.split(__file__)
     fn = os.path.join(dir, "res", "icon.tif")
     bmp.InitWith(fn)
     plugins.RegisterCommandPlugin(id=PLUGIN_ID, 
                                  str="TestDialoog3",
                                  info=0,
                                  help="TestDialoog", 
                                  dat=TestDialoog(),
                                  icon=bmp)

On 02/06/2013 at 11:04, xxxxxxxx wrote:

I think the code LD posted is more designed for a Node based plugin. Not a GeDialog.

I've used the filename gizmo in one of my examples.
Here's the entire code:

"""  This is an example of using a .res based link box gizmo. And a customgui FILENAME gizmo  """  
  
#Id's for the custom LinkBox GUI if needed  
#CUSTOMGUI_LINKBOX = 1009415,    
#CUSTOMGUI_INLINE = 300001044,  
  
import c4d,os,sys  
from c4d import plugins, utils, bitmaps, gui, documents  
  
Plugin_ID=1000011 # Testing id ONLY!!!!!!!   
  
ResBasedMenu =  10001  
MY_FILE      =  10002  
MY_LINK      =  10003  
MY_GROUP     =  10004  
  
class MyDialog_Gui(gui.GeDialog) :  
  
  mylink = None  
  file = None  
   
  def CreateLayout(self) :      
  
      res = self.LoadDialogResource(ResBasedMenu)    #Loads GUI stuff from the .res file  
        
   
      self.GroupBegin(MY_GROUP, c4d.BFH_SCALEFIT|c4d.BFH_SCALEFIT, 1, 3, "Group Title",0) #id, flags, columns, rows, grouptext, groupflags  
      self.GroupBorder(c4d.BORDER_BLACK)  
      self.GroupBorderSpace(5, 20, 5, 20) #Left, top, Right, Bottom   
      self.SetTitle("LinkBox Example")    
      self.AddStaticText(1111,c4d.BFH_LEFT,50,10,"input",c4d.BORDER_NONE) #id, flags, height, width, text, borderstyle  
        
      #A linkbox gizmo created in the .res file  
      self.mylink = self.FindCustomGui(MY_LINK, c4d.CUSTOMGUI_LINKBOX)          
  
      #A FileName gizmo created here in the code(not in the .res file)  
      settings = c4d.BaseContainer()  
      #settings.SetBool(c4d.FILENAME_DIRECTORY, True)  #Use this to restrict selections to a folder(not a file)  
      #settings.SetBool(c4d.FILENAME_SAVE, True)          #Use this to open the save dialog  
      #settings.SetBool(c4d.FILENAME_TEXTURE, True)    #Texture mode...Makes the "do you want to create a project copy" message window pop up  
      self.file = self.AddCustomGui(MY_FILE, c4d.CUSTOMGUI_FILENAME, "", c4d.BFH_SCALEFIT|c4d.BFV_CENTER, 0, 0, settings)  
        
      self.GroupEnd()          
      return res      
  
  def InitValues(self) :   
      return True  
  
    
  def Command(self, id, msg) :  
   
      doc = documents.GetActiveDocument()  
        
      if id == MY_LINK:                           #When an object is droppped into the linkbox  
           print self.mylink.GetLink().GetName()  #print that object's name      
            
      c4d.EventAdd()     
      return True  
        
        
  def CoreMessage(self, id, msg) :      
  
      if id == c4d.EVMSG_CHANGE:     
          doc = documents.GetActiveDocument()   
          #print "Event Occurred"      
          linkedFile = self.GetString(MY_FILE)   #Gets the fn(string) path of the file in the gizmo  
          if len(linkedFile) != 0:               #If there's a file in the gizmo  
              print linkedFile                   #Do something with that file  
      return True      
        
        
   
#-------------------------------------------------------------------------  
#   MyDialog_Main --- Where the plugin stuff happens--Don't edit this part  
#-------------------------------------------------------------------------  
class myDialog_Main(plugins.CommandData) :  
  dialog = None  
    
  def Execute(self, doc) :  
      #Create the dialog  
      if self.dialog is None:  
          self.dialog = MyDialog_Gui()  
      return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC, pluginid=Plugin_ID, xpos=-1, ypos=-1)  
        
  def RestoreLayout(self, sec_ref) :  
      #Manage the async dialog so it can be docked in the UI  
      if self.dialog is None:  
          self.dialog = MyDialog_Gui()  
      return self.dialog.Restore(pluginid=Plugin_ID, secret=sec_ref)  
   
  
if __name__ == "__main__":  
 path, fn = os.path.split(__file__)  
 #bmp = bitmaps.BaseBitmap()  
 #bmp.InitWith(os.path.join(path, "res/icons/", "None")) #Uses a folder called "icons" inside the "res" folder to hold the icon  
 plugins.RegisterCommandPlugin(Plugin_ID, "LinkBox Example", 0, None, "", myDialog_Main())

When an image file is added to the filename gizmo using the file browser. The EVMSG_CHANGE message is sent to C4D. So you can use that message in place of a drag&drop message.

-ScottA

On 02/06/2013 at 11:10, xxxxxxxx wrote:

When a msg id does not work / is not received. Simply print all ids and then search after them.
You can do this in c4d by searching in the c4d __dict__ . Personally i have a small macro in 
sublime text which produces a agent ransack search string out of the c4d console output (strip 
everything not a number, kill doubles and connect everything with an OR).

agent ransack will come up with that for your plugin :

resource\coffeesymbols.h 173,00 KB 19.04.2013 11:20:42
5798 BFM_GETCURSORINFO=1667853926,
5830 BFM_GOTFOCUS=1648838211,
5831 BFM_LOSTFOCUS=1649165891,
5870 BFM_ACTION=1648444244,
5893 BFM_ACTIVE_CHG=1648444231,
5981 BFM_CORE_MESSAGE=1298360653,
5994 BFM_INTERACTSTART=1768846433,
5995 BFM_INTERACTEND=1768846437,
6028 BFM_FADE_REMOVEALL=1178682437,

so to fix your plugin you have to do this :

def Command(self, id, msg) :
        if (id == 1012) :
            print "file: ", self.GetString (1012)
        return True       
       
    def Message(self, msg, result) :
        if (msg.GetId() == c4d.BFM_ACTION) :
            cid = msg[c4d.BFM_ACTION_ID]
            val = msg[c4d.BFM_ACTION_VALUE]
            print 'Msg ID:', cid, ' Val:', val
            self.SetString(cid, val)
        return gui.GeDialog.Message(self, msg, result)

edit : and to be extra clear before someone starts complaining, the fixed code is super 
unsafe due laziness, practically you have to check both the action id and value if they are 
valid. you could do this by passing it to command().

On 02/06/2013 at 11:44, xxxxxxxx wrote:

Thank you very much.
Also thanks for the patience.
I''ll try to do something back, by putting python tutorials on my blog.

Thanks again. I keep learning good stuff from you and this forum.