Full file path for textures



  • On 17/02/2015 at 03:21, xxxxxxxx wrote:

    Hi,
    I need to extract the full file path for all textures using python scripting. So I was iterating over all the textures and trying to extract the file path. But in some cases eg. when the texture file is in the project path or in tex folder or in any of the search paths, we get only the file name and not the full file path.

    So I wrote my code such that in cases where only file name is available, look for the file in the below order -

    • in project path
    • in tex folder
    • in all the search paths
      If the file is found in any of these, save the full path.
      This works when the file names in all these paths are unique. But if there are duplicate names, it is not possible to determine which path to save. How do I handle such cases? Or is there a simpler way to extract texture paths which I am missing out?

    Thanks.



  • On 18/02/2015 at 02:18, xxxxxxxx wrote:

    Hi,

    although this topic may seem trivial, it is unfortunately not.
    In C++ you'd use GenerateTexturePath(), but this is currently not available in Python.

    So you need to try to do this manually. GenerateTexturePath() uses the following order:

    I hope this helps.



  • On 18/02/2015 at 03:52, xxxxxxxx wrote:

    Hi Andreas,
    Thanks for your inputs, they do help. However, there are still few confusions that I have :

    • in your first point, what is meant by suggested folder?
    • if I have more than one texture files having same name e.g. water.jpg in documentPath and a different water.jpg in one of the the texture paths, say tex1/water.jpg. I have linked tex1/water.jpg with a texture. Now, going by the mentioned order, my path would be resolved as documentPath/water.jpg, which is incorrect. How do I handle this case?

    Thanks again for your help.



  • On 18/02/2015 at 04:02, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    • in your first point, what is meant by suggested folder?

    Have a look at the GenerateTexturePath() docs I linked to. It's one of the input parameters.

    Originally posted by xxxxxxxx

    • if I have more than one texture files having same name e.g. water.jpg in documentPath and a different water.jpg in one of the the texture paths, say tex1/water.jpg. I have linked tex1/water.jpg with a texture. Now, going by the mentioned order, my path would be resolved as documentPath/water.jpg, which is incorrect. How do I handle this case?

    All I can say is, in what order C4D resolves texture paths. In your case, I see at least two options:

    • have an absolute path to the texture
    • use a good naming scheme for storing your textures (as long as there are equally named textures in several texture search paths, you will end up with this confusion in one way or the other)


  • On 20/02/2015 at 03:22, xxxxxxxx wrote:

    Hi Andreas,
    Thanks for your inputs.
    Unfortunately, we cannot restrict our customers to any particular naming scheme. 
    As we can communicate between C++ and Python using ctypes etc., it should be possible to invoke the C++ GenerateTexturePath() method from Python.
    Could you please give an example how we can use the C++  GenerateTexturePath() method in our python code?

    Thanks.



  • On 20/02/2015 at 07:58, xxxxxxxx wrote:

    Hi,

    unfortunately, while it is in theory possible to call functions from a (C++) library in Python using ctypes (and I myself thought this might be an option), this works only if you have a separate library, which then could be made available in Python. This is not possible with the C++ SDK. I also thought about providing the code of GenerateTexturePath() (as I revealed the internal already...), but there are so many dependencies on Cinema's core, this wouldn't work either.

    So your best bet is to use the info I gave on the internals of GenerateTexturePath(). This is how C4D is searching for textures.

    But as said before, this solves your problem only half way. I wish I had a better idea of what you are actually trying to achieve. From what I know so far, you will probably have to write a C++ plugin. Therein you not only have access to GenerateTexturePath(), but could also write a SceneHook (which isn't possible in Python, either) to properly act on loading/saving a scene file. There you could quite easily detect all needed assets and the respective absolute paths.

    I'm sorry, this is not the answer you want to hear. But I honestly don't see any other options (given my current state of knowledge about what you are trying to do).

    Cheers,
    Andreas



  • On 30/03/2015 at 11:30, xxxxxxxx wrote:

    This is more than a little annoying.

    Devs, clearly C4D has the full path to the texture or it wouldn't be able to display it.

    Why can't we get this through Python?
    There is no way to be sure you have the right file, unless you get it from C4D.
    You can't control customers, and you can't search recursively.

    This is a major oversight.

    😠



  • On 30/03/2015 at 12:02, xxxxxxxx wrote:

    Where is your problem? Andreas has given great information on how Cinema 4D searches for textures
    and it can easily be ported to Python. The only thing that I would need is some additional information on
    how to use ConvertRelative2Absolute().

    Niklas



  • On 30/03/2015 at 14:30, xxxxxxxx wrote:

    Yes, you can search, but as mentioned earlier, people use identical texture names and put them in different folders.  Especially with image sequences.  E.g., frame001.png, frame002.png, etc.

    If you start with a file name and search recursively through the paths he mentions, you could find many files with the same name, but in different folders. There is no way to know which file retrieved with:

    shader[c4d.BITMAPSHADER_FILENAME]
    

    is the one being used in C4D.

    Or am I missing something?



  • On 30/03/2015 at 16:06, xxxxxxxx wrote:

    Yes there is, Cinema searches for the files in exactly the order Andreas described.

    Originally posted by xxxxxxxx

    The first file you find this way is the same file that Cinema will use.



  • On 30/03/2015 at 17:30, xxxxxxxx wrote:

    Let me explain in more detail:
    My customers drop a texture on a plane, and my plugin detects that and gets the full path with:

    shader[c4d.BITMAPSHADER_FILENAME]
    

    This works fine, unless C4D finds out that the path to the file is already set in the preferences.
    In that case, the code above only returns the file name portion and not the path.

    In this example, C4D is not searching for the file is it?
    It already has the full path when the file is dropped on the plane.

    If my plugin searches in the order above, then it could find a similar file name in another folder couldn't it?



  • On 31/03/2015 at 06:32, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    Let me explain in more detail:
    My customers drop a texture on a plane, and my plugin detects that and gets the full path with:

    shader[c4d.BITMAPSHADER_FILENAME]
    

    This works fine, unless C4D finds out that the path to the file is already set in the preferences.
    [...]

    Are you talking about the Preferences > Files > Texture Paths settings?



  • On 31/03/2015 at 08:52, xxxxxxxx wrote:

    Yes, but the same thing happens if the image file is in the document path.
    C4D only exposes the file name, and not the path when you call:

    shader[c4d.BITMAPSHADER_FILENAME]
    

    If I then do a recursive search in the order Andreas suggested, my plugin could find the same file name, both in the document path, and in one of the Preferences>Files>Texture Paths.
    I don't see a way to know for sure which one it would be in that case.



  • On 31/03/2015 at 08:54, xxxxxxxx wrote:

    Hi terrachild,
    two posts ago you were asking "C4D is not searching for the file is it?"
    But yes it is, and it does so exactly in the order I described.



  • On 31/03/2015 at 08:57, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    Yes, but the same thing happens if the image file is in the document path.
    C4D only exposes the file name, and not the path when you call:

    shader[c4d.BITMAPSHADER_FILENAME]
    

    If I then do a recursive search in the order Andreas suggested, my plugin could find the same file name, both in the document path, and in one of the Preferences>Files>Texture Paths.
    I don't see a way to know for sure which one it would be in that case.

    Yes there is, the first file  that is found by following the order Andreas described is the file that Cinema
    will use.



  • On 31/03/2015 at 12:21, xxxxxxxx wrote:

    Okay, Niklas, I did some more testing.
    It seems that if you drop a texture on a plane, C4D always looks first to see if it is in the document path; and if it isn't, then it prompts you with: "This image is not in the project search path..."

    It seems to do this even if you have set up texture paths in:  Preferences > Files > Texture Paths
    **
    **
    If it is in the project search path, then it will use it, and expose only the file name with:

    shader[c4d.BITMAPSHADER_FILENAME]
    

    I can detect that, and then prompt the customer with a file browser to give the path.

    Just to confuse the matter more: If you drop a texture on a plane from a folder named 'tex', that is located next to the project file, then C4D doesn't give you the prompt to copy.  If the texture is in a nested folder like this "tex/1/pic.jpg", it doesn't give you the prompt.  If the texture is in a nested folder like this "tex/2/pic.jpg", it does give you the prompt.  It doesn't search the folders in the project path very consistently.

    I guess I need to know if C4D always ignores the texture paths, set in the preferences, and prompts to make a copy of the texture?

    If so, I'm fine.  I can just tell the customer to always select 'No' at the prompt, and force C4D to expose the full path from Python.

    Why is it ignoring the texture paths set in preferences when you drop a file on a plane though?

    Thanks for you help NiklasR!
    **
    **
    **
    **



  • On 01/04/2015 at 10:05, xxxxxxxx wrote:

    Hi Chris,

    Cinema 4D doesn't store anything else than what you see in the bitmap shader. It is either a absolute path or just the filename, if the texture is in the texture search path. The texture search path I described earlier in the exact same order, Cinema 4D searches.

    I also did some test and I can't reproduce your findings.
    Here's what I did:
    I set up the following project structure:
    ./test_scene
    ./test_scene/tex
    ./test_scene/tex/1
    ./test_scene/tex/2
    The scene got stored in ./test_scene and in each of these directories I put an image. Furthermore I stored an image in the "global" search path (under Windows that's in Users\USERNAME\AppData\Roaming\MAXON\CINEMA 4D R16_... ex), which kind of works the same as any path configured additionally in the preferences.
    From all these places I dragged in the image and I never got asked, if the file should be imported, and C4D stored only the filename in the bitmap shader.
    Then I dragged in an image from an arbitrary directory (not in the described search paths) and I was asked, if the file should get imported. I answered "No" and the absolute path got stored in the bitmap shader.
    So I can confirm for me Cinema 4D behaves like its code suggests and as I described.



  • On 09/04/2015 at 10:26, xxxxxxxx wrote:

    Hi guys,

    Just my 2 cents about the dilemma of how far an application should search (not just Cinema 4D, any app on a computer that has file storage using directories), and the fact that two files with different content can have the same name.

    You reveal two competing problems:

    1. "It's bad when the wrong file is chosen, it's best if it would just fail and prompt the user for the correct file"

    2. "It's bad that an app doesn't search far and wide enough to find the file"

    This is a fundamental computer issue with no clear solution, so everyone is expected to work within these limitations, even if somewhat masked by GUI based OSes.  When trying to solve 1, you increase the chances that 2 occurs, and vice versa.  That's why there are specific paths checked in a rigid order, from the closest in the directory hierarchy (usually a subdirectory) to farthest away, often passing through mostly reliable 'shared' directories.  Going up a level in the directory hierarchy usually exposes you to increased chance of finding the wrong file, as we may inadvertently call similar but different content by the same file name by habit.  At the extreme, searching all the hard disks on a computer for a file is asking for trouble, hence why that is very rarely done, even as a last resort.

    However, there's the other angle to consider that was stated above: "you can't control customers".  The assumption that if they are using your software, which is certainly aimed at experienced computer users, they should know how to use a computer properly.  That includes understanding the dilemma about file naming and directory organization.   You should consider it a problem outside of your responsibility, as you can't control sloppy computer file (dis)organization on someone else's system.  If it worries you a lot or they have given you trouble in the past, you should provide guidelines and warnings to your customers about file search paths.  This is the norm for other applications, even if it's not always clearly stated.

    I hope that helps.

    Joey Gaspe
    SDK Support Engineer



  • On 09/04/2015 at 12:21, xxxxxxxx wrote:

    My problem is very simple actually:

    1. A user drops an image file on a plane.
    2. My plugin detects that and needs the full path.

    That's it.

    C4D has the full path when the user drops it.  It doesn't, or shouldn't have to, search for it.  All programs have the full path to a drag and dropped file.  Why can't I get this?

    But I don't seem to be able to get that path.  It isn't stored in the shader settings unless C4D displays the pop-up dialog I mentioned earlier that asks if you want to make a copy of the file, and the user selects 'No'.

    If C4D finds the file in one of its search paths, then that dialog doesn't pop up, and only the file name is stored in the shader.

    If only the file name is stored in the shader, then I guess I have to do a search in the order that C4D does it.

    Here's what doesn't make sense to me about this:  If the user drops a file on a plane, that image is going to be used no matter what.  Is that correct.?

    Even if C4D searches, using the order mentioned above, and finds a different image with that same name earlier in its search order than the dropped file occurs in its search order, are you saying it will use the out of order search result?  If not, then if you drop one file, it could display a different one.  Is that correct?  Surely, it won't do that.

    If this out of search order file is displayed when it is dropped, then what about the next time the file is opened and C4D searches.  Will it display the different image found earlier in the search?

    Good lord, I just need the path of a dropped image.



  • On 10/04/2015 at 06:50, xxxxxxxx wrote:

    Hi,

    I did some more testing on this topic.
    Let's assume you have this structure:
    ./test_scene
    ./test_scene/tex/walter.jpg
    And in the global texture search path you have another walter.jpg.
    If you now drag the walter.jpg from the global search path into your scene, C4D will actually ask you "This image is not in the project search path. Do you want to create a copy at the project location?", although the image is in the global search path. It does so, in order to resolve the file collision. If you choose "Yes, import to project dir", the file will get renamed and copied into ./test_scene/tex/, only the filename will be stored in the scene. And if you answer "No", the absolute path will be stored in the scene.

    Which in the end means for you: You can still use the above mentioned search order, if you only have a filename, as C4D already cared for the file collision.


Log in to reply