Lua basics

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

Moderators: Víctor Paredes, Belgarath, slowtiger

User avatar
synthsin75
Posts: 10280
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

Hey would it be useful to have a script that provides some global variables with the names of AS actions? I've actually almost got this working. I just need to refine the regex search pattern and assign the result to some variable/s.

I seem to remember you needing to access these for something. Right now it will access these (as soon as I get it finished) for any AS file you select. That much of it tests well. It's just a matter of finding the right search pattern now, but I think I have a handle on that.

Of course this may be useless, but I'm at least trying to do a proof of concept on being able to get any data from the AS files text for use in scripting.


So far, in searching the AS file for action names, I can get "s 4" which is the string following "action". Not sure yet why it only gets 4 and not 1, 2, or3. :wink:
User avatar
synthsin75
Posts: 10280
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

Wow, you can actually store all kinds of info in the AS file itself. Just use one layer marked "Do not delete" and set for don't render/hide in editting. Then anywhere on that layer that you can enter text, you can put custom data to be retrieved by a script.

Shape names, action names, there's all kinds of options.
User avatar
synthsin75
Posts: 10280
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

Well I got that 'read action names' script done, but like I said, I don't know how useful it may be. Good practice anyway.

I put it in the script writing menu. Once selected, it asks for the file to be selected. ( I haven't figured out if there is anyway to open the current file by default. Is there a way to get the path of the current document? I've read I can set the default path, but I don't know how to let the script find that.)

Once you've selected the AS file, it reads it as text and supplies the action names to a global table so these could be accessed by other scripts. I can easily change whether it returns the names in quotes or not.

Now I don't know how clean this script is, but hey, it works!

I'm thinking that someone could use the table's index as number hotkeys for like Vern's 'action commander' script.

:wink:

Could also modify it to find other data, but the user text input info seems easiest to find.
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

I would LOVE to see this script! It could be very useful!

As for getting the current document path... It's built right in! It is not in the documentation. Mike added it in a long time ago but it was never updated in the scripting reference for Moho.

Code: Select all

moho.document:Path()
This will give you the entire path including the file name to the currently opened AS document. I use this a lot to save data files to the same directory as the AS document (have to do some regex to strip out the document name and just get the path).

You could just modify your script to use a check box for selecting the current document instead of opening one.

If you don't know how to set up a checkbox with variable etc... I can post that later. Basically you just need a variable:

Code: Select all

local TheFilePath = moho.document:Path()
TheFilePath variable now contains a string with the path to the current document, exactly the same as if you chose it with that open file dialog box.

I really would like to look at this script. This would be what I need to improve my "Action Commander" script. I hate parsing the file format... and if you've done most of the work for me that would be a huge help.

-vern
User avatar
synthsin75
Posts: 10280
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

Code: Select all

--[[ Script name ]]

ScriptName = "SYN_ActionData"


--[[ General info ]]

SYN_ActionData = {}

function SYN_ActionData:Name()
  return "Action Data"
end

function SYN_ActionData:Version()
  return "1.0"
end

function SYN_ActionData:Description()
  return "Read action data"
end

function SYN_ActionData:Creator()
  return "SynthSin75"
end

function SYN_ActionData:UILabel()
  return "Read action data"
end


--[[ Recurring values ]]

aname = {}

--[[ Main body ]]

function SYN_ActionData:IsEnabled(moho)
  if (moho.layer:CurrentAction() ~= "") then
    return false -- creating new objects in the middle of an action can lead to unexpected results
  end
  return true
end
  
function SYN_ActionData:Run(moho)
  local mesh = moho:Mesh()
	if (mesh == nil) then
    return
  end
  
  
  local path = LM.GUI.OpenFile("Select Anime Studio file")
  if (path == "") then
    return
  end
  
  --[[local f = io.open(path, "r")
  if (f == nil) then
    return
  end]]
  
  moho.document:PrepUndo(moho.layer)
	moho.document:SetDirty()
	
	for line in io.lines(path) do
    local__,__,name = string.find(line,"action%s%p(.+)%p")
      if (name ~= nil) then
      table.insert(aname,name)
      
      end
   
   end
  for i,v in pairs(aname) do
  print(v)
  end
  
end
I'm not entirely clear on what you mean by 'parse' so I don't know if this is an improvement. There's probably a lot here that is not needed. I've commented out some of it.

I based this on LM's 'Load data file' example in the 'script writing' menu.

I expect the meat of this could be easily added to another script. If it automatically finds the file path, you wouldn't even need that bit of user interface to do it. (Thanks for pointing that out, I'm sure I'll need that)

Hope this has some use, but like I said, if nothing else it's good practice. :wink:
User avatar
synthsin75
Posts: 10280
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

Cool! I just added that trick for the current file path. I love it! It now just does it's job with out having to be told anything. Thanks for that tip Vern!

Here it is with that change. Commented out even more of the code.

I really hope this is useful. I'd love to be able to contribute to one of our great scripters. :wink:
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

"parse" is just a fancy word that means... go through a file or text string looking at everything untill you find what you want and then pull it out.

The only way to find the "actions" in an AS file is to look at the whole darn thing 1 character at a time (or one line at a time) until you find the word "action" and then extract the action name. Parsing. Parse.

I might not be using the work correctly... or maybe its meaning has changed since the computer was invented. That is how I've understood it.

-vern
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

Wow!

The code is pretty simple. I don't know what I was so afraid of. :) I always get nervous thinking of trying to parse the file format for information. It just seems like pulling a needle out of a haystack.

I can probably use this to get the key frame interpolation for my save bone animation script. WOOOHOOO!

-vern
User avatar
synthsin75
Posts: 10280
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

The code is pretty simple.
Well that's what I kept thinking, but you never know until you do it, huh? It should be just as simple to find any user input that is stored in the file format. Especially since that appears to be the only place the AS file uses double quotes.
User avatar
synthsin75
Posts: 10280
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

Mmm, just looked for the keyframe interpolation, and it doesn't appear to be obvious. Hopefully you've already done enough trial and error to discover what part signifies interpolation.

I may play around with scripting that writes to some user input area, as these seem to be the only place in the format that AS won't complain about.

Could really use the ability to lock a layer though.
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

I know exactly where the key interpolation is. It will be tricky though since there is really nothing unique to indicate it. Hopefully the location should always be in the same spot.

The really hard part will be figuring out which line of the file matches up with the keys that being saved with my script. Things are not always in the same order in the file format as how they appear in AS or looping through bones with scripting.

Hopefully it will be simple enough to find the name of the bone in the file format and then go through the "keys".

-vern
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

Wooohooo!

I updated my Action Commander tool. It now reads in all the actions and assigns 0-9 to the first 10 actions. Also I added a menu so you can insert the actions ANY action even those above 10 with out the action palette open.

viewtopic.php?t=11594

Thanks for the help!

-vern
User avatar
synthsin75
Posts: 10280
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

I'm so glad this was useful. I was proud of it anyway, but it's always nice to make something that works and is useful.

I'll look at the updated script and work on figuring out how to write those hotkeys to the file.
User avatar
synthsin75
Posts: 10280
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Post by synthsin75 »

Vern, if you have a breakdown of the keyframe elements (like 1.10.24.3546, or what ever, equals the frame.channel.interp.key value) I'd love to see it!

I was thinking today about being able to catalogue these somehow. Like: layer={channel={frame=etc... I'm not sure how I'd have to do it yet, but I'm kind of thinking that I may need to get it all in some sort of table hierarchy to make it easier to find stuff like interpolation.

With a map, it should be possible to create tables that will do much of the work. Granted the initial search pattern is going to be insane. :wink:
User avatar
heyvern
Posts: 7042
Joined: Fri Sep 02, 2005 4:49 am

Post by heyvern »

Here's a small portion of a simple AS file with one bone that has keys for the rotation. Each key is set to each interpolation type in the order in the list (you can see the numbers are "out of sequence" when referenced through scripting).

For some odd reason "6" is not used. The numbers are 0-5, 7-8.

The keys start at the section that says "keys 10". The first number is the frame. The second number is the key interpolation followed by 2 optional values for cycle and noisy. The other interpolation modes do not have optional values which are indicated by "-1".

The last value is of course the value of the channel. In this case it is rotation.

Code: Select all

	skeleton
	[
		binding_mode 1
		bones 1
			"1" -1 -1 1 -1 1 1 -1 1 true 0.696276 1 0 0
			false -1.221731 1.221731
			[
				keys 1
					0 1 0.1 0.5 false
			]
			2 2 1
			[
				keys 1
					0 1 0.1 0.5 -0.24919 -0.102127
			]
			[
				keys 10
					0 1 0.1 0.5 0.77285
					1 1 -1 -1 0.785195
					12 0 -1 -1 0.785195
					24 2 -1 -1 0.785195
					36 7 -1 -1 0.785195
					48 8 -1 -1 0.785195
					60 3 -1 -1 0.785195
					72 4 0.1 0.5 0.785195
					84 5 2 -1 0.805762
					93 5 -1 84 0.84063
			]
1-3, 7 and 8 are straight forward.

4 is "noisy". It has two additional values. Amplitude and Scale.

Code: Select all

72 4 0.1 0.5 0.785195
72 is the frame number. 0.1 is the amplitude. 0.5 is the "scale". I set it to "2" which is 0.5. Setting it to 1 = 1.0, 2 is 0.5, 8 is 0.125. I am guessing this is a percentage value. 8 is 1/8th (0.125), 2 is 1/2 (0.5) etc.

5 is "cycle". I used it twice to show the different value settings. It has two values, the radio box value and the box to enter numbers. The choice of how the cycle functions determines the placement of the numbers in the AS file.

Code: Select all

84 5 2 -1 0.805762
In this one I chose "relative" and "2" for the frames to go back.
84 is the frame the key is on. 5 is the interpolation. 2 is the number of frames to "go back". -1 indicates that this value is not used since "relative" was chosen.

Code: Select all

93 5 -1 84 0.84063
In this one I chose "absolute", and set the frame number to "84".
95 is the frame the key is on. 5 is the interpolation. -1 indicates "absolute" was chosen. 84 indicates the exact frame to go to for the loop.

-vern
Post Reply