[Closed] Structs with functions
I was wondering if someone could explain or show and example to me on what is the benefit of putting a function in a struct?
I understand how to use structs but I do not see the immediate benefit of putting a function inside of one. I’m not sure if my example is one that really displays the benefits of functions in structs.
example:
struct person (
name,
height,
age,
sex,
fnWirecolor obj = (
obj.wirecolor = random black white
)
)
I think of it as like Methods… I’ve changed your example to be more the way a function inside a struct would work instead of referencing outer variables.
struct person (
name,
height,
age,
sex,
fn CalculateWeight = (
(height * 10) + (0.2 * age)
)
)
Then for every instance of the struct you can call this function and it will reference everything inside the struct.
bob = person "Bob" 174 21 "Male"
bob.CalculateWeight()
That’s my interpretation anyway, I know other people use them differently.
encapsulation…
and stuff like this…
struct AnInterface
(
private
version = 1.1,
sourcefile = "D:/Development/3dsMax/MaxScript/interfaces/AnInterface.ms",
public
-- Get this version
fn getVersion = version,
fn getSourceFile = sourcefile,
-- Installs this script into "stdplugs/stdscripts/"
fn Install =
(
file = getSourceFile();
sourcefileModdate = getFileModDate file;
filename = filenameFromPath file;
stdscriptsdir = (getdir #maxroot) + "stdplugs/stdscripts/";
destfile = stdscriptsdir + filename;
need_to_update = false
if doesFileExist destfile then
(
destfileModdate = getFileModDate destfile;
if sourcefileModdate != destfileModdate then
need_to_update = true;
)
else
need_to_update = true;
if need_to_update then
(
deleteFile (stdscriptsdir + filename);
copyFile file (stdscriptsdir + filename);
)
),
fn GetFacesFromVerts obj verts =
(
faces = polyop.getFacesUsingVert obj verts[1]
for v = 2 to verts.count do faces *= polyop.getFacesUsingVert obj verts[v];
faces
),
-- more functions here
on create do install()
)
-- create an instance of our interface
global library = AnInterface();
then you call your functions with
library.GetFacesFromVerts obj verts
Very cool.
I appreciate booth of your examples they make a lot of sense and have surely opened my eyes to more ways to use structs. These are great. They can make things much simpler.
Thank you both.
Yep I use structs as a library of functions all the time I have a Math struct that I can call when doing math operations.
math.mirror cross:x flip:y
math.getOffset $[1] $[2]
this way I do not need to rewrite it every time I need it or nor do I need to keep various scripts open. One of the tools I give to clients also contains a library of functions that are used by a variety of characters, I do not need to give them a new script every time because once they have placed that main script in their system I know I can call upon select functions doesn’t matter the character
PePeTD
That is a very good idea. It seems like that is a good way to build a foundation of scripts, and like you said eliminate the rewriting of scripts.
another example showing encapsulation…
-- 2D binary tree packing demo
fn compare v1 v2 =
(
v1min = amin v1.width v1.height;
v2min = amin v2.width v2.height;
d = v2min - v1min;
if d == 0 then
(
v1max = amax v1.width v1.height;
v2max = amax v2.width v2.height;
d = v2max - v1max;
)
d;
)
fn RandomColorGen src_color = ( 0.5 * ((random (color 0 0 0) (color 255 255 255)) + src_color))
struct leafnode
(
pos,
width,
height,
down,
right,
used,
fn init xy w h d:undefined r:undefined u:false =
(
pos = xy; width = w; height = h; down = d; right = r; used = u;
)
)
struct rect
(
pos,
width,
height,
flip = false,
fn printf = (format "x:% y:% w:% h:%
" pos.x pos.y width height; ),
fn makeshape =
(
if pos != undefined then
(
rct = rectangle length:height width:width cornerRadius:0 pos:[width * 0.5,height * 0.5,0]
rct.wirecolor = random (color 0 0 0) (color 255 255 255);
rct.pivot = [0,0,0];
rct.pos = [pos.x,pos.y,0];
)
),
fn toBitmap dest_bm =
(
if pos != undefined then
(
source_bm = bitmap width height color:(RandomColorGen (color 232 232 255))
pasteBitmap source_bm dest_bm (box2 0 0 width height) pos;
close source_bm;
)
)
)
struct packer
(
width,
height,
rectangles,
root = leafnode(),
fn onCreate = ( root.init [0.0,0.0] width height; ),
fn addrect r = ( append rectangles r),
fn findleafnode leaf w h =
(
result = undefined;
if leaf != undefined and leaf.used then
(
newleaf = findleafnode leaf.right w h;
if newleaf != undefined then
result = newleaf;
else
result = findleafnode leaf.down w h;
)
else if leaf != undefined and w <= leaf.width and h <= leaf.height then
result = leaf;
result;
),
fn splitleafnode leaf w h =
(
leaf.used = true;
leaf.down = leafnode [leaf.pos.x,(leaf.pos.y + h)] leaf.width (leaf.height - h) undefined undefined false;
leaf.right = leafnode [(leaf.pos.x + w), leaf.pos.y] (leaf.width - w) h undefined undefined false;
leaf.pos;
),
fn sortit compfn = (qsort rectangles compfn),
fn pack =
(
for r in rectangles do
(
if (leaf = findleafnode root r.width r.height) != undefined then
r.pos = splitleafnode leaf r.width r.height;
else
r.pos = undefined;
)
),
fn show =
(
bm = bitmap width height color:white
for r in rectangles do r.toBitmap bm;
display bm;
),
on create do onCreate()
)
thePacker = packer 200 200 #();
thePacker.addrect (rect [0,0] 50 50)
thePacker.addrect (rect [0,0] 100 100)
thePacker.addrect (rect [0,0] 100 50)
thePacker.addrect (rect [0,0] 50 50)
thePacker.addrect (rect [0,0] 50 100)
thePacker.addrect (rect [0,0] 50 50)
thePacker.addrect (rect [0,0] 50 50)
thePacker.addrect (rect [0,0] 100 100)
thePacker.sortit compare;
thePacker.pack()
thePacker.show()
fn MaxVal a b = (res = a; if a < b then res = b; res)
fn MinVal a b = (res = a; if a > b then res = b; res)
is it more than just a sample? …
hmm… amax. hmm… amin.
no idea why I wrote my own functions and does it matter ? really, in a demo snippet.
fixed it as not to offend Denis
Member order counts unless you do some instantiation, for example:
struct my_struct
(
fn b =
(
a()
),
fn a =
(
print "working"
),
EndOfStruct
)
test = my_struct()
test.b()
This would break but you can get around it with this:
struct my_struct
(
self,
fn b =
(
self = my_struct()
self.a()
),
fn a =
(
print "working"
),
EndOfStruct
)
test = my_struct()
test.b()
A better solution for that problem is using forward declarations:
struct my_struct
(
-- forward declaration
function a=(),
function b =
(
a()
),
function a =
(
print "working"
)
)
a problem regarding member variable declaration order that remains is discussed here:
http://forums.cgsociety.org/showthread.php?p=7444135#post7444135
As posted in that thread’s last post, it has been confirmed to be a bug in maxscript, lets hope for some fix in upcoming Max releases…