Grab all open documents

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

Moderators: Víctor Paredes, Belgarath, slowtiger

User avatar
LeviFiction
Posts: 18
Joined: Thu Jul 10, 2014 4:19 am

Grab all open documents

Post by LeviFiction »

Hello,

I tried looking in the script documents and couldn't find anything that fit so I thought I'd ask just to double check. Is there a way to grab all open documents in Moho? I know the MOHO.document variable points to the document object for the current document. And I know that using "LoadDocument" can return a document object once called. But nothing I can find for just getting all open documents. Though I do understand this isn't usually a common need.
User avatar
synthsin75
Posts: 10266
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Grab all open documents

Post by synthsin75 »

No such luck. Moho always considers the active document tab the moho.document, and can't even tell when you've switched tabs.

But you can get the list of recent files, searching the user.settings file for "RecentFile", using moho:UserPrefsFile(). So if you know how many documents are opened, and they've all been recently saved, you can find their paths as "RecentFile1", "RecentFile2", etc..
User avatar
LeviFiction
Posts: 18
Joined: Thu Jul 10, 2014 4:19 am

Re: Grab all open documents

Post by LeviFiction »

Thank you so much for the prompt answer and optional workaround. :D That's fine. I was hoping there would be a good way to copy a style between two open documents. I was able to successfully copy a style from a document loaded in using LoadDocument(). So that may be the direction I go instead.
User avatar
synthsin75
Posts: 10266
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Grab all open documents

Post by synthsin75 »

Yeah, if you know the path to the target document LoadDocument should be all you need.

If I were to do this for multiple opened documents, I'd probably use an AutoHotkey script (Windows only), invoked by a Lua script, to change tabs.
ggoblin
Posts: 266
Joined: Wed Jan 19, 2022 2:09 pm

Re: Grab all open documents

Post by ggoblin »

LeviFiction wrote: Sun Jun 19, 2022 11:20 pm Thank you so much for the prompt answer and optional workaround. :D That's fine. I was hoping there would be a good way to copy a style between two open documents. I was able to successfully copy a style from a document loaded in using LoadDocument(). So that may be the direction I go instead.
LeviFiction, just be aware that there are several undocumented limitations to what you can do with styles using lua. Please see this thread for more information: http://www.lostmarble.com/forum/viewtopic.php?t=35151

Essentially copying a style from a document is fine, but you will have problems (real problems which I dont think have a solution right now) when it comes to creating a new style using lua (ie copying style into another document). This is undocumented so you will only see bizzare crashes with no explaination. Another shortcoming is that the API doesn't cover all style properites (like gradients).

I have asked that mohoscripting.com include a warning message next to the styles api reference so coders dont waste their time trying to do something which at present will not work.
ggoblin
Posts: 266
Joined: Wed Jan 19, 2022 2:09 pm

Re: Grab all open documents

Post by ggoblin »

To summarise, answers from hayasidist in that thread:

1. Can we safely create a new style from Lua? - NO
2. Can we safely modify an existing style and save it as a new style from Lua? - NO
3. Can we safely modify an existing style in Lua and the modifications appear in the style pallette? Yes - but not all properties
4. Can we safely choose an existing style and use it in Lua for shapes created in Lua? Yes
User avatar
LeviFiction
Posts: 18
Joined: Thu Jul 10, 2014 4:19 am

Re: Grab all open documents

Post by LeviFiction »

Thank you very much ggoblin. I did see and read through that thread. Technically it's what gave me my initial idea. I thought maybe I could create a new *.anme file (since it's a much more simplistic format than *.moho and I don't know of a file format document for either) from lua, then load that document in and copy the style in. A massively overly complex workaround and I had hoped I could start with open documents rather than having to make test files. But even loading in the document I still got occasional crashes. I think the most interesting was when it crashed if I tried to look at the fUUID string for an imported style. I was curious if it changed after adding it. It would either crash or claim that the userdata variable didn't include an fUUID member.
User avatar
SimplSam
Posts: 1218
Joined: Thu Mar 13, 2014 5:09 pm
Location: London, UK
Contact:

Re: Grab all open documents

Post by SimplSam »

Have you have tried/used the File > Import > Moho Styles ?

Obviously not scripted, but may get you to where you wanna go - without too much headache.
Moho 14.3 » Win 11 Pro 64GB » NVIDIA GTX 1080ti 11GB
Moho 14.3 » Mac mini 2012 8GB » macOS 10.15 Catalina
Tube: SimplSam


Sam
User avatar
hayasidist
Posts: 3841
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: Grab all open documents

Post by hayasidist »

Interesting that you are looking at writing a file and loading it...

a .mohoproj file is what is held in a .moho file (and the .moho is, for all practical purposes a .zip -- copy a .moho, rename it as a .zip and extract the .mohoproj which you can then view with any text editor)

.mohoproj is a JSON formatted text file. It can be loaded by the ScriptInterface:LoadDocument(path) method or opened directly by Moho. JSON is a very simple "standard" - in essence it only describes the "punctuation" -- what you put in the text is not portable across applications unless the apps share a common vocabulary, syntax and semantics [by way of illustration see http://www.lostmarble.com/forum/viewtopic.php?t=35050]

There are many fields in a Moho-generated .mohoproj that are only there for animation - so a script-generated .mohoproj could be much cut down (e.g. I have created "minimalistic" .mohoproj file that can successfully load into tools such as the scatter brush).

As I see it, there are two ways to create a new .mohoproj file: copy / edit one; or write from scratch - I have not yet found the minimum information set for a .mohoproj with "just" a document-wide style. If that is "small enough to be useful" I'd aim for the "create" option - if not, I'd go for "copy/edit". In any event, you end up with a new document with a new style.

When copying styles between documents, there is an unlink option. viewtopic.php?t=31433 discusses further. I have not yet tried to use MohoDoc:RelinkStyles(layer) method, but I think this should address the duplicate UUID issue. [The UI does!] As an option, it should be possible to generate a new UUID and put this in the file along with other style information (e.g. name, colours etc) (I think moho uses a type 4 random -- see https://www.cryptosys.net/pki/uuid-rfc4122.html -- I have a type 4 generator -- say if you want it.)

About your last point about "no fUUID" -- take a closer look at http://www.lostmarble.com/forum/viewtop ... 27#p205227 This talks about an M_Style object that is not properly formed - and accessing the fUUID field in such can cause crashes - it also talks about a workaround.

Bottom line:
It should be possible to create a new style in a .mohoproj file and import it. (It's way down my list right now ... so if you feel like giving it a try ...
User avatar
LeviFiction
Posts: 18
Joined: Thu Jul 10, 2014 4:19 am

Re: Grab all open documents

Post by LeviFiction »

Ah, I thought a file header of PK looked familiar. I was expecting a binary format. Got very used to dealing with those making scripts for PaintShop Pro. Happy to see it'll load the mohoproj just fine and json is definitely easier.

Yeah there are a lot of setting in these files, so I just blindly brute-forced it by deleting things until they broke. Here's the minimum file I was able to create that loaded without error into 13.5.

Code: Select all

{
    "mime_type": "application/x-vnd.lm_mohodoc",
    "version": 1040,
    "created_date": "Mon Jun 20 15:28:38 2022",
    "modified_date": "Mon Jun 20 15:28:38 2022",
    "styles":[]
    "layers": [
        {
            "type": "MeshLayer",
            "name": "Layer 1"
        }
    ]
}
Now I just need to find time to study all of the style effects settings and make the functions to recreate them.
User avatar
LeviFiction
Posts: 18
Joined: Thu Jul 10, 2014 4:19 am

Re: Grab all open documents

Post by LeviFiction »

Before I forget, I'd be interested in seeing your UUID function, I was planning on using this gist from a github user named jrus. https://gist.github.com/jrus/3197011.
User avatar
synthsin75
Posts: 10266
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Grab all open documents

Post by synthsin75 »

This is what I've been using, to generate random alphanumeric IDs:

Code: Select all

--random alphanumeric
	local charset = {}
	for c = 48, 57  do table.insert(charset, string.char(c)) end
	for c = 65, 90  do table.insert(charset, string.char(c)) end
	for c = 97, 122 do table.insert(charset, string.char(c)) end
	length = 20
	local function randomString(length)
		if not length or length <= 0 then return '' end
		math.randomseed(os.clock()^5)
		return randomString(length - 1) .. charset[math.random(1, #charset)]
	end
	print(randomString(length))
User avatar
hayasidist
Posts: 3841
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: Grab all open documents

Post by hayasidist »

LeviFiction wrote: Tue Jun 21, 2022 3:00 am Before I forget, I'd be interested in seeing your UUID function, I was planning on using this gist from a github user named jrus. https://gist.github.com/jrus/3197011.
here y' go ...

Code: Select all

function HS_GenUUID() -- type 4 as RFC 4122
	local i, t, uuid
	local b = {}
	local s = {}

	local limits = {
		65535,
		65535,
		65535,
		4095,
		16383,
		65535,
		65535,
		65535
	}

	t = os.time()
	math.randomseed (t)

	for i = 1, #limits do
		b[i] = math.random (0, limits[i])
	end

	b[4] = b[4] + 0X4000
	b[5] = bit32.bor (b[5], 0X8000)
	for i = 1, #limits do
		s[i] = string.format ("%04x", b[i])
	end
	uuid = s[1] .. s[2] .. "-" .. s[3] .. "-" .. s[4] .."-" .. s[5] .. "-" .. s[6] .. s[7] .. s[8]
	return uuid
end
User avatar
hayasidist
Posts: 3841
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: Grab all open documents

Post by hayasidist »

LeviFiction wrote: Mon Jun 20, 2022 10:23 pm ...
Now I just need to find time to study all of the style effects settings and make the functions to recreate them.
here's a minimal style block for a "radial gradient" type...

Code: Select all

"styles":[

	{"type":"Style","name":"Style 1","uuid":"c3dd5371-9569-4bf5-afb2-df921644ab78",
	"define_fill_color":true,"fill_color":{"type":"Color","when":[0],"val":[{"r":1.0,"g":1.0,"b":1.0,"a":1.0}]},
	"define_line_width":true,"line_width":0.003704,
	"define_line_col":true,"line_color":{"type":"Color","when":[0],"val":[{"r":0.0,"g":0.0,"b":0.0,"a":1.0}]},
	"line_caps":1,

	"fill_style_id":9,"fill_style":
		{"type":"SS_Gradient2","gradient_type":1,"through_alpha":true,

		"gradients":[
			{"location":{"type":"Val","when":[0],"val":[0.0]},     "color":{"type":"Color","when":[0],          "val":[{"r":0.0,"g":0.0,"b":0.0,"a":0.0}]}},
			{"location":{"type":"Val","when":[0],"val":[0.180392]},"color":{"type":"Color","when":[0],"val":[{"r":0.294118,"g":0.0,"b":0.509804,"a":1.0}]}},
			{"location":{"type":"Val","when":[0],"val":[0.345098]},"color":{"type":"Color","when":[0],          "val":[{"r":0.0,"g":0.0,"b":1.0,"a":1.0}]}},
			{"location":{"type":"Val","when":[0],"val":[0.5]},     "color":{"type":"Color","when":[0],          "val":[{"r":0.0,"g":1.0,"b":0.0,"a":1.0}]}},
			{"location":{"type":"Val","when":[0],"val":[0.639216]},"color":{"type":"Color","when":[0],          "val":[{"r":1.0,"g":1.0,"b":0.0,"a":1.0}]}},
			{"location":{"type":"Val","when":[0],"val":[0.780392]},"color":{"type":"Color","when":[0],     "val":[{"r":1.0,"g":0.588235,"b":0.0,"a":1.0}]}},
			{"location":{"type":"Val","when":[0],"val":[0.878431]},"color":{"type":"Color","when":[0],          "val":[{"r":1.0,"g":0.0,"b":0.0,"a":1.0}]}},
			{"location":{"type":"Val","when":[0],"val":[1.0]},     "color":{"type":"Color","when":[0],          "val":[{"r":0.0,"g":0.0,"b":0.0,"a":0.0}]}}
			]
		}
	}
],

(it's the rainbow that I used to make this: https://youtu.be/y54IvF-D6eI -- by script changing the gradient colour channels)


And for some inspiration on how to write a file from Lua where a lot of it is standard text - http://www.lostmarble.com/forum/viewtopic.php?t=32570 - Synthsin's approach to creating a layerscript is, IMO, a great model for holding a string which is to be written out as (in his case) a Lua file - but the idea is wholly portable to a .mohoproj
User avatar
LeviFiction
Posts: 18
Joined: Thu Jul 10, 2014 4:19 am

Re: Grab all open documents

Post by LeviFiction »

Thank you again. I've grabbed examples of every style by making a change, saving the mohoproj file, and searching for the styles. I'm still so new to Lua's tables to make up for the lack of classes (not a fan but I'll get over it xD) but I think I've got a decent one set up to help me create accurate json for all style values and combinations. Right now just making sure I've accounted for all mins and maxs (mostly 0-256, or 359 for angles), that the calculations are done right (several are percentages of a weird constant 0.20576153), and legacy colors use 0-255 while new color values are 0-1. Also considering making it understand M_Style tables for quick importing and editing. No idea what I'm going to do with this, xD But I'm committed to see if I can make it work.
Post Reply