Start a new topic

One Click Button for Adding Group Beads On Externals.

Original Post by: Wed Dec 3 21:11:46 2014


Hi,


I want to ask something regarding External references. I find it really difficult to add Group Beads to external files. Like if I converted 10 models to external references, now i want each externals to be under individual Group beads, also those group beads should have the same name of the external referenced file. I thought about adding a button to do than in one shot.

In creator we have insert level option but still we have to rename each Group bead matching the name of External file. Is it possible to do? Can you suggest the way or a sample to do that? These are the painful stuffs to do if its only 10 Group beads still manageable to do but if that number increases renaming manually is a hectic task. Is there any way to automate it through a button?


Original Post by: SteveThompson Wed Dec 10 15:42:08 2014


Yeah I’m able to get the file name and change the group bead name, but it says in status message bar that id already exists

This is expected because as we said earlier nodes must have unique names. You cannot assign two nodes the same name. So in your case, if you have two instances of the same external reference and you want to name each of their group parents to match the x-ref name, it won't work. You'll have to figure out some other strategy for naming the parents. If no x-ref is referenced more than once, you're ok but as soon as you reference the same x-ref multiple times, your renaming strategy fails.

Original Post by: Wed Dec 10 16:15:22 2014


That is why I was trying to filter the name and then to apply it. Is that impossible?

Original Post by: ChrisRogers Wed Dec 10 16:42:03 2014


I don’t know how to implement that in the code I wrote. Can anyone of you help me in adding that string function in the code I provided above.


The function I wrote you just needs to be copy pasted above any other function that uses it.


That is why I was trying to filter the name and then to apply it. Is that impossible?


It is possible to modify the name, but keep in mind your method for modifying the name needs to be different for each node. You need to decide a naming scheme though. Perhaps appending a number that changes each time?

Original Post by: SteveThompson Wed Dec 10 16:57:23 2014


That is why I was trying to filter the name and then to apply it. Is that impossible?

Sorry if I was not clear in my post. Let me try to clarify.


From what you say, you want to rename the parent group node above each external reference to the file name part of the full path of the x-ref. So if, say, you had an external reference named e:\db\tree.flt, you would rename its parent group "tree".


You can certainly do this, the code is very straightforward. Chris is trying to help you with the C string functions to do this. What I was saying is that since you are not allowed to name two nodes in the scene the same name, this renaming strategy will be limited if you have two external references that reference the same file.


Consider this scenario... you have three "tree" external refs each referencing the same external file e:\db\tree.flt. This is possible and very likely. You can put different translation, rotation, scale transforms on each of the three instances to get three "different" trees each using the same x-ref file. If you have this and you try to rename each of the three group parent nodes using the name part for each, it will work when you rename the first group parent, you can rename it "tree" fine. But when you try to rename the 2nd and 3rd group parent nodes you will try to rename them "tree" and that will fail because you already named the 1st group parent "tree".


I hope that better explains what we were trying to say. You can certainly rename nodes but you cannot rename two or more nodes the same name.

Original Post by: Wed Dec 10 17:22:13 2014


That is why I was trying to filter the name and then to apply it. Is that impossible?

Sorry if I was not clear in my post. Let me try to clarify.

.

.

.

.


I hope that better explains what we were trying to say. You can certainly rename nodes but you cannot rename two or more nodes the same name.


Yeah strictly there wont be any instances / duplicates of same name because once we add and rename the group node then we duplicates external references in case if its needed but till the renaming process there wont be any duplication.

I understood what Chriss was trying to explain about string function but can you show that added in my code because when i tried its showing compiling errors and all due to lack of knowledge in C.If you can modify my code please show me how it can be done with the funtion Chriss showed.

Original Post by: SteveThompson Wed Dec 10 17:26:22 2014


Yeah strictly there wont be any instances / duplicates of same name because once we add and rename the group node then we duplicates external references in case if its needed but till the renaming process there wont be any duplication.

I don't understand this... if you duplicate the external reference, the name of the duplicate will be the same name as the original - they both reference the same x-ref file. You have not avoided the core problem. If you reference the same x-ref file more than once, you will not be able to uniquely rename the parent nodes.

Original Post by: Wed Dec 10 18:19:01 2014


I don't understand this... if you duplicate the external reference, the name of the duplicate will be the same name as the original - they both reference the same x-ref file. You have not avoided the core problem. If you reference the same x-ref file more than once, you will not be able to uniquely rename the parent nodes.


What I meant is, I wont be duplicating any external files in same FLT. Like as u said if one is "Tree" next will be "Tree_1" or "Hangar1" etc. So there wont be duplicates of external files. Each one will be having unique names. I just wanted the way to extract that particular models name without path and . flt extension.

If you can correct that in my code that will give me an idea and I can learn a bit from that too.

Original Post by: SteveThompson Wed Dec 10 18:39:50 2014


Sorry, I believe we are still not communicating clearly on this.


Consider this example. Lets say you have an external reference of e:\db\tree.flt. The

"name" of this external refererence is "e:\db\tree.flt". If you duplicate this x-ref, the name of the duplicate will be "e:\db\tree.flt". Note that the "name" of the x-ref is not a name like other names, it is the name of the OpenFlight referenced. So when you say you will duplicate the x-ref to get Tree and Tree_1, that is just not going to happen. Again when you duplicate an x-ref, the name of the original and the name of the duplicate will be the same since they reference the same external file.


If, on the other hand you have one single x-ref and rename its parent group to be the name part and then duplicate the group, yes, the first group will be tree and the second group will be tree_1. But the x-ref under each will still have the same names.


So perhaps I don't fully understand how your tool will work. But now that you know that a duplicate of an x-ref has the same name as the original, you have all you need to write your tool properly.

Original Post by: SteveThompson Wed Dec 10 19:28:24 2014


I just wanted the way to extract that particular models name without path and . flt extension.

Sounds like you are still unsure about how to use the function Chris gave you in your code. I understand how "string" (or more generally, "array") functions can be a bit confusing to beginner C programmers. Once you grasp them a bit, you will be much better off.


Instead of just giving you the answer, I'd like to try to walk you through it a bit. Hopefully this will help you to answer future questions before you need to ask them.


Ok...


The first thing you need to understand is what a character string is in C. It is an "array" of char (sometimes called "character array" or "pointer to char") and is declared like this:


char* string;


So given that, the function Chris wrote takes a character array (pointer to char) as a parameter and also returns a pointer to char. The pointer it returns is the address of the character in the original string where the file name starts.


So if you start with a character string that is:


e:\folder1\db\name.flt


The original character array (pointer to char) points to the first "e" of the name. In your code the xName is such a pointer and points to the first "e" in the name.

The return value of the function will be the address of the "name" part in the original character array, which will point to the "n" of "name.flt".


Hopefully this makes sense. If it does not, I suggest that you study the C language a bit more. A good grasp of C strings (arrays and the entire C language) is very important when using the OpenFlight API.


Anyway, if you now understand that the function takes a character string as a parameter and returns a pointer the "name" part within the parameter string, you should be able to follow this next bit.


Right now you are passing the original name to mgSetName. Instead of passing the original name here, you need to pass the return value of this function after passing to it the original name.


This would look like this in your final code (I fixed a minor problem with Chris' original function - it was not returning a value when it could not find the slash)



const char* PathToFilename(const char* path)

{

const char* location1 = strrchr (path, '/');

const char* location2 = strrchr (path, '\\');

const char* lastSlash = location1 > location2? location1: location2;

if (strlen (lastSlash) > 0)

return & lastSlash[1]; // strip off the beginning slash;

else // I added this "else" bit

return path;

}


static mgbool gbeadNApply (mgrec* db, mgrec* parent, mgrec* rec, void* gBead)

{

toolrec* toolRec = (toolrec*)gBead;

if (mgGetCode(rec) == fltXref)

{

char *xName;

const char *namePart;

mgGetAttList(rec,fltXrefFilename,& xName,MG_NULL);

// get a pointer to the name part of xName

namePart = PathToFilename(xName);


// pass that to mgSetName, not xName

mgSetName(parent,namePart);

}

return MG_TRUE;

}


Hopefully this makes sense. Note that Chris' function does not do exactly what you really want. For a file name like: "e:\db\name.flt", it returns "name.flt". From what you said earlier in this post, you really want just "name". This is a bit more complicated but if you now understand how Chris' function works, it should not be too difficult for you to strip off the ".flt" part. Let us know if you can't sort that part out either.


Good luck and hang in there with C. It is worth learning well!

Original Post by: SteveThompson Wed Dec 10 19:43:39 2014


I don't want to overwhelm you but there is another part of your code that you should consider.


When you use mgGetAttList to retrieve a string attribute, mgGetAttList returns a string "copy" that has been allocated for you to use. That way if you were to modify the string returned to you, you would not affect the node directly, just the copy of the string.


That said, to avoid a memory leak in your program you should "free" the string attribute the API allocated and returned to you. You should also consider more error checking in your code (but that is a whole other topic).


Anyway, here is a suggestion on how you might modify the previous snippet I gave you to include both proper string "free" and error checking to make sure you don' free "bad memory"


// initialize xName to NULL so we know mgGetAttList returned something valid

char *xName = NULL;

int numAttr;


// mgGetAttList returns the number of attributes it actually returned.

// you can use this value to make sure you got something

// in this case if numAttr is 0, then fltXrefFilename was not found on the node

numAttr = mgGetAttList(rec,fltXrefFilename,& xName,MG_NULL);


// here is some error checking

// we make sure mgGetAttList returned exactly 1 value and we check to make sure

// the value it returned to us is not NULL - only when both of these conditions

// are true should we actually trust the xName is something useful


if (numAttr == 1 && xName != NULL)

{

// get a pointer to the name part of xName

const char* namePart = PathToFilename(xName);

// pass that to mgSetName, not xName

mgSetName(parent,namePart);


// if you don't free xName, you will have a memory leak

mgFree(xName);

}

Original Post by: Thu Dec 11 18:45:05 2014


Thanks Steve & Chriss finallly I got what i wanted :) ...


I Used this to remove ".flt"


const char* trimFlt (const char* s){

int n;

int i;

char* new;

for (i = 0; s != '\0'; i++);

n = i - 5 + 1; // lenght of the new string

new = (char*) malloc (n * sizeof(char));

for (i = 0; i < n; i++)

new = s;

new = '\0';

return new;

}


Original Post by: SteveThompson Thu Dec 11 18:57:00 2014


Note that since you "malloc'ed" this string, you should "free" it or your plugin will have a memory leak.


Enjoy!

Original Post by: Thu Dec 11 18:58:19 2014


Note that since you "malloc'ed" this string, you should "free" it or your plugin will have a memory leak.


Enjoy!


Sure Thanks :)

Login to post a comment