Open blackears opened 1 month ago
It can be worked around by manually changing window position based on launch arguments.
Can it be configured in project settings? Or do you need to run script commands in the _ready() of your first scene?
Both is possible actually.
display/window/size/initial_position
allows to define initial position of the window. You can use feature overrides to define multiple positions and then run your instances with different feature tags. However seems like you can't use custom tags in the settings dialog, so you can either add these settings manually in project.godot
or use existing tags.
Then provide these tags for the instances:
(though using default tags in this way is not recommended; better to use custom tags)
It's easier from code, if you have autoload singleton just set the position in _init()
, so it's moved at the very beginning.
I think this is something Godot can and should do on it's own, for the following reasons:
Run/Window Placement
editor settings section. Run/Window Placement
but this new use case is not handled gracefully. All windows follow exactly the same settings which means they end up in exactly the same position, with exactly the same size, fully covering each other, forcing the user to move them one by one. To flesh out the proposal a bit more I think the new settings could be the following:
Prop Name | Description |
---|---|
Multiple Instance Placement Style | Defines placement approach to use when running multiple instances. None (default): Do nothing. Preserve the current behavior Cascading: Use a cascading layout. Tiling: Use a grid layout |
Tile Grid Size | How to divide the screen space. Defaults to 2x1 (side-to-side split screen) |
Preserve Aspect Ratio | Off (default) : Each instance is resized to fully cover its assigned tile On: Each instance is resized so it fits inside it's assigned tile, while respecting the aspect ratio defined in "display/window/size/viewport_width" and "display/window/size/viewport_width" |
Q: Why add cascading? No one requested that A: I added it for completion since most window managers offer it, and we can easily get the title bar size with DisplayServer::window_get_title_size. Feel free to ignore it if you think it's unnecessary bloat.
Q: Why "Tile Grid Size" instead of just side by side? A: Because some users might want two instances side-by-side, others might want them top and bottom, others might have 4 instances instead. By letting the user just specify the grid size you cover all those cases with the same implementation
Q: What happens if the user sets the amount of instances to say, four, and the grid has fewer divisions, e.g: 2x1? A: The tile index wraps around and, in the example, you'd get instances 3 and 4 on top of 1 and 2 respectively. It's the responsibility of the user to set a grid size that makes sense for the amount of running instances. "Auto" could be an option but I don't know if changing the amount of running instances all the time is a common use case.
Q: What's the point of "Preserve Aspect Ratio"? A: Some games have UI and cameras designed for a specific aspect ratio (usually the 16:9 standard), so we might want to support that use case. Again feel free to ignore it if you think it's unnecesary
In editor_run.cpp around https://github.com/godotengine/godot/blob/88ed6af1e6844908293aa1599421b40870be513c/editor/editor_run.cpp#L125 we need to:
int instance_count = RunInstancesDialog::get_singleton()->get_instance_count();
Size2i size DisplayServer::window_get_title_size
and then iterate over the instance_count adding Size2i(size.y, size.y) * i
to the position of each windowint tile_count = grid_size.x * grid_size.y
assigned_tile = i % instance_count
assigned_tile
, grid_size
, and screen_rect
to calculate the size and position of each instance window@blackears I'm using this to have side by side windows when I test the project I'm working on
Then on some autoload:
@export var SPLIT_SCREEN_STYLE := VERTICAL
@export var USE_RATIO := true
func _ready():
var screen_rect = DisplayServer.screen_get_usable_rect()
var screen_ratio = screen_rect.size.aspect()
if SPLIT_SCREEN_STYLE == HORIZONTAL:
get_window().size.x = screen_rect.size.x / 2
get_window().size.y = get_window().size.x / screen_ratio if USE_RATIO else screen_rect.size.y
get_window().position.y = screen_rect.position.y
else:
get_window().size.y = screen_rect.size.y / 2
get_window().size.x = get_window().size.y * screen_ratio if USE_RATIO else screen_rect.size.x
get_window().position.x = screen_rect.position.x
if "--server" in OS.get_cmdline_args():
get_window().position = screen_rect.position
elif "--client" in OS.get_cmdline_args():
if SPLIT_SCREEN_STYLE == HORIZONTAL:
get_window().position.x = screen_rect.size.x / 2
else:
get_window().position.y = screen_rect.size.y / 2
Describe the project you are working on
A networked soccer game
Describe the problem or limitation you are having in your project
Debugging networked programs can be tough, especially because you often need multiple programs running at the same time. While the
Debug/Run Multiple Instances
provides a useful way to start many sessions at once, you must still manually resize and move the windows each time you start a new session. It would be really helpful if your multiple windows would open next to each other rather than exactly on top of each other.Describe the feature / enhancement and how it helps to overcome the problem or limitation
Add a 'tiled' checkbox option to the Debug/Run Multiple Instances section. When checked, the extra windows will be laid out next to each other in a grid instead of on top of each other.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
When you run, windows will be smaller and laid out in a grid instead of on top of each other.
If this enhancement will not be used often, can it be worked around with a few lines of script?
No
Is there a reason why this should be core and not an add-on in the asset library?
Requires changing how programs are launched.