Tk package and tcl files

It seems that Tk needs some .tcl files (like init.tcl) to works.
Those files are in the panda3d SDK but not into the Tk package downloaded through runtime.panda3d.org.

The error produced is :

_tkinter.TclError: Can't find a usable init.tcl in the following directories: 
[...]

This probably means that Tcl wasn't installed properly.

A workaround I have tried were to build my own Tk package hosted on my side. This way I included the tcl files into my Tk package. But I just realised that Tk is probably not aware of the panda3d VirtualFileSystem… so it couldn’t found and open tcl files.

What do you think ?

vash

That’s a good hypothesis. I haven’t extensively tried to make Tk work in the runtime yet, but I’m sure it should be possible. Maybe we should force init.tcl to be included and instruct the runtime to extract this file (similarly to how we extract .dlls, which cannot be loaded from the VFS either).

It’s exactly what I have done :slight_smile:. I have packaged those tcl files and extracted them at runtime… It works but it’s maybe done in an ugly way…
Maybe panda is doing things better than me for the dll files ? Where can I found the dll’s extraction code to ensure that I am not over-coding things for nothing.
After that I would be glad if I can contribute to the build of a new tk package and extraction for panda3d.

Also I have similar issue for the cursor files.
It seems that they cannot be loaded directly through the vfs… I tried to backtrace this. And first I realised that vfs firstly points on start/ directory (in AppData/Local/Panda3D/ on windows). On the other side, packages are mount in their own installation directory (in …/hosts/domainname/packagename/versionNum/).
For loader.loadTexture() it founds files with the original pathname given on packaging. But for PNMImage() I should use the mounted package pathname in the relative way (…/hosts/…/image.png) or in the absolute way (/c/…/hosts/…/image.png ).
For cursor, it’s just impossible to open it through a vfs… It blocks in this part of panda3d sources (x11GraphicsWindow.cxx:1905) :

// If it wasn't found, resolve the filename and search for that.
  Filename resolved = filename;
  if (!resolved.resolve_filename(get_model_path())) {
    // The filename doesn't exist.
    x11display_cat.warning() << "Could not find cursor filename " << filename << "\n";
    return None;
}

Some lines below, it’s calling the vfs. But in this part they are no reference to vfs (so it returns None and so it stops here the cursor loading)… is Filename module knowing the vfs ? I’m not sure of this… The resolve_filename() and exists() methods always return ‘False’ on my cursor pathname.
My cursor file is in the package (according to the result of ‘multify -vfs mypackage.mf’).

So, am I missing somethings ? Is it a panda3d strange behavior ? A is it a bug ? May I have to extract my cursor files outside the vfs ?

Thanks for your answers.

Great! Could you share your .pdef file, so that I can fix the tk package properly?

You can add extract=True as parameter to file() in the pdef file, this will make Panda automatically extract the file when running the p3d.

The Filename module is a low-level module that uses OS calls, and is not aware of the VFS. I’ve changed the code to use vfs->resolve_filename(resolved, get_model_path()) instead, just checked it into CVS.

Aaarg, the ‘extract’ keyword is so magic ! I have done all the work by myself without expecting this…

So ok, now it works in the “panda3d” way.
Here is the pdef of tk :

class tk(package):
    config(display_name = "Tk GUI Toolkit")
    require('panda3d')

    module('Tkinter', required = True)
    module('direct.showbase.TkGlobal', 'direct.tkpanels', 'direct.tkwidgets')
    file(Filename(os.environ["PATH_PYTHON_LIB"]+"../tcl/tcl8.5", "*.tcl"), newDir = "tcl8.5", extract = True)
    file(Filename(os.environ["PATH_PYTHON_LIB"]+"../tcl/tcl8.5", "tclIndex"), newDir = "tcl8.5", extract = True)
    file(Filename(os.environ["PATH_PYTHON_LIB"]+"../tcl/tk8.5", "*.tcl"), newDir = "tk8.5", extract = True)
    file(Filename(os.environ["PATH_PYTHON_LIB"]+"../tcl/tk8.5/ttk", "*.tcl"), newDir = "tk8.5/ttk", extract = True)
    packager.setHost('http://127.0.0.1/packages/')

Actually os.environ[“PATH_PYTHON_LIB”] point to the python lib hold by panda3d sdk.

Also I didn’t use the dir() inclusion for 2 reasons :
1 - I suspect dir() directive to exclude files that doesn’t match predifined extensions (.png, .jpg, …).
2 - The files included with the file() directive seems sufficient for my usage of tk.

After that I setup os.environ[“TCL_LIBRARY”] and os.environ[“TK_LIBRARY”] to where tk8.5 and tcl8.5 were extracted.

Also thanks for your support and the correction on the CVS.
Last questions : Is resolve_filename will search into each mounted filetree ? What about PNMImage ? According to the panda3d texture loader, it should search through the mounted filetree I think.

Thanks again for all your help and your efforts to decrypt my (really not perfect) english.

vash

Thank you. That only works on Windows, so I’ve added this to the section in thirdparty.pdef instead:

        from Tkinter import Tcl
        dir = Filename.fromOsSpecific(Tcl().eval("info library"))
        file(Filename(dir, "*.tcl"), extract = True)

It seems to work on my Mac. I’ve checked it into CVS and it will be in the upcoming 1.8.1 release.

resolve_filename, if passed get_model_path(), will search in the model path. Package directories (like the “tk” package directory when mounted) are automatically added to the model path when the package is loaded.

If you want to add custom directories to the model path, use getModelPath().appendDirectory or prependDirectory. Again, this is not necessary if the files are located in a p3d package.

Alternatively, you can also specify directories to add to the model-path in your Config.prc file, using an instruction like:

model-path $MAIN_DIR/icons

($MAIN_DIR refers to the directory containing the main application file, eg main.py.)

Or, create your own DSearchPath with your own directories and pass that to resolveFilename.