-
Notifications
You must be signed in to change notification settings - Fork 117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamically add player HUD to map scenes #179
Comments
Added a quick implementation as a draft PR. |
Haven't looked at the PR yet, but just wanted to mention that it has previously come up to streamline this a bit more in general. Ok, will look into your PR now. |
Yup, the PR is a quick and dirty change to see if it works, and does just what you described with the HUD and pause menus. The singleton preloads both, and then CogitoScene instantiates them and adds them into the scene. It's a very small change and visually works, however one thing to verify is that the scene management doesn't work any magic behind the scenes, i.e. ensure there ever is only one instance of both UI elements in the scene, as in one of the variations I tested only the initial scene had the HUD, and this didn't pass into the other scenes. For my own project I ended up doing the following: class_name UserInterfaceSingleton
static var _instantiated: bool = false
var _ui_scene: PackedScene = preload("res://core/user_interface.tscn")
var _ui_instance: Control = null
var ui_instance: Control:
get:
if _ui_instance == null:
_ui_instance = _ui_scene.instantiate()
return _ui_instance
func _init() -> void:
assert(not _instantiated, "Do not instantiate UserInterfaceSingleton!")
_instantiated = true The null check is there, because a scene change seems to also free the instance, even if it comes from the singleton. I didn't too heavily investigate this however, it might be possible to simply reparent the UI scenes instead 🤔 And then the scene simply gets the instance from the singleton: func _ready() -> void:
var ui: Control = Icarus.UserInterface.ui_instance
add_child(ui) The benefit here being that I can access the |
Oh, this looks pretty good, shouldn't add too much complexity?
Scene manager pretty much only moves the Player around and loads player data. I made the UI independent of this, so should be fine. 🤷🏼
Yeah, the level scene transition works by completely freeing the level scenes. In this case, having the PlayerHUD and PauseMenu dynamically added to the Level scene might make things a bit more complicated (though not impossible). Just thinking out loud, I probably lean more towards adding the PauseMenu and PlayerHUD as "components" to the Player.tscn. Pros:
Cons:
|
Yeah, shouldn't add too much complexity. In this case, as long as a map/level is a
True, true. For some hard coded strings I'm planning on adding them to a configuration file that can be edited through editor tools, and in case of UI I just hope I won't have to alter the structure too much 😄
That's definitely one way to do it and should work. For my own project I try to decouple things like that, so you don't have to access the player to get to the UI. Quickly thinking about it, the only edge case where that could be an issue is a game that allows switching the controllable character (for an interesting example, see Battlefield 2: Modern Combat), but I guess that would be more of a game implementation detail in the end, as in how do you handle passing the control/updating the player object.
So I kind of ended up doing this in a hacky way because I like namespaces. I only have a single autoload, that acts as namespace for singletons + is config holder (global toggles etc.). This way I can then access every singleton from a single namespace. extends Node
## A singleton that acts as a namespace for all other singletons.
# NOTE: An issue with this method of doing singletons, is that the autocompletion
# does not seem to function (at least in Godot 4.2.1)
var UserInterface: UserInterfaceSingleton = UserInterfaceSingleton.new()
var ItemRepository: ItemRepositorySingleton = ItemRepositorySingleton.new()
var Utils: UtilsSingleton = UtilsSingleton.new()
#region Paths
# TODO: Fetch the correct folder from a config instead
var items_path: String = "res://game/assets/items/"
#endregion
#region Global toggles
## Controls interactability globally.
var interactions_allowed: bool = true
## Controls whether interaction prompts are generated globally.
var generate_interaction_prompts: bool = true
## Controls whether carried items can be picked or not.
var can_pick_carried_item: bool = true
#endregion If that were loaded simply as |
I would like to add my two cents to this as I am working on an MP extension
and I actively change the menu in my code rn.
Lots of these solutions sound good. The one thing I want to see is the
ability to make non destructive changes on the users end. Basically all I'm
say is that the dev using Cogito should be able to duplicate the menu,
change it, and point to the new menu they made.
This is because if you change base cogito files and then want to update
cogito you lose your changes when you do so.
…On Thu, May 2, 2024, 01:58 aronand ***@***.***> wrote:
Oh, this looks pretty good, shouldn't add too much complexity?
Yeah, shouldn't add too much complexity. In this case, as long as a
map/level is a CogitoScene the UI will get added to it during runtime.
I'm not too much of a fan off is the string-based path reference to the UI
scene in the autoload/singleton though [...] they break as soon as you
restructure your project a bit.
True, true. For some hard coded strings I'm planning on adding them to a
configuration file that can be edited through editor tools, and in case of
UI I just hope I won't have to alter the structure too much 😄
Just thinking out loud, I probably lean more towards adding the PauseMenu
and PlayerHUD as "components" to the Player.tscn.
That's definitely one way to do it and should work. For my own project I
try to decouple things like that, so you don't have to access the player to
get to the UI.
Quickly thinking about it, the only edge case where that could be an issue
is a game that allows switching the controllable character (for an
interesting example, see *Battlefield 2: Modern Combat*), but I guess
that would be more of a game implementation detail in the end, as in how do
you handle passing the control/updating the player object.
No need for another autoload/singleton
So I kind of ended up doing this in a hacky way because I like namespaces.
I only have a single autoload, that acts as namespace for singletons + is
config holder (global toggles etc.). This way I can then access every
singleton from a single namespace.
extends Node## A singleton that acts as a namespace for all other singletons.
# NOTE: An issue with this method of doing singletons, is that the autocompletion# does not seem to function (at least in Godot 4.2.1)var UserInterface: UserInterfaceSingleton = UserInterfaceSingleton.new()var ItemRepository: ItemRepositorySingleton = ItemRepositorySingleton.new()var Utils: UtilsSingleton = UtilsSingleton.new()
#region Paths# TODO: Fetch the correct folder from a config insteadvar items_path: String = "res://game/assets/items/"#endregion
#region Global toggles## Controls interactability globally.var interactions_allowed: bool = true
## Controls whether interaction prompts are generated globally.var generate_interaction_prompts: bool = true
## Controls whether carried items can be picked or not.var can_pick_carried_item: bool = true#endregion
If that were loaded simply as Cogito, you could use it like
Cogito.UserInterface etc.
—
Reply to this email directly, view it on GitHub
<#179 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABJVOI7SQW24H3FOCMYCKTTZAH54BAVCNFSM6AAAAABG2VEDPCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAOBZHE2DGNJYGM>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
If I understood correctly, essentially we'd want to have the ability to plug in your own UI scenes instead of using the built-in ones, right? |
Yes, that's what I would like to see.
…On Thu, May 2, 2024, 08:51 aronand ***@***.***> wrote:
If I understood correctly, essentially we'd want to have the ability to
plug in your own UI scenes instead of using the built-in ones, right?
—
Reply to this email directly, view it on GitHub
<#179 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABJVOI3VBJS5IMRP5O6CXP3ZAJOI7AVCNFSM6AAAAABG2VEDPCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAOJQHA3DINZZGQ>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Thinking about it, at least with the injection route I think some sort of a Cogito project config would be necessary to achieve that (not necessarily a config, could be some central script as well of course). As long as the custom UI implements a Cogito UI interface (so probably just create a base class which the UI script should extend), it should be good to use. On the other hand, if attached to the player, the user could create a copy of the player scene, modify it, and use that in their own levels. Might cause some headaches if trying to integrate changes from Cogito to own project, depending on how heavily it otherwise stays dependent on Cogito's scripts, or doesn't. |
Currently in my mp project I've extended the menu class, so either approach
seems workable to me.
To add some context, I've got a MP extension scene which loads the demo
scene in and then finds the menu, deletes it, and replaces it with a new
one.
…On Thu, May 2, 2024, 10:37 aronand ***@***.***> wrote:
Thinking about it, at least with the injection route I think some sort of
a Cogito project config would be necessary to achieve that. As long as the
custom UI implements a Cogito UI interface (so probably just create a base
class which the UI script should extend), it should be good to use.
On the other hand, if attached to the player, the user could create a copy
of the player scene, modify it, and use that in their own levels. Might
cause some headaches if trying to integrate changes from Cogito to own
project, depending on how heavily it otherwise stays dependent on Cogito's
scripts, or doesn't.
—
Reply to this email directly, view it on GitHub
<#179 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABJVOI5TITNPZNMIFAAXHR3ZAJ2WPAVCNFSM6AAAAABG2VEDPCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAOJRGE2DANZWG4>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Sorry for the late reply, had to deal with my main game project and then worked on some other ends of Cogito.
I was thinking this more and more recently. In Unity there's the Indexer pattern, that can be used to specify a global singleton that works like a ScriptableObject. I'd love to have something similar in Cogito, though we'd probably have to go the plug-in route of creating a For the 1.0 release I'd probably keep it simpler though. |
What about a resource for Cogito configuration? It could be top level in the cogito directory and we can point it out in the readme. In Unity terms its like a Scriptable Object I think I would be happy though with an object in the scene that you point to a player scene which already contains a player, hud, and pause menu. Users could just change the scene it is pointed to. This way all the correct player settings are loaded for their project rather than needing to make sure it is set up correctly in every single scene. Perhaps this could be handled in scene loading. |
Closing this now as it's no longer an issue per se. |
As far as I can tell, currently the HUD has to be added to each map scene for it to work/exist. I propose that it is instead instantiated during scene loading (either in
CogitoSceneManager
or inCogitoScene
), or/and made into a singleton as we'll most likely not have or need multiple instances of the HUD for the player.Going with a singleton would open new possibilities for updating data as well. This could possibly allow us to signal (some) user interface changes directly via the singleton.
Singleton pseudocode
The text was updated successfully, but these errors were encountered: