ZBrushCentral

Strings in memory

Hi folks!
I think I ran into a dead end and hope you can show me a hidden path out of it :D.
Possibly my lack of understanding how to properly work with the [Mem] functions, is a big part of this issue.

What I want to do:
For a script I am currently working on I want to add/or subtract Subtools from a list.
If it is not yet part of the list, add it - otherwise remove it.

Currently I do this by:
-[StrFind] if the currently selected Subtool is part of the list
If not:
-[StrMerge] padded with a few special characters to prevent mixups, to the list
If already present:

-Exclude by splitting the list in two (before and after the entry) and [StrMerge] the two pieces back together again.

Adding and removing this way actually works pretty well!

list_problem.gif

My problem:
The problems start to arise though, when the list of Subtool names gets too long. Sofar I stored the list in a “normal” variable, but already knew that I had to move them to memory at some point.
Usually I do this using MVar, but I suppose the limits for them are the same as for normal variables.

Because of this I wanted to work with the [Mem] functions. But I can’t wrap my head around how to properly work with them.
I can store/increase/read their size, but that is as far as I got :(.
Is there a way to compare a new string, with what I have stored into a memory block?
Like [StrFind,newName,[MemReadString,storedNames]]?

I came across this thread in which Marcus describes, how to add items to a list stored in memory and write it to a .txt file.
This way I was able to write my list to a file and it really worked well!
But I got stuck again, as I could not find a way how to compare with the string stored in the .txt file.
I played around with [MemCreateFromFile] and it’s size increased when the list got longer, but then I found myself having the same issue as before:
How do I compare with data stored in memory?

Ideally I would not want to write a file anyway. This sounds like a pretty costly operation, so preferably I would only want to compare with data temporarily stored in memory.
So any help would be much appreciated!

A little follow up:
I spend some more time with the [Mem] functions and think I now understand how to use them. Unfortunately let me realize, that I would still run into the 255 char limit as I would need to create a variable to store the extracted string in.
I guess it would be still doable, by reading through multiple chunks using the offset of the [MemReadString] function. But I came to the conclusion, that this would be too much effort, since there would also be the downside of having issues with name duplicates.

I found another way to tag Subtools though. I add a specially named layer to the selected Subtools and look for it while crawling through the Subtoollist. This of course is not as elegant and less performant. On the flipside this seems pretty foolproof to me, even when having name duplicates or switching to a different tool.

Hope this insight might help someone at some point (or me if I forget why I decided to go this way :D)

I may be missing something but why are you storing the subtool names in a single string? It would be easier to create a list variable such as
[VarDef,subtoolName(300),""]
and store the names in that. (This is for 300 names but that’s arbitrary. You simply need it to be big enough to hold all the strings you are likely to need.)

You could then loop through and search for the string without the need for extra characters or encountering the 255 char limit. This method has the added advantage that the number of the variable can correspond to the subtool number so that:

[SubToolSelect,0]
[VarSet,sTName,[IGetTitle,Tool:ItemInfo]]
[VarSet,sTName,[StrExtract,sTName,0,[StrLength,sTName]-2]]//trim off period
[VarSet,subtoolName(0),sTName]

will set the first subtoolName variable to the name of the top subtool.

HTH,

Thank you very much for your answer Marcus!
I briefly thought about storing the names in an array, but dismissed the idea. I feared the list might get fragmented too fast, by removing/readding subtools.
To be honest I might just be too inexperienced working with strings/arrays, and it would be easy to avoid. Or not an issue at all simply by creating enough buffer space.

The “tagging via layer” approach was a dead end (technically working, but WAY to sluggish and prone to issues with a bigger layer stack/duplicates). Therefore I will take a look into your suggestion, thanks again for the snippet!

Ok wow… I really feel stupid now for wasting that much time when the answere was within arm’s reach.
Thank you so much for giving me a push in the right direction!

Incase someone looks for a way to add and remove subtools from an array, this might be a starting point:

[VarDef,subtoolNameList(300),""]

[IButton, “add/remove subtool to list”, ,
[VarSet,subtoolName,[IGetTitle,Tool:ItemInfo]]
[VarSet,subtoolName,[StrExtract,subtoolName,0,[StrLength,subtoolName]-2]]//trim off period
[VarSet,unique,1]

[Loop,300, [If, [StrFind,subtoolName,subtoolNameList(loop1)] == 0, //dublicate [VarSet,subtoolNameList(loop1),""] [Note,"dublicate"] [VarSet,unique,0] [LoopExit] ] ,loop1] [If,unique == 1, [Loop,300, [If,[StrLength,subtoolNameList(loop2)]<1, [VarSet,subtoolNameList(loop2),subtoolName] [Note,"new entry"] [LoopExit] ] ,loop2] ]

]