Open Texture using CallButton

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

I want to open a texture in my scene.

Looking at the interface, you click Open Texture and then a standard file dialog opens and you can select a file. I want to do this 'automatically'. I already have the filename.
I can simulate OpenTexture using CallCommand or CallButton, but I do not know the ID's for the different dialog fields (to simulate) : "File Name" and "Open".
Are the ID''s part of a OpenTexture DLG or the standard file dialog. If so, which Tool to use for the CallButton?

So something like this

OpenTexture_ID=170001 # Open Texture...
    OpenTexture=c4d.plugins.FindPlugin(OpenTexture_ID, c4d.PLUGINTYPE_ANY)

c4d.CallButton(OpenTexture,set filename)
    c4d.CallButton(OpenTexture,Open)
    
Here the complete code of what I''m trying to do.

import c4d, os
from c4d import bitmaps, gui, plugins, utils
  
### Open Texture ###
  
PLUGIN_ID = 14500219 #TestID only!!!!!!!!!!!!
  
GROUPBUTTON         = 1030
MY_OPENBUTTON       = GROUPBUTTON + 1
  
def OpenTexture() :
    texturename = "studio003.hdr"
  
    #c4d.CallCommand(170001) # Open Texture...
  
    OpenTexture_ID=170001
    OpenTexture=c4d.plugins.FindPlugin(OpenTexture_ID, c4d.PLUGINTYPE_ANY)
    print "OpenTexture tool: ", OpenTexture
    #c4d.CallButton(OpenTexture,c4d.IDS_RM_M_OPENFILE)
    
    #FilesTool_ID=465001626
    #FilesTool=c4d.plugins.FindPlugin(FilesTool_ID, c4d.PLUGINTYPE_ANY)
    #print "FilesTool: ", FilesTool
    
    #c4d.CallButton(FilesTool,c4d.IDS_RM_M_OPENFILE)
  
    return True
    
class MyDialog(gui.GeDialog) :
  
    def CreateLayout(self) :
        self.SetTitle("Open Texture.")
        self.AddButton(MY_OPENBUTTON, flags=c4d.BFH_LEFT, initw=150, name="Open Texture")   
        return True
        
    def Command(self, id, msg) :
  
        if (id == MY_OPENBUTTON) :
            OpenTexture()
            return True
                      
        return True
  
class MyOpenTexture(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=200, defaulth=200)
    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__":
  
    pluginstr = "Open Texture v01"
    bmp = bitmaps.BaseBitmap()
    dir, f = os.path.split(__file__)
    fn = os.path.join(dir, "res/icons", "IconChar.tif")
    bmp.InitWith(fn)
    
    plugins.RegisterCommandPlugin(id=PLUGIN_ID, 
                                  str=pluginstr,
                                  info=0,
                                  help=pluginstr, 
                                  dat=MyOpenTexture(),
                                  icon=bmp)

On 04/06/2013 at 06:17, xxxxxxxx wrote:

I am not sure what you want to do. Do you want to pass a path to the os load file dialog
to be used as the starting folder ? Doesn't the filename gadget do that when writing the 
path into its textbox  by default ?
If not, you have to build your own filename gadget out of a textbox and a button. The raise
a open file dialog with the button. storage.LoadDialog() supports a default path.

On 04/06/2013 at 06:41, xxxxxxxx wrote:

What I want to do is to open a texture using the Open Texture command.
But I do not know how to do that is Python.
Using the CallCommand is not enough, because after the CallCommand a file dialog opens where I have to fill in the filename and click the Open Button.

How should I do all of this in Python.

I hope his explains what I want

On 04/06/2013 at 06:53, xxxxxxxx wrote:

Ah ok, your first posting actually explained it just fine, I should have red more carefully but I 
got confused by the wall of text :)

CallCommand() does obviously support no additional parameters. You have to to use one
of the SendCommand methods if you want to specify a parameter. Check :

c4d.modules.bodypaint.SendPainterCommand()

edit : I haven't used the method yet, but i guess the flag PAINTER_LOADTEXTURE will 
do, what you are looking for.

On 05/06/2013 at 01:53, xxxxxxxx wrote:

Sorry, no success. This is what I tried:

def OpenTexture() :
    texturename = "studio003.hdr"
   
    doc = c4d.documents.GetActiveDocument()
    c4d.modules.bodypaint.SendPainterCommand(c4d.PAINTER_LOADTEXTURE, doc=doc, tex=texturename)
    
    return True

This gave the error:
TypeError: argument 3 must be c4d.modules.bodypaint.PaintTexture, not str

Next attempt

    settings = c4d.BaseContainer()
    settings.SetString(c4d.LOADTEXTURE_FILENAME, texturename)   
  
    doc = c4d.documents.GetActiveDocument()
    c4d.modules.bodypaint.SendPainterCommand(c4d.PAINTER_LOADTEXTURE, doc=None, tex=None, bc=settings)

Now c4d crashes

Next attempt:

    settings = c4d.BaseContainer()
    settings.SetString(c4d.LOADTEXTURE_FILENAME, texturename)   
    painttext = c4d.modules.bodypaint.PaintTexture()  
  
    doc = c4d.documents.GetActiveDocument()
    c4d.modules.bodypaint.SendPainterCommand(c4d.PAINTER_LOADTEXTURE, doc=doc, tex=painttext, bc=settings)

This gave the error:
This type cannot be instantiated

On 05/06/2013 at 02:58, xxxxxxxx wrote:

try first one with an absolute path again, it should work, or you have found a bug.
make sure you escape your path string correctly (we had that one often in the last
time, so no offense ;) ).

On 05/06/2013 at 03:25, xxxxxxxx wrote:

Originally posted by xxxxxxxx

try first one with an absolute path again, it should work, or you have found a bug.

I changed the filename to: texturename = r"D:\studio003.hdr"
 
Sorry, I do not think that having a relative path is the issues.
C4d does not complain that it can''t find the texture.
I changed it to an absolute path, but still the same issues:

1) TypeError: argument 3 must be c4d.modules.bodypaint.PaintTexture, not str
2) crash, because tex = None?
3) This type cannot be instantiated

So, if I can instantiate it correctly, it might work.

Could you please tell me how to instantiate a PaintTexture?

Regards, Pim

On 05/06/2013 at 04:32, xxxxxxxx wrote:

Hm, took a look at it, your second version in the first posting seems to be technically correct, 
and the crashing is definitely a sign for a bug. For instantiating the PaintTexture  - you can't - 
it is not implemented. You might have some luck with other Bodypaint bitmap class types and
then weasel your way somehow back, but the parent/ super class PaintBitmap is abstract 
which meas we are not meant to instantiate it at all.

I guess you can just hope that a maxon employee explains how module was intended, the
whole thing seems rather buggy, but I might be wrong.

On 05/06/2013 at 04:38, xxxxxxxx wrote:

Ok, thanks for all the support and effort.

I guess I have to find another way or hopefully, like you say, Yannick can ask the programmers.

On 05/06/2013 at 08:45, xxxxxxxx wrote:

The wrapped Python version of SendPainterCommand() is bugged.
You can see this old thread for the C++ API that shows how to use PAINTER_LOADTEXTURE command.
It works fine in C++ but crahes in Python.
Also the documentation isn't accurate because it tells to pass the texture to tex parameter while PAINTER_LOADTEXTURE command returns the PaintTexture if the call was successful.

I'll report this issue.

On 06/06/2013 at 00:26, xxxxxxxx wrote:

Originally posted by xxxxxxxx

The wrapped Python version of SendPainterCommand() is bugged.
You can see this old thread for the C++ API that shows how to use PAINTER_LOADTEXTURE command.
It works fine in C++ but crahes in Python.
Also the documentation isn't accurate because it tells to pass the texture to tex parameter while PAINTER_LOADTEXTURE command returns the PaintTexture if the call was successful.

I'll report this issue.

Ok, thanks for the information.
Of course the next question is: when will it be solved.

In the mean time, is it difficult to call C++ modules from Python?

On 24/06/2013 at 10:37, xxxxxxxx wrote:

Pim,
I tried IM'ing you back but your messages inbox is full. So I hope you see this reply.

The answer to your question is yes. The images in the BP texture window are actually layers.
A more accurate name for the texture window would be the "Texture Layer Window".
The working C++ version for this is here:https://plugincafe.maxon.net/topic/7242/8316_selecting-images-in-thetexture-view-window

I took a look at converting it to Python. But that would require the following:
-Loading the image file as a PaintTexture object
-Saving that as a new layer
-Selecting that layer so it shows in the texture window

There's no documentation on creating PaintTexture objects. So I got stuck right away with the conversion. But Yannick also mentioned that the wrapper itself has bugs in it. So this might not be possible in Python yet.

-ScottA

On 24/06/2013 at 12:38, xxxxxxxx wrote:

Hi ScottA,

Yes, the inbox is limited to 5 messages. So indeed full.

Thanks for the clear reply.
More and more I am considering switching over to C++.

Regards, Pim