What would be the easiest way to reload a gui collection without switching collections first?
Basically, I want to
msg.post("#mainScreen", “load”)
msg.post("#mainScreen", “unload”)
to reset the current gui to it’s original layout. But this throws an error “The collection ‘mainScreen’ could not be created since there is already a socket with the same name.”
Do I have to switch to a different collection first?
You need wait, until mainScreen have unloaded, and then load it.
function on_message(self, message_id, message, sender)
if message_id == hash('reset') then
msg.post("#mainScreen", "unload")
elseif message_id == hash('proxy_unloaded') then
msg.post("#mainScreen", "load")
elseif message_id == hash('proxy_loaded') then
msg.post(sender, 'enable')
end
end
function on_message(self, message_id, message, sender)
if message_id == hash('reset') then
-- reset code here
elseif message_id == hash('load_level') then
-- ...
elseif message_id == hash('level_menu') then
-- ...
elseif message_id == hash('win_screen') then
-- ...
end
end
function on_message(self, message_id, message, sender)
if message_id == hash('reset') then
msg.post("#mainScreen", "unload")
elseif message_id == hash('proxy_unloaded') then
msg.post("#mainScreen", "load")
elseif message_id == hash('proxy_loaded') then
msg.post(sender, 'enable')
end
end
then it loads the main screen even if I want to switch to a different one.
I shouldve been more clear.
I meant, If i want to add, for example, a Settings screen for my game, I can’t load it, because as soon as mainscreen has unloaded it immediately loads mainscreen again.
can I check which collection has unloaded with an if statement?
Ok, as far as I know, the ‘proxy_unloaded’ message is generated automatically by the Defold messaging system, so it will fire every time a collection (any collection) unloads, so, if you don’t want main screen to load then, I guess you would have to remove those lines:
elseif message_id == hash('proxy_unloaded') then
msg.post("#myOtherCollection", "load")
Although the question is for the Defold pros to answer, my best guess is that the parameter ‘sender’ will give you the identifier of the collection that just unloaded, but you could add a line (or two) to test if this is the case:
elseif message_id == hash('proxy_unloaded') then
print(sender)
pprint(message)
And that will hopefully point you in the direction of what you want to implement
I would recommend that you learn and understand how collection proxies work and how you load and unload them. It seems as though you are well underway and I believe the answers in the thread will help you understand them fully.
It can be a hassle to manage the loading and unloading of collections/screens and if you have many different proxies that you load and unload I’d recommend that you spend the time to write your own screen manager to take care of this. If you design it well it can be reused between your projects. You could also take a look at the routing library that was posted a while back. It’s well written and will take care of all your screen management problems.
You should never try to perform string manipulation on userdata or hash since the format of these aren’t guaranteed to stay the same. There’s an excellent post by @jakob.pogulis describing why reverse hashing isn’t even available in release builds.
What you want to do is to compare actual URLs (because that is the kind of userdata object sender is):
elseif message_id == hash('proxy_unloaded') then
if sender == msg.url("main:/loader#mainScreen") then
load_main(self)
end
end
While looking for a solution for my app I came across this old thread.
I present the code that works in my case.
It’s a glued together solution, mostly from Ben James (benjames-171) and DeepSeek (which helps a lot, although it’s sometimes wrong - but I managed to construct a working game with its help).
I’ve been using Defold for a few days, so half of this code I don’t understand, but it works for me.
local function show(self, proxy)
if self.current_proxy then
msg.post(self.current_proxy, "unload")
self.current_proxy = nil
end
msg.post(proxy, "async_load")
end
function init(self)
msg.post(".", "acquire_input_focus")
self.current_proxy = nil
msg.post("#", "show_menu")
end
function on_message(self, message_id, message, sender)
if message_id == hash("show_menu") then
show(self, "#menu_proxy")
elseif message_id == hash("show_game") then
show(self, "#game_proxy")
elseif message_id == hash("show_about") then
show(self, "#about_proxy")
elseif message_id == hash("show_scores") then
show(self, "#scores_proxy")
elseif message_id == hash("restart_game") then
show(self, "#game_proxy")
elseif message_id == hash("proxy_loaded") then
self.current_proxy = sender
msg.post(sender, "enable")
elseif message_id == hash("proxy_unloaded") then
print("Unloaded proxy", sender)
end
end
Use the force Luke, or do not…
As I think about it, I conclude that it would probably be possible to extend this with parameters and basically reset any collection from anywhere by passing a name.