Notifications
Clear all

[Closed] Struct problem – Struct member access requires instance

Hi,

I am in the process of upgrading some old scripts, and one of the tips I’ve got is to make structs of my function collections. At the moment I have a struct patterned like this:


 global SSR_gui
 struct SSR_gui
 (	
    function getControllers amount = 
    (
 	   -- A function that returns controllers in the scene based on amount string
    ),
    
   function clearKeys amount frameRange =
   (
 	  -- This function calls getControllers, and clears keys in the returned controllers
   ),
 
   function offsetKeys amount frameRange =
   (
 	  -- This function does the same, but offsets keys
   )
 )
 

Functions two and three calls the first function for a list of objects, something that worked fine when these were just separate functions in my .ms file. But now that they are inside a struct, they both return “– Runtime error: Struct member access requires instance: getControllers”

I have a ton of other functions – but only these two (so far) are giving me problems. Does anyone know what could be causing this?

11 Replies

here is one way:


 struct str
 (
 	fn a = (print "a"),
 	fn b = str.a()
 )
 

there are another.

It looks like your have defined your structure properly but you need to create an instance of it before you can use it. Usually you would do this by assigning the constructor StructureName() to a variable.

struct SSR_gui
 (	
    function getControllers amount = 
    (
 	   -- A function that returns controllers in the scene based on amount string
    ),
    
   function clearKeys amount frameRange =
   (
 	  -- This function calls getControllers, and clears keys in the returned controllers
   ),
 
   function offsetKeys amount frameRange =
   (
 	  -- This function does the same, but offsets keys
   )
 )
global gui = SSR_gui()

Now if you are calling the function offsetKeys from outside the structure you would use:

gui.offsetKeys [I]amount frameRange[/I] 

And from functions inside the structure you can use:

SSR_gui.offsetKeys [I]amount frameRange[/I] 

EDIT: Looks like Denis beat me to it…

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

you’ve shown another way. (one of another ;))
technically your way is safer and i prefer just that one. because using a structure instance you can easy extend your structure with some default values or extra structures…

the using of structures is probably most popular way today to organize functions, values, settings, rollouts, forms, etc. in one place.
but Struct still has some limitations…

there is another way almost forgotten. it’s utilities… check the sample:


utility ControllerUtilities ""
(
	local defaultInterval = #all
	struct keyData (key, controller, extra)
	
	fn isKeyInRange k range = k.time >= range.start and k.time <= range.end
	fn collectKeys controller range:animationrange = if iscontroller controller and controller.keyable do
	(
		case of
		(
			(range == #all):
			(
				for k in controller.keys collect (keyData key:k controller:controller extra:k.time)
			)
			(iskindof range Interval):
			(
				for k in controller.keys where isKeyInRange k range collect (keyData key:k controller:controller extra:k.time)
			)
		)
	)
)

/*
animationrange = interval 0 100
delete objects
b = box()
animate on 
(
	at time 20 move b [10,10,10]
	at time 200 move b [10,10,10]
)
ControllerUtilities.collectKeys b.pos.controller.x_position.controller 
*/

Yes, I prefer using an instance. As you said, you can assign values, rollouts, dotNet maxForms etc to members after instancing.

I think there’s a typo in my post, calling functions from inside the structure you should use:

offsetKeys amount frameRange
2 Replies
(@feranti)
Joined: 11 months ago

Posts: 0

Furthermore, to get rid of functions order, you should even use

this.offsetKeys amount frameRange

That way, you can call a functions inside the same struct, no matter their order in the script. I noticed that several times and always put his in front of function calls.

(@raytracer05)
Joined: 11 months ago

Posts: 0

That’s a very good point. I have had problems with function order but must have been able to find a solution by changing the order in the structure because I don’t think I’ve ever solved it your way.

Thanks for all your tips – I’m learning a lot of new tricks here!

This worked fine:

struct str  
 (
 	 fn a = (print "a"), 
  	fn b = str.a()  
 )

But in some of my structs this seems to work fine:

struct str  
 (
 	 fn a = (print "a"),
 	 fn b = a()  
 )

Anybody know why it can work in some and not in others?

I also have been predeclaring the functions at the top of the struct, but in this fashion:


  struct str  
 (
 	         -- pre-declerations
 	 fn a = (),
 	 fn b = (),
  
 	         -- definitions
 	         fn a = (print "a"), 
  	fn b = str.a()  
 )

Sometimes it works because you’re testing things and declaring functions and structs in a global scope and then next time you go to restart max it won’t work as it won’t have been declared already.

I can’t seem to create a situation where your second example works but I bet it’s something to do with scopes.

It still looks to me like you’re mixing the two methods shown in this thread.

As you said, this works:

struct str  
 (
 	fn a = (print "a"), 
  	fn b = str.a()  
 )

It follows the way Denis suggested and there is no need to create an instance of the structure for this to work.

And this also works:

struct str  
 (
 	 fn a = (print "a"),
 	 fn b = a()
 )
s = str() --creates an instance of the structure
s.a() --calls function a in the structure

But only if you have instanced the structure first.

This looks like a mixture of the two:

struct str  
 (
 	         -- pre-declerations
 	 fn a = (),
 	 fn b = (),
  
 	         -- definitions
 	         fn a = (print "a"), 
  	fn b = str.a()  
 )

I don’t understand what you’re trying to do or why you need to pre-declare your functions in that way. You shouldn’t be trying to use the same name more than once for a structure member anyway. Can you explain what you are trying to do?

I missed this last reply, and actually found this thread when I was googling the problem. The point is I never fully understand what I’m doing when I script And I saw someone else doing forward declarations (in some source code) and assumed that it might help with the struct not seeing its own functions below the calling function. I have a feeling it fixed some errors, but I’m not sure