[Closed] Extending Structs
I want to add new ListView functions but the NET_ListViewWrapper in stdscripts/stdplugs already has an instance of the ListViewOps struct called “lvOps”. I would like to add additional methods to this struct and not replace it, but I can’t quite figure out how to do this. Any advice?
well maybe I can’t understand what are you trying to do, but if you want to add new function to ListViewOps , just write your function inside the struct. the struct being instantiated should not bother you.
The problem is that I don’t want to touch the original file. I don’t want to modify or change the NET_ListViewWrapper.ms file, which is where the struct is, nor do I want to duplicate the code inside of my own struct. I want to be able to extend the struct in ‘whatever.ms’. I know you can do this in classes in C# but I wasn’t sure if I can do anything like it in maxScript.
nope – can’t do that (add properties/functions to existing structs), not to built-in structs, and not to scripted structs.
With scripted structs you could try, real hard, by identifying the struct and then all its properties and functions (this being particularly difficult) within, get everything that’s using that struct (good luck), then redefine the struct and make everything that was using the original struct use the new one, transferring their existing settings.
Yeah – can’t do that sums it up just fine
if you want it to be
I don’t often find myself needing to extend scripted structs, though. They’re typically transient entities, meaning they’re not intended to be saved with the scene. If I want them to be more stable and the ability to extend them, remove from them, update them… a scripted plugin or custom attributes block is much more appropriate.
That doesn’t help with third party structs, of course… nor max internal ones.
Updating e.g. the ‘renderers’ struct would have been pretty nice if it were possible, for some of our scripts; but oh well
Oh well that wasn’t TOO hard
(this won’t work on your machine as-is since it uses my struct to mash together, make your own!)
fn getStructFnArr theStructDef =
(
local fnNames = #()
global getStructFnArr_fnStr = stringStream ""
local exStr = "print (" + theStructDef + " as string) to:getStructFnArr_fnStr"
execute exStr
seek getStructFnArr_fnStr 0
while (not eof getStructFnArr_fnStr) do
(
local l = (readLine getStructFnArr_fnStr) as string
local isFn = matchPattern l pattern:"*<fn>*"
if isFn == true then
(
local fnName = (filterString l ":")[1]
append fnNames (trimLeft fnName)
)
)
(fnNames)
)
--EXTENDING LVOPS
/*we need to initialize a struct with DATA member names the same as our listviewops struct
we will then fill in the data with references to the struct functions, for example:
struct testDef (d1, d2)
testInst = testDef listViewOps.clearColumns
testInst.d1()*/
fn extendStruct refName def1 def2 =
(
--first get an array of all the function names in the original struct, and the one we are adding to it
global fnNames = getStructFnArr def1
local fnNames2 = getStructFnArr def2 -- we need to use seperate arrays for the reference part, in our refStr execute
fnNames
--create our alternative struct definition
local autoStructName = refName + "AutoStruct"
local structStr = "struct " + autoStructName + "
(
"
for a in fnNames do
(
local str = " " + a + ",
"
append structStr str
)
for a in fnNames2 do
(
local str = " " + a + ",
"
append structStr str
)
structStr = trimRight structStr ",
"
append structStr ")"
execute structStr
--create an instance of the struct, and we set the data members in the for loop
execute ("global " + refName + " = " + autoStructName + "()")
for a in fnNames do
(
local refStr = refName + "." + a + " = " + def1 as string + "." + a
execute refStr
)
for a in fnNames2 do
(
local refStr = refName + "." + a + " = " + def2 as string + "." + a
execute refStr
)
execute refName
)
--and to use it...
extendstruct "lvOps" "ListViewOps" "robg3d_lvOps"
Only handles function only structs, I will make it handle ones that contain data as well.
The main reason I’m doing this is for those ‘common function’ structs. In this case it is just lvOps, but let’s say you have a stOps struct for common string functions (as I do), and you don’t want to edit it directly- this way you can extend it. Not ultra useful but hopefully someone will benefit… probably as close to class extension as we’ll get.
Another Edit: It is somewhat limited because of the built in classes/structs, such as skinOps, which I cannot extend. But it would be possible to mash together your own structs and skinOps into a universal ‘skinOps2’… but I don’t see the demand to do this, tbh, it isn’t like people are mashing together lots of skin functions from a variety of sources.
well sure, if you already know the struct. But in that case you might as well just redefine the thing from the get-go (after 3ds Max initializes, say), and you’re all set.
Extend, for kicks, extend this struct, adding a new variable.
struct test_s (
local var = 5,
fn func param1 param2 = ( format "% %
" param1 param2 )
)
test_a = test_s()
test_b = test_s()
But assume you do -not- know the above source code. All you have is the ‘test_a’ instance of the struct.
Then once extended, adjust test_b to use the new struct. One catch: you don’t know test_b exists. In other words, devise a way to find all instances of the original struct so that you can replace them.
That’s what I thought the challenge was; if you already know the full original struct then that’s just no fun
I don’t have the source of any struct or function. I am creating a new struct definition with references to all the members of the original structs.
For example, the only reason this doesn’t work:
extendstruct "skinOps" "skinOps" "robg3d_lvOps"
is because skinOps is a read-only variable (boooo!), even though skinOps is compiled.
(Also, see the edits I made, you posted while I was editing I think)
Sneaking little…
Well now that’s not quite ‘extending an existing struct’
Does the intended job fine, though – so I’ll quit harassing ya