Run an MCR file but ignore its macroscrip header?


#1

I wonder, out of curiosity; Is it possible to run an MCR file but ignore the macroscript header, ie only read what is between ( and ) ?

I assume that one dont want to evaluate the whole macroscript over and over again, or is it harmless?


#2

mcr without its header is just a script.


#3

The only difference is when there’s a on execute handler, in that case what’s outside of it is persistent across session, what’s inside is what gets reevaluated. So in case that the person writing it used the macroscript top-level scope to store values across multiple runs, that will break.


#4

Yes, I understand this. But I needed to know if there were downsides reevaluating MCRs over and over compared to evaluating MS files.

Would you please elaborate this?
Does it mean things outside “on execute” will not be reevaluated, just what’s inside or the other way around?
If so, does it mean an script structured as an MCR is partially read on an evaluation compared to an MS that is fully evaluated?

Let me just quickly explain why this question came to my mind.
There are scripts out there that generate menus or popups or in some way list up all available scripts in a user interface. By some reason, the MCRs are ignored.
So I assumed that the MCR part, the macroscript plus on execute handler which are additions on top of a regular MS file might be the reason. And if so, I wondered if there was a way to strip away those parts on the fly and read the MCR just like if it was an MS file.


#5

Exactly, here’s a minimal example to show that:

macroscript ScopeExample
(
	local counter = 0
	on execute do print (counter += 1)
)

Run it a few times with macros.run #unknown #ScopeExample and see the value increasing. Basically, the on execute scope is meant for things that happen on executing the macro, the top-level scope for initialization of the macro, functions, rollout definitions and stuff like that.

In that case those scripts are poorly written. Use macros.list (for example macros.list to:stringStreamToParse) to get all the macros, avoid what you suggested… Like, really


#6

Sorry for bumping up this thread, but I realised I had still an unanswered question.

When I run fileIn ((getdir #userMacros)+"\somefile.mcr"), the Macroscript gets evaluated as expected.
How can I run the macroscript-file but ignoring the header and only running the script inside it?


#7

Separate the headerd in .mcr(header.mcr) file and the body of the script in .ms(body.ms or body.mse) file. When you want to evaluate the macro fileIn the header.mcr, when you want to load the real script fileIn body.ms


#8

Thanks @miauu . This I know, but I was hoping there was a way to do this scriptwise without altering the original MCR-file. Something like runAsScript(macroScript.mcr) and then have it only run what is between the first and last parenthesis-signs…


#9

You can read .mcr file as string with something like this (dotnetclass “System.IO.File”).ReadAllText and remove the macroscript definition header
And of course it doesn’t guarantee that this altered string can be executed via Execute function without errors.


#10

see macros.run

or do you need something different?


#11

macros.run works if you have evaluated the Macroscript already.
I need something different, more like what @Serejah is mentioning.

The logic could be like this

  1. read the macroscript-file as text
  2. search for the string macroscript and then it searches for the first (
  3. Execute everything from ( to the end of the file.

There might be a bunch of commented text before the macroscript header starts, for example author notes with the word “Macroscript” followed by a paranthesis that has nothing to do with the macroscript. A solution could be that to ask the user for confirmation

Do you want to execute the code within "macroscript Macroname tooltip:"blah blah" text text text"

ie, it shows you a preview of the first macroscript row to let the user confirm we found the correct macroscript start. If not, the user can press "search next".

Once you find the right spot, you can press Run the execute the code inside the Macroscript without executing the header.


#12

I doubt that it would be that easy.
How about macro with such structure?

macroScript testmacro
buttonText:"testmacro"
category:"custom"
tooltip:"test macro"
icon:#("someicon",1)
(
	local state = off
			
	fn someFunction = (

		...

	)
	
	
	on isChecked do
	(
		state
	)
	
	on isEnabled do (
				
		enabled = isKindOf selection[1] Editable_Poly
		if not enabled do state = false
		enabled
		
	)

	on execute do
	(
		...
		someFunction()
		...
	)
)

#13

@Serejah, the problem I am facing here is that as long you execute a Macroscript, you’ll have a copy of it under $userScripts.
If you decide to test out bunches of scripts, you’ll end up with a heap of files and categories that needs to be cleaned up manually .

Maybe we could save out a temporary .ms file and then run that file.


#14

it’s not safe in general case because MACRO can have specific for macroscript handlers which don’t make sense outside macroscript body (e.g. on isChecked, on isIndeterminate, on execute, on drop, etc.).

Run and Clean after that is the safer way IMHO

For example all my macros run with the execute handler which makes them ‘executable’ as a marcoscript only. (So you have to check first that the macro does not use execute handler before trying to run it your way)
Also some of my macros and tools need some other macros to be loaded (registered) before their own execution.


#15

BTW
I believe that using MCR files is an outdated technique and rarely use it.
I usually define macro(s) inside a plugin or script (MS) file.


#16

I couldn’t find anything about this event. What is it for?


#17

it was my misspelling and auto-fix … it has to be isIndeterminate


#18

is it somehow related to tri-state of a macro button? I always thought it can only be on/off


#19

isIndeterminate handler is usually used for menu and quad menu items. Because you can see it in UI (see the help).

You can use it in sense of ‘tri-state’ like as an ‘available’ action for not all currently selected (visible, etc.) nodes.

For example some action works for selected geometry class nodes. But current selection also includes helpers…
So you can define ability of this action as ‘indeterminate’ - means it works but not for all.
If there is no geometry nodes in the current list you should set it to ‘disabled’, if all nodes are geometries you should set it to ‘enabled’


#20

Thanks for the explanation, Denis.
There’s not a single word in reference about this particular handler.