Monarch simple question(s)

I’m trying to integrate Monarch and I’m just not understanding how to just get a simple screen to appear.

ERROR:SCRIPT: /monarch/monarch.lua:655: There is no screen registered with id hash: [cards]

I know it has something to do with this…

NOTE: You must ensure that the init() function of the screen.script has run. The init() function is responsible for registering the screen and it’s not possible to show it until this has happened. A good practice is to delay the first call by posting a message to a controller script or similar before calling monarch.show() the first time:

function init(self)
	msg.post("#", "show_first_screen")
end

function on_message(self, message_id, message, sender)
	monarch.show(hash("first_screen"))
end

But I’m not sure how to interpret that code and need in my own project since the example for filling out the dialogs for the screen_proxy script doesn’t match these items –

Ok I figured out parts of this but it was still a bit confusing in the docs. I’ll try to post a thought or two on how to improve the doc later.

1 Like

Yes, please post feedback!

I was also confused about this. I got it working, but not sure how. I didn’t actually do anything other than follow the instructions in the readme. I didn’t do anything special with the init() function n the screen.script and I don’t know what a controller script is.

A controller script is just a way of saying a script which organizes the flow of other features. It’s like calling the main.script (if you even choose to have one) the bootstrap script.

If you have doubts about Monarch download the .zip of it from GitHub, extract that, and open that project to see how the demo project works.

2 Likes

Okay, I didn’t know about the demo project. I’ve added Monarch to my project, set up a factory, and managed to get a screen to load on a cursor click.

It’s this part specifically that confused me.

A good practice is to delay the first call by posting a message to a controller script or similar before calling monarch.show() the first time:

Yes, it’s good to keep in mind. Most of the libraries/extensions also act as a demo project for the feature it implements.

2 Likes

Definitely, very helpful. I’m very new and still wrapping my head everything.

And I realized this was an old thread, but it’s what came up on Google when I searched and it was exactly about my question. So I figured, ask here incase anyone else has a similar issue.

2 Likes

A good practice is to delay the first call by posting a message to a controller script or similar before calling monarch.show() the first time:

A way to delay this is to in your main.script init send a message to itself which is resolved at the end of the current frame, which will mean the screen scripts have all had a chance to init as well. (This is state in the original post of this topic but it’s missing part of it.)

msg.post(".", "init_actual")

Then in on_message do

if message_id == hash("init_actual") then
  -- do things which rely on screens being ready such as going to the initial screen
end
1 Like

Okay, if you don’t mind explaining, why would you want to delay the first call? To me, a delay means to postpone something. What is the benefit of putting the first call on hold?

Is the delay to make sure all of the screens have had time to initialize before called? Also, is it necessary to run init() for every monarch screen before using it?

I think by writing this reply I’m starting to figure it out. Because it is necessary to initialize the screens before calling them, you can self initialize a main or background screen before using monarch.show.

1 Like

The order of scripts doing init (and update / final etc.) is not guaranteed. It can all be out of order from frame to frame. You might get lucky and have it work right without a delay just because of the more random order the scripts are handled.

All of the screen scripts need time to init. If you try to go to a Monarch screen before it has a chance to init Monarch will complain that the screen does not exist yet, Monarch doesn’t know about it yet.

Also, is it necessary to run init() for every monarch screen before using it?

This is done by the screen’s script and it is necessary to have that screen’s data to be known about by Monarch.

2 Likes

Right. But is it necessary to pre-initialize every monarch screen before using it? Or will the call to initialized one (e.g., a background screen that’s not part of the stack) “wake up” the other screens and have them ready/available?

Before you can use Monarch all screen_proxy.script or screen_factory.script files must have had their init() functions called. In the init() function the scripts register themselves and the screens they represent with Monarch. Once this is done Monarch is ready and can be used. And because what Pkeod mentioned above about the order of scripts being undefined you can’t be 100% sure that the init() function of all screens have been run before your own script is trying to interact with a Monarch screen.

1 Like

It’s not waking up / starting the screen to load when its related screen script inits, but simply informing Monarch of its meta data so that it can interact with it. Actually loading a screen’s contents only happens when going to the screen unless you have the screen set to preload.

I prefer to put all parent screen GOs (with the screen script, screen collection proxy attached) within a single screens.collection which I then put inside of the main.collection.

Assets folders related to screens. Pro Tip: You can right click on a .gui file and generate its related collection and gui_script vis the Monarch editor script to save time setting up.
1
screens.collection holds GOs with a collectionproxy linking to the .collection of that screen, and a screen_proxy script which has the meta data for that screen.
2
Then it’s added to main.collection
3

1 Like

Thanks for this. I’ll try this approach.

I’m 39 years old and figuring this all out is the most challenging thing I’ve done for as long as I can remember. I sometimes grasp a concept and everything seems so simple, but I also often run into something so challenging, it can take me hours to comprehend. When it comes to programming, I’ve found that it’s helpful to take baby steps and celebrate small wins.

2 Likes

Okay, I’ve set up something similar.

Although, I used a collectionfactory because I intend to have this gui interact with and control game objects in the collection that the screen is a part of. It is my understanding that collection proxies are unable to interact with game objects.

1 Like

You want to use proxy if you want the screen to be able to be unloaded. A factory will cause the referenced collection to always be loaded so long as its parent collection is loaded (and the collections will share the same “world” / socket). This is the main difference between factory and proxy, but there are other features of proxies too such as being able to change the timestep of screens loaded through a proxy (meaning you could “pause” the screen if you have a popup show).

It is my understanding that collection proxies are unable to interact with game objects.

To reiterate factory vs proxy with collections is merely how the linked collection is loaded and unloaded / able to be handled. It does not change much about what its contents are capable of.

One thing is different though. You can not use any of the go.* functions from a script in one proxy to interact with game objects from another proxy.

1 Like

I believe this is what I read about that made me decide to go with a factory. My intention is to be able to click a unit on the screen, show a menu, and then click the actions on the menu to command the unit to move.

1 Like

I’m thinking this might all be over my head and I should go back to the basics. I’m trying to use monarch.post to send a message, but it’s not working for me.

I’m able to enable the screen like so:

But the monarch.post("main", "hello") is not being received by the gui.

I can’t figure out what I’m doing wrong.