How would you get the working (active) layer from an embedded script?

Moho allows users to write new tools and plugins. Discuss scripting ideas and problems here.

Moderators: Víctor Paredes, Belgarath, slowtiger

User avatar
Rai López
Posts: 2250
Joined: Sun Aug 08, 2004 1:41 pm
Location: Spain
Contact:

Re: How would you get the working (active) layer from an embedded script?

Post by Rai López »

Yeah, I really don't know why it is working/behaving like this and that makes me kinda feel like there were something fishy going on, but OTOH, it seems to behave so well no matter the layer type or hierarchy location...

Image

...that I think I'm going to start using it even though. And, in any case, the other convoluted alternative I've been using is always going to be there just in case something change in the future or whatev-

OK, just while I was writing that I realized that, of course, there seems to be at least an exception when it does not return the working layer but it's active children, this is the case when there are FBF layers involved, which is bad news but makes everything start making sense at least. Well, maybe I could address that by adding some logic that tells me if I'm indeed getting the correct working layer or the FBF's active child instead, but not sure yet if it's going to be possible or if it'll be easy to reliably cover all possible situations... But well, as I said, in case it also start become too convoluted I still have at least the other method, so it could be worse!
...
User avatar
hayasidist
Posts: 3562
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: How would you get the working (active) layer from an embedded script?

Post by hayasidist »

Ramón López wrote: Thu Mar 02, 2023 2:28 am ... Well, maybe I could address that by adding some logic that tells me if I'm indeed getting the correct working layer or the FBF's active child instead, but not sure yet if it's going to be possible or if it'll be easy to reliably cover all possible situations...
it's certainly possible to see if the drawinglayer is a child of a switch layer (which, internally, is how an FBF layer is stored -- yeah, I was surprised there isn't a layer type for FBF!?) and then see if the parent is in the 'selected' list?!
User avatar
Rai López
Posts: 2250
Joined: Sun Aug 08, 2004 1:41 pm
Location: Spain
Contact:

Re: How would you get the working (active) layer from an embedded script?

Post by Rai López »

Yes, that's what I thought at first, Paul! But when you start thinking on nested Switch/FbF layers and the way they behave, I'm not sure it's so clear how can tell 100% sure which is the working layer and which the active children of a multi selection under this (maybe not very common, but possible) scenario... I think that's why I'm going to continue using the other method for the time being, but I well could be overthinking it now, so I don't rule out the possibility of going back to it in the future because the potential simplicity of this one is just too tentative, as long as finally this FbF aspect didn't start complicate things too much... Greetings!
...
User avatar
synthsin75
Posts: 10012
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: How would you get the working (active) layer from an embedded script?

Post by synthsin75 »

synthsin75 wrote: Wed Mar 01, 2023 12:34 am Here's a much simpler and rock solid solution.

If you don't mind the user installing a tool, you can have something as simple as this:

Code: Select all

ScriptName = "syn_temp"

syn_temp = {}

function syn_temp:IsEnabled(moho)
	self.layer = moho.layer
	return false
end
Return false so it never shows in the tool window.

And then the layerscript can always read the active layer, like this:

Code: Select all

function LayerScript(moho)
	
	print(syn_temp.layer:Name())
	
end
Nope. Apparently a layerscript can't read a global variable while rendering.
So I'm going to steal your use of drawingLayer, Ramon. Luckily, my use case definitely will not involve any FBF layers.
User avatar
Rai López
Posts: 2250
Joined: Sun Aug 08, 2004 1:41 pm
Location: Spain
Contact:

Re: How would you get the working (active) layer from an embedded script?

Post by Rai López »

synthsin75 wrote: Wed Mar 08, 2023 4:16 am Nope. Apparently a layerscript can't read a global variable while rendering.

Don't tell me that... I don't tend to test rendering while developing layer scripts, at least at fist stages, so if such limitation is true I'm afraid I'm going to be in big trouble soon...

But it'd be kind of funny such limitation didn't have come up before, hence do you mean in all cases or only under some special one/s like in your example? The only oddity I recall I've experienced related to layer scripts and the exporter/renderer is one that makes it silently crash if ScriptInterface:CurrentTool() is present anywhere along a layer script, and it called my attention precisely because, normally, what works in other type of scripts also works for embedded ones... That, and the fact that your example also has to do with tools, makes me think if couldn't be some kind of "incompatibility" on trying to involve anything having to do with them along embedded scripts, so hopefully the limitation (although troublesome) wouldn't be so limiting. I'll try to start making more render tests from now on so I'll see, but if that would be finally the case, I hope in the end it can be somehow workaroundable at least (what we would do without workarounds :lol:)
...
User avatar
Rai López
Posts: 2250
Joined: Sun Aug 08, 2004 1:41 pm
Location: Spain
Contact:

Re: How would you get the working (active) layer from an embedded script?

Post by Rai López »

Yep, the more I dig into this, the more convinced I am the problem has not to do with reading global variables while rendering but with the fact of trying to call any tool/menu functions (or rely on a variable returned by them as in Wes' code case).

Oh, well... honestly, I think in the end it's not as bad as can't access global variables at rendering (which would have been simply terrible), but for me this kind of unexpected limitation is going to complicate things even more, although I still have to think more about it to really can say till what extent. Or who knows if maybe a workaround will arise with the new day :)
...
User avatar
Rai López
Posts: 2250
Joined: Sun Aug 08, 2004 1:41 pm
Location: Spain
Contact:

Re: How would you get the working (active) layer from an embedded script?

Post by Rai López »

Well, no workaround for now, but after some more testing I'm starting to think there is indeed some kind of limitation upon trying to read/access Lua globals while rendering... But since you still seem able to can get _G itself, my guess (is for some reason) Moho could be clearing some of them (the majority indeed) before starting to render. Some of the global tables that seem to survive to the purge after having started a render are "LM" and "MOHO", but even thought it seems render crashes when trying to access (print in this case) some of them. I'm right now trying to determine which ones make it crash and which not (or if it's simply random, as I'm starting to think) by embedding the following script and repeatedly performing "Export Animation With Previous Settings" with the simplest testing file...

Code: Select all

function LayerScript(moho)
	local frame = moho.frame
	local gCount = 0

	if (prevframe ~= nil) then
		if (prevframe ~= moho.frame) then
			if LM ~= nil then
				for k, v in pairs(LM) do
					gCount = gCount + 1
					if gCount % 16 == 0 then --try to "randomly" print only one at a time or so... 
						print(k, ", ", v)
					end
				end
			else
				print("LM == nil!")
			end
		end
	end
	prevframe = moho.frame
end

On second thoughts (and it kind of makes more sense), maybe it's not even a purge but simply render engine uses a new/different virtual Lua environment or something but, in any case, the fact those tables be still accessible made me think if couldn't I start using them as containers for my globals (or at least for the ones I need to be always accesible) from now on, but I'm not totally sure yet if it's a good idea. Anyway! I'm still making tests and all this well may requiere a whole new topic, so I'll continue treating to get some conclusions and see.

BTW, thanks, Wes for pointing it out this unknown (for me at least) limitation just at the right moment since, as I said, I well may have been continue working on not workable solutions for a time without even noticing till I had started render tests, with the consequent loss of time that this would have entailed... Well, greetings.
...
User avatar
hayasidist
Posts: 3562
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: How would you get the working (active) layer from an embedded script?

Post by hayasidist »

I may be about to demonstrate some significant ignorance here but... Globals -- what is their scope? If (as, from this discussion, I am beginning to suspect) the scope is the process in which _a_ Lua instance is running, then the fact that the renderer can't see some "globals" is likely explained because they are not set in _its_ Lua instance. Put another way: each process has its own _G?? This is borne out (I think) by this: http://www.lua.org/manual/5.2/manual.html#2.2. What I haven't done is looked more deeply into _ENV and how that is related to "process" / "thread" / "task"
User avatar
Rai López
Posts: 2250
Joined: Sun Aug 08, 2004 1:41 pm
Location: Spain
Contact:

Re: How would you get the working (active) layer from an embedded script?

Post by Rai López »

Yes, Paul, that was also my latest conclusion and I added it to my previous post as soon as it came to my mind so maybe you read it before that, so nobody more ignorant than me on this subjects! So, yeah... Moho could be using different Lua environments and that would explain a lot, but also would entail that my plan of using "LM" or "MOHO" tables as the containers is not going to work after all... Thus I'm treating to think on alternatives like make the required functions available somewhere/somehow else by load them when required directly from the *.lua file should they are not found, to at least can avoid performance loss under normal usage since that's not so important for renders, but that only is going to complicate things a lot, so trying to think another ways before starting to study that possibility.

I think the ideal outcome would be that there were a way to pass variables from one Lua environment to another, but I don't know if that's even possible (I'd bet not), so... And I don't think using "_G" or "_ENV" entails any significant make difference in this case, isn't? Because even they doesn't seem to be exactly the same thing (as used to think at first), I've not been able to see any difference when I tried to use one or the other. Therefore, not sure what is going to be my next step, but as I said this has turned to be an unexpected hiccup for me and I still have to make a lot of tests and make some considerations about it, which sounds like a lot of fun ahead, haha...
...
User avatar
synthsin75
Posts: 10012
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: How would you get the working (active) layer from an embedded script?

Post by synthsin75 »

Thanks for digging in a verifying what I suspected, Ramon.
User avatar
Rai López
Posts: 2250
Joined: Sun Aug 08, 2004 1:41 pm
Location: Spain
Contact:

Re: How would you get the working (active) layer from an embedded script?

Post by Rai López »

Yes, you were right as much as I would have liked it not to be, haha... But even though I'm very glad you made me know about all this as I said, so thanks to you again.

BTW, as a side note... does it mean the fact that "lfs" appears listed in the global variables mean we have access to all the possibilities LuaFileSystem (1.6.2) can bring? Because I had no idea this module could be included this way and that could mean very good news when it comes to deal with OS, directories, files and so from Moho's scripting interface directly. Well, it has been just right there all this time after all, so most of you probably already know... but I've just noticed and there it is just in case.
...
User avatar
Rai López
Posts: 2250
Joined: Sun Aug 08, 2004 1:41 pm
Location: Spain
Contact:

Re: How would you get the working (active) layer from an embedded script?

Post by Rai López »

OK, I don't want to talk too soon... but I think I could have found my beloved workaround. Basically the idea will consist on, if the called function is not found (so Moho is rendering) start loading and running the scripts containing the not found functions by using the SetLayerScript & RunLayerScript and then back to the original script so that everything remain the same but now with all the needed functions available in the new/clean environment as well. After some quick test at least it seems like it could do the job and, for what I've been able to inquire, it well could be indeed the (only) way to go... So, even thought it's kind of weird and it's going to introduce some unexpected and unwanted complexity to the process (and surely new problems that will have to be solved) plus there are still some tests I'd have to do to really can say, at least I think I have something to start with tomorrow. We'll see...
...
User avatar
synthsin75
Posts: 10012
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: How would you get the working (active) layer from an embedded script?

Post by synthsin75 »

Ramón López wrote: Sat Mar 11, 2023 6:20 am BTW, as a side note... does it mean the fact that "lfs" appears listed in the global variables mean we have access to all the possibilities LuaFileSystem (1.6.2) can bring? Because I had no idea this module could be included this way and that could mean very good news when it comes to deal with OS, directories, files and so from Moho's scripting interface directly. Well, it has been just right there all this time after all, so most of you probably already know... but I've just noticed and there it is just in case.
I usually use the Lua OS functions for file handling, but seeing lfs.chdir (path), I wonder if that's a possible way to change Moho's working directory...so you can point an open file dialog to a specific directory, instead of always the last directory Moho opened.

Ramón López wrote: Sat Mar 11, 2023 7:51 am OK, I don't want to talk too soon... but I think I could have found my beloved workaround. Basically the idea will consist on, if the called function is not found (so Moho is rendering) start loading and running the scripts containing the not found functions by using the SetLayerScript & RunLayerScript and then back to the original script so that everything remain the same but now with all the needed functions available in the new/clean environment as well. After some quick test at least it seems like it could do the job and, for what I've been able to inquire, it well could be indeed the (only) way to go... So, even thought it's kind of weird and it's going to introduce some unexpected and unwanted complexity to the process (and surely new problems that will have to be solved) plus there are still some tests I'd have to do to really can say, at least I think I have something to start with tomorrow. We'll see...
So set and run a layerscript once, at the beginning of a render, to load functions into the Lua render environment?
You'd already have to have a variable hard-coded in the layerscript, right?
User avatar
Rai López
Posts: 2250
Joined: Sun Aug 08, 2004 1:41 pm
Location: Spain
Contact:

Re: How would you get the working (active) layer from an embedded script?

Post by Rai López »

synthsin75 wrote: Sat Mar 11, 2023 6:57 pm I usually use the Lua OS functions for file handling, but seeing lfs.chdir (path), I wonder if that's a possible way to change Moho's working directory...so you can point an open file dialog to a specific directory, instead of always the last directory Moho opened.
Same here! But they are quite limited and, even Moho also offers some functions that can help when dealing with files, I always had missed can access file attributes and e.g. be able to create/remove directories and so, things that although I've not tested yet, "lfs" should be able to do with ease. E.g. I had to use recently kind of a hack to simply can test if a file already exits in a directory or not and, precisely yesterday, I realized it wasn't even reliable after all; well as I understand, with lfs this kind of things should be easy peasy, so for me it has been like an unexpected gift around all this situation :D

Oh, but at first sight at least, it doesn't sound to me like "lfs.chdir" can do what you wonder, or at least unless I'm missing something. I've done a quick test anyway by simply calling it just before what makes open the "open file dialog" in "lm_automation.lua" meu script and, as kind of expected, it continue opening in the last directory used by Moho. OTOH, what it does indeed is change "lfs" working directory as "lfs.currentdir()" reveals, meaning everything seems to work! (Can't wait to start giving some real use to it).

synthsin75 wrote: Sat Mar 11, 2023 6:57 pm So set and run a layerscript once, at the beginning of a render, to load functions into the Lua render environment?
You'd already have to have a variable hard-coded in the layerscript, right?
Yes! And I can't believe it yet it seems to work... Still testing things though, because I've spend a lot of time today treating to make work the combo "string.dump" & "load" Lua functions (just to know if I could have another alternative should the first one reveal problematic at some point), but without any success because I can't get moho to be passed as valid argument upon calling the "binary stringed" function, for some reason that I simply can't (and neither Bing AI) understand... Therefore I'm afraid I'm tied to my workaround for now, so I hope it continue working without surprises.

But what do you mean by variable hard-coded? There is nothing special about the functions I want to call from other scripts, I just want they to be available "in memory" so that they can be called at anytime and from anywhere, and loading them that way seems to guarantee (still can hardly believe it 😅) that, since now they appear as any other available variable in the new/fresh environment as well.
...
User avatar
synthsin75
Posts: 10012
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: How would you get the working (active) layer from an embedded script?

Post by synthsin75 »

Ramón López wrote: Sun Mar 12, 2023 1:56 am
synthsin75 wrote: Sat Mar 11, 2023 6:57 pm I usually use the Lua OS functions for file handling, but seeing lfs.chdir (path), I wonder if that's a possible way to change Moho's working directory...so you can point an open file dialog to a specific directory, instead of always the last directory Moho opened.
Same here! But they are quite limited and, even Moho also offers some functions that can help when dealing with files, I always had missed can access file attributes and e.g. be able to create/remove directories and so, things that although I've not tested yet, "lfs" should be able to do with ease. E.g. I had to use recently kind of a hack to simply can test if a file already exits in a directory or not and, precisely yesterday, I realized it wasn't even reliable after all; well as I understand, with lfs this kind of things should be easy peasy, so for me it has been like an unexpected gift around all this situation :D
I haven't ever needed to get file attributes, but creating/removing directories can be done with os.execute, like I used in my Switch Icons tool.
You can use the Lua IO library to test if a file exists, like this:

Code: Select all

			local f = io.open(tempPath, "rb")
			if (f == nil) then
				--file doesn't exist
			end
Oh, but at first sight at least, it doesn't sound to me like "lfs.chdir" can do what you wonder, or at least unless I'm missing something. I've done a quick test anyway by simply calling it just before what makes open the "open file dialog" in "lm_automation.lua" meu script and, as kind of expected, it continue opening in the last directory used by Moho. OTOH, what it does indeed is change "lfs" working directory as "lfs.currentdir()" reveals, meaning everything seems to work! (Can't wait to start giving some real use to it).
That's what I expected, as I figured it only changed the working directory for Lua, but it was something I hadn't tried yet.
Oh well. :roll:
synthsin75 wrote: Sat Mar 11, 2023 6:57 pm So set and run a layerscript once, at the beginning of a render, to load functions into the Lua render environment?
You'd already have to have a variable hard-coded in the layerscript, right?
Yes! And I can't believe it yet it seems to work... Still testing things though, because I've spend a lot of time today treating to make work the combo "string.dump" & "load" Lua functions (just to know if I could have another alternative should the first one reveal problematic at some point), but without any success because I can't get moho to be passed as valid argument upon calling the "binary stringed" function, for some reason that I simply can't (and neither Bing AI) understand... Therefore I'm afraid I'm tied to my workaround for now, so I hope it continue working without surprises.

But what do you mean by variable hard-coded? There is nothing special about the functions I want to call from other scripts, I just want they to be available "in memory" so that they can be called at anytime and from anywhere, and loading them that way seems to guarantee (still can hardly believe it 😅) that, since now they appear as any other available variable in the new/fresh environment as well.
I guess I'm not quite following you. What I'm needing is to have a variable, set by a tool, accessible to a layerscript while rendering. So once the render starts, I'd have the same problem with any other layerscript I try to set and run, right? Unless the value of the variable was hard-coded in the layerscript, i.e. "var = value." Now, I can have a script write a layerscript on the fly, to do that, but that's starting to sound too involved for my purposes.
Post Reply