.res help



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 03/09/2012 at 16:42, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   R13 
    Platform:   OS X  ;   
    Language(s) :   Python  ;

    ---------
    Considering how simple it is to add user data within the C4D gui, you'd think the same would be true of making a plug-in, but after staring at these three files for several hours now and plowing through two dozen forum posts, I'm quite frustrated.

    I'm also puzzled that Python object plug-ins use C++ to setup their GUI instead of relying on a Python based GUI within the plug-in itself.

    I've heard there's some great examples of how to do this in the C++ SDK, but the navigation on that page is ridiculously unhelpful (I type ".res" into the search panel and get zero results).

    So here's my .res file, and the accompanying errors. I don't even know what the first one is even referring to. The second one seems to be some sort of formatting error, and since I don't know C++, I'm not able to interpret it. Everything seems to be formatted exactly like all the other example plug-ins I've looked at, so I'm not sure what's wrong with this one.

    I should note that every time I make a modification to the code, I will delete the symbolcache file at:
    User --> Library --> Preferences --> MAXON --> C4DR13... --> Prefs

    Any help would be greatly appreciated.

    Here is an image of the code with correct spacing, etc if needed:
    http://www.lukeletellier.com/wp-content/uploads/downloads/2012/09/res-code.png

    CONTAINER genome		
    {
    	NAME genome;
    	INCLUDE Obase;
      
    	GROUP ID_MAIN
    	{
    		REAL P1			{ UNIT METER; }
    		REAL P2			{ UNIT METER; }
    		REAL P3			{ UNIT METER; }
    		REAL CHAMFER	{ UNIT METER; MIN 0.0;}
    	}
    } 
    

    Symbol 'genome' not found
    File '/Applications/MAXON/CINEMA 4D R13/plugins/genome/res/description/genome.res'
    Line 3

    Error reading resource
    file '/Applications/MAXON/CINEMA 4D R13/plugins/genome/res/description/genome.res'
    Line 7
    --
    --
    Many thanks,
    Luke



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 03/09/2012 at 23:53, xxxxxxxx wrote:

    Hello Luke,

    for information in the C++ documentation, you need to search for Description Resource. Note that they differ from Dialog Resources.

    _> >> I'm also puzzled that Python object plug-ins use C++ to setup their GUI instead of relying on a Python based GUI within the plug-in itself. _

    The GUI-resource is parsed and built by the application, which is written in C++. What do you mean with Python based GUI?

    > >> I should note that every time I make a modification to the code, I will delete the symbolcache file at:
    > >> User --> Library --> Preferences --> MAXON --> C4DR13... --> Prefs

    Yes, this is necessary when you changed the name of a symbol of you have added new symbols. Instead of deleting it by hand every-time, you can just remove it at startup of Cinema 4D within your plugin while you are developing. But do not deliver your plugin when it is still removing the symbolcache. It would be rebuild every startup, and the actual use of the symbolcache is to prevent this rebuilding.

    To your code: Have you actuall added a resource-header and stringtable? You do not mention something about them. It is not enough to just have a resource-file. Cinema would not know the name of the element (in the GUI) nor the integer-ID the symbol is assigned to. Therefore, you need to more files.

    The first error looks like you haven't specified the name of the genome symbol. When you insert the NAME genome; command, a name must be assigned to the given symbol.

    The second error looks like you did not define an ID for the P1 symbol.

    Additionall, the first group in an Object Plugin is usually called ID_OBJECTPROPERTIES , not ID_MAIN.

    Do you other two files (if there are actually any) look somewhat like this?

    res/description/genome.h

    #ifndef _GENOME_H_    // In case someone wants the symbols in a C++ plugin, one needs this include-guard.  
    #define _GENOME_H_  
      
      enum {  
          genome = <plugin-id>,  
          P1 = 1000,  
          P2,  
          P3,  
          CHAMFER  
      }  
      
    #endif // _GENOME_H_
    

    res/strings_us/description/genome.str

    STRINGTABLE genome {  
      genome "Genome Object";  
      P1 "P1";  
      P2 "P2;  
      P3 "P3";  
      CHAMFER "Chamfer";  
    }
    

    Note that you should use prefixes for your symbols. Nobody knows what P1 refers to, but GENOME_P1 immediately tells you that the symbol is part of the GENOME plugin.

    -Niklas



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 04/09/2012 at 01:29, xxxxxxxx wrote:

    Just a couple of small points to add:

    The ID_OBJECTPROPERTIES convention simply guarantees that the first tab after Basic and Coords in your object's GUI is called 'Properties'. If you don't want it to be, simply rename the group and provide entries for it in the .h and .str files.

    It's only a personal POV but I never use auto-enumeration in enums. It looks easy to use but sooner or later doing that is going to bite you on the butt, hard. If you give individual numbers to all your enums you know exactly where you are. Just IMHO of course.

    Steve



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 04/09/2012 at 06:23, xxxxxxxx wrote:

    Wow. This is helping a lot. Thank you so much for helping despite last night's grumpiness on my part. This profession is such a roller coaster ride of emotions...

    Since your pointers helped me fix my problem, I thought I'd list out what I actually did so that anyone else having this same problem who might be ghosting the forum in later months can pick up on it.

    Here's my 'genome.h' file:

    #ifndef _genome_H_
    #define _genome_H_
      
    enum
    {	
        genome = 1029036,
        P1 = 1001,
        P2 = 1002,
        P3 = 1003,
        CHAMFER = 1004 
    }
    #endif
    

    The issue with this page was that I had not included the line "genome = 1029036", which is basically "[Name-of-Plugin-defined-in-.res-file] = [PluginID]" without brackets. This portion is missing from many plug-in templates. Also of note: every template I found had long spaces between each name and it's equals. These don't seem to be necessary - I took them out without issue.

    genome.str:

    STRINGTABLE genome
      
    { 
      genome "Genome Object";
        P1 "Port 1";
        P2 "Port 2";
        P3 "Port 3";
        Chamfer "Chamfer";
    }
    

    Again, I had not specifically given genome a name. And long spaces do not seem to be necessary here either.

    Two more questions to round out the post.

    1. Niklas, you recommended removing the symbol cache file from within the plugin. While I know I could manually spell out the location of the file to have it removed, I thought that there might be a built-in function made for accessing the C4D preferences folder on a given system. Is that true? Having built in functions to reference that folder as well as the plug-ins folder would be quite useful.

    2. When I first start up my plug-in, I create a Python Effector. I've figured out how to add code directly into the effector's code attribute box ("PyEffector[c4d.OEPYTHON_STRING]="). However, I am not doing it that efficiently, as all the code that I insert into the effector is written right in the source code for my plug-in, and I basically do a big copy and paste to get it in there.

    It would make much more sense to create the code in a separate .pyp file stored in my res directory, then import that into the code slot on my effector.  I seem to remember a topic in this forum that addressed the issue, but I can't find it. (I think Chris Smith was involved in the discussion...he might have been the one asking the original question. Not positive though).

    I would also like to know how I might encrypt that incoming code, so that someone cannot open up the Python Effector and copy and paste the code into another effector.

    If there's a well known thread that addresses either of these issues, please point me there. The wording of some of these issues is so generic that Google has trouble picking out the right threads when I search for them.

    Once again, thank you for your assistance,
    Luke



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 04/09/2012 at 07:42, xxxxxxxx wrote:

    I would also like to know how I might encrypt that incoming code, so that someone cannot open up the Python Effector and copy and paste the code into another effector.

    Afaik, like other native script objects, like the coffee and py expressions, I'm not aware
    of any way to protect what is clearly put into them.

    Regarding the "symbolcache" issue, despite my efforts to get some info how to handle it
    without manually deleting it or hacking it with a separate .py file I still haven't got
    an answer.
    So what I do is to set up the .res .h and .str files as usual but only use them for
    creating the GUI.
    In the plugin file (myplugin.py) I don't use the symbols from the files.
    Instead the numerical value of them.

    So instead of:
    myparameter = myplugin[c4d.ID_THING]

    I run:
    myparameter = myplugin[1234]

    (This means that auto number the objects in the .res file is not a good idea :) )

    While I still have to restart Cinema for changes, I don't have to delete the
    "symbolcache" file. This means that updating plugins is much leaner especially
    for the headless apps of NET.

    @Niklas.
    Just curious, why is it that you are using the pluginID in the .res files first group?
    To the best of my knowledge, starting with "1000" is sufficient and using the plugin ID
    is only needed in the registering part of the Plugin.

    Cheers
    Lennart



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 04/09/2012 at 08:29, xxxxxxxx wrote:

    Thanks TCA for the notes. That makes a lot of sense, and is very helpful as I was having a lot of difficulty getting python to recognize the correct path for the symbolcache file for deletion purposes.

    I went into the terminal, dragged my symbolcache file into it to get the correct path, then inserted it into the following.

    import os
    os.remove(path)
    

    It would result in an error message saying that the file/directory could not be found. If your technique overrides the need to figure that out, I will be very grateful.

    ~~I'm still having a little difficulty getting the user submitted data from the interface into myplugin.py.  ~~
    ~~
    ~~
    Here is what I have so far in my .py file, with 'genome' being the name of the plugin and 'reset' being a boolean switch. I'm trying to create a situation in which "If 'reset' is switched on, do the following".
    ~~
    ~~
    ~~

    reset = genome[1001]~~
     ~~if reset == 1:~~
     ~~  print "it works!"
    

    ~~
    ~~
    ~~
    Figured that one out. Had to add "reset = op[c4d.RESET]".



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 05/09/2012 at 09:29, xxxxxxxx wrote:

    @Lennart:
    @Niklas.
    Just curious, why is it that you are using the pluginID in the .res files first group?
    To the best of my knowledge, starting with "1000" is sufficient and using the plugin ID
    is only needed in the registering part of the Plugin.

    > Hey Lennart. My symbols do start with "1000". But I additionally add the ID of the plugin itself. This way the symbol is also exposed the c4d module and will be available for C++ developers as well when including the resource-header.
    >
    >

    import c4d  
    \> obj = c4d.BaseObject(c4d.genome)
    

    >
    >

    #include "genome.h"  
    \> // ...  
    \>   BaseObject* op = BaseObject::Alloc(genome);
    

    >

    @Luke:
    1) Niklas, you recommended removing the symbol cache file from within the plugin. While I know I could manually spell out the location of the file to have it removed, I thought that there might be a built-in function made for accessing the C4D preferences folder on a given system. Is that true? Having built in functions to reference that folder as well as the plug-ins folder would be quite useful.
    > The error when removing the file should not actually appear. Have you copied and pasted the full path to the file? Note that Windows uses backslashes for path-separation, so you need to add a small r before your actual string starts to inhibit possibble backslash-escapes.
    >
    >

    path = r"C:\Users\niklas\AppData\Roaming\MAXON\CINEMA 4D R13_05DFD2A0\prefs\symbolcache"  
    \> if os.path.exists(path) :  
    \>   os.remove(path)
    

    >
    > You can obtain the path to the prefs-folder with c4
    > c4dd.storage.GeGetC4DPath(c4d.C4D_PATH_PREFS).
    >
    And long spaces do not seem to be necessary here either.
    > The spaces don't say anything. You could theoretically write the header like this:
    >

    #ifndef _genome_H_  
    \> #define _genome_H_  
    \> enum { genome=1029036,P1=1000,P2,P3,CHAMFER};  
    \> #endif // _genome_H_
    

    > A C compiler would accept it. I don't know if the Cinema 4D parser allows to write everything in one line.
    >
    Luke, I just want you to note once again that your naming does not fit the Cinema 4D convention.

    -Niklas



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 05/09/2012 at 10:35, xxxxxxxx wrote:

    The error when removing the file should not actually appear. Have you copied and pasted the full path to the file? Note that Windows uses backslashes for path-separation, so you need to add a small  r  before your actual string starts to inhibit possibble backslash-escapes.

    The r fixed the problem, and the symbol cache is now being deleted. However, it doesn't seem to be re-created each time I start. For instance:

    1. I check in my prefs folder; symbolchache is there. I start up Cinema, and in my console I receive my notification that the symbolcache file has been deleted. I shut Cinema down, and check in my prefs folder, and the symbol cache file is still missing - it has not been regenerated.

    2. I start up Cinema once again, this time I do not receive my notification that the file has been deleted. But if I check in the prefs folder, I see that it has been re-generated.

    3. When I shut down and start up for a third time, it is a repeat of #1. Notifcation is there, but the file does not regenerate.

    Is this normal behavior? Is this code snippet something that I should be sticking within my python_init file within my /prefs/python/ folder? Right now it runs on lines 10-14 of my plug-in's main pyp file, right after I import C4D & os.

    Originally posted by xxxxxxxx

    Luke, I just want you to note once again that your naming does not fit the Cinema 4D convention.

    -Niklas

    Could you elaborate more on this, maybe with an example? When I initially read though your first post, I didn't quite understand that section, so when my plug-in began to work without error, I thought I had 
    inadvertently accomplished what you had said I needed.

    Here are the appropriate files as I have them now:

    Genome.res:

    CONTAINER Genome		
    {
    	NAME Genome;
    	INCLUDE Obase;
      
    	GROUP ID_OBJECTPROPERTIES
    	{
    		GROUP MAIN
    		{
    			BOOL UPDATE      { ;} 
    			BOOL SOLO       { ;}
    		}
    		GROUP CONVERTCLONER
    		{
    			BOOL CONVERT    { ;}
    			LINK CLONER     { ;}
    		}
    		GROUP CREATEXPRESSO
    		{
    			BOOL CREATE_X   { ;}
    			LINK OBJECT_TO_CONTROL     { ;}
    			LINK TAGHOLDER  { ;}
    		}
    	}
    } 
    

    Genome.str:

    STRINGTABLE Genome
      
    { 
    	Genome "Genome Object";
    	MAIN "Main";
        UPDATE "Update";
        SOLO "Solo Source Object";
        CONVERTCLONER "Convert Pre-existing Cloner";
        CLONER "Cloner to Convert";
        CONVERT "Convert Cloner";
        CREATEXPRESSO "Create Basic Xpresso Setup";
        CREATE_X "Create Xpresso Nodes";
        OBJECT_TO_CONTROL "Object to Control";
        TAGHOLDER "Xpresso Tag Holder";
    }
    

    Genome.h:

    #ifndef _Genome_H_
    #define _Genome_H_
      
    enum
    {	
      	Genome = 1029036,
        UPDATE = 1001,
        SOLO = 1002,
        CLONER = 1003,
        CONVERT = 1004,
        CREATE_H = 1005,
        OBJECT_TO_CONTROL = 1006,
        TAGHOLDER = 1007,
        MAIN = 1008,
        CONVERTCLONER = 1009,
        CREATE_X = 1010,
        CREATEXPRESSO = 1011
    }
    #endif
    

    Once again, thank you all for this. 
    Luke



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 05/09/2012 at 12:52, xxxxxxxx wrote:

    Hi Luke,

    to the symbolcache thing: I don't know how Cinema 4D handles this internally. I guess this is the normal behaviour. It doesn't seem to result in any issues. Note that Cinema 4D start-up will slow down when you really delete the symbolcache every start. It will need to go through each resource-header from the application itself and third-party plugins to retrieve all the symbols that are used in Python and COFFEE. And these are quite a lot of files which can take some seconds.

    The the naming-conventions: It's simple. You have added symbols to be used for your plugin. One of your symbol, just for example, is "UPDATE" with id "1001". Cinema 4D will parse your resource-header (Genome.h) and add this to Pythons and COFFEEs symbols (and write it into the symbolcache). This way, you can access your symbol via the C4D module. (print c4d.UPDATE will print "1001"). The problem is, that no one except you actually knows what "UPDATE" refers to. That's why every symbol is prefixed. (MSG_, COPYFLAGS_, DIRTYFLAGS_, VIEWCOLOR_, PRIM_, etc.). You should prefix every of your symbol with what it refers to. I.e. "UPDATE" turns into "GENOME_UPDATE", "CREATEXPRESSO" turns into "GENOME_CREATEXPRESSO", etc.
    The next thing is more a minor thing, but plugin ID symbols (such as Ocube, Tdisplay, Mmaterial, Xbitmap, etc.) are prefixed as well. As you might have guessed, object-plugins with "O", Tags with "T", Materials with "M", Shaders with "X", etc.
    This again makes it easier to identify what the symbol refers to. Also, prefixing the names with what they refer to avoids name-collisions.
    You don't have to stick 100% with the naming of Cinema 4D, but the prefixing-issue is very important.

    I'm currently working on a C++ plugin suite I called Pr1mitive as it implements some new primitives for Cinema 4D and other features. I have chosen a strict naming-convention that I apply to all parts of the project (which doesn't mean to every project I'm working on). Here's an excerpt from my resource-files for a parametric Pillow object (well, looks like a pillow).

    Opr1m_pillow.h

    // coding: UTF-8  
    //  
    // Copyright (C) 2012, Niklas Rosenstein  
      
    #ifndef _OPR1M_PILLOWSHAPE_H_  
    #define _OPR1M_PILLOWSHAPE_H_  
      
      enum {  
          Opr1m_pillow = 1028986,  
          PR1M_PILLOW_SIZE = 1000  
      };  
      
    #endif // _OPR1M_PILLOWSHAPE_H_
    

    Opr1m_pillow.res

    // coding: UTF-8  
    //  
    // Copyright (C) 2012, Niklas Rosenstein  
      
    CONTAINER Opr1m_pillow {  
      NAME Opr1m_pillow;  
      INCLUDE Obase;  
      
      GROUP ID_OBJECTPROPERTIES {  
          VECTOR PR1M_PILLOW_SIZE { MIN 0 0 0; UNIT METER; CUSTOMGUI SUBDESCRIPTION; };  
      }  
      
      INCLUDE Opr1m_complexshape;  
    }
    

    Opr1m_pillow.str

    // coding: UTF-8  
    //  
    // Copyright (C) 2012, Niklas Rosenstein  
      
    STRINGTABLE Opr1m_pillow {  
      Opr1m_pillow        "Pillow Shape";  
      PR1M_PILLOW_SIZE    "Size";  
    }
    

    Cheers,
    -Niklas



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 05/09/2012 at 14:26, xxxxxxxx wrote:

    Thank Niklas - I can understand why that's important.

    And your plug-in looks pretty cool. I've been watching your thread at CGsociety, and it's very impressive. Nice work!


Log in to reply