Skip to content

Commit 6083546

Browse files
committed
Add game speed controls to the embedded game window
1 parent fc523ec commit 6083546

File tree

6 files changed

+149
-2
lines changed

6 files changed

+149
-2
lines changed

core/config/engine.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,18 @@
3838
#include "core/version.h"
3939
#include "servers/rendering/rendering_device.h"
4040

41+
void Engine::_update_time_scale() {
42+
double wanted_time_scale = time_scale_override_enabled
43+
? time_scale_override * time_scale_base
44+
: time_scale_base;
45+
46+
if (_time_scale == wanted_time_scale) {
47+
return;
48+
}
49+
50+
_time_scale = wanted_time_scale;
51+
}
52+
4153
void Engine::set_physics_ticks_per_second(int p_ips) {
4254
ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0.");
4355
ips = p_ips;
@@ -113,6 +125,11 @@ uint32_t Engine::get_frame_delay() const {
113125

114126
void Engine::set_time_scale(double p_scale) {
115127
_time_scale = p_scale;
128+
if (time_scale_base == p_scale) {
129+
return;
130+
}
131+
time_scale_base = p_scale;
132+
_update_time_scale();
116133
}
117134

118135
double Engine::get_time_scale() const {
@@ -404,6 +421,36 @@ bool Engine::is_embedded_in_editor() const {
404421
return embedded_in_editor;
405422
}
406423

424+
void Engine::set_time_scale_base(double p_scale) {
425+
time_scale_base = p_scale;
426+
}
427+
428+
void Engine::set_time_scale_override(double p_scale) {
429+
if (time_scale_override == p_scale) {
430+
return;
431+
}
432+
time_scale_override = p_scale;
433+
if (is_time_scale_override_enabled()) {
434+
_update_time_scale();
435+
}
436+
}
437+
438+
double Engine::get_time_scale_override() {
439+
return time_scale_override;
440+
}
441+
442+
void Engine::set_time_scale_override_enabled(bool p_enabled) {
443+
if (time_scale_override_enabled == p_enabled) {
444+
return;
445+
}
446+
time_scale_override_enabled = p_enabled;
447+
_update_time_scale();
448+
}
449+
450+
bool Engine::is_time_scale_override_enabled() {
451+
return time_scale_override_enabled;
452+
}
453+
407454
Engine::Engine() {
408455
singleton = this;
409456
}

core/config/engine.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,13 @@ class Engine {
101101

102102
bool freeze_time_scale = false;
103103

104+
double time_scale_base;
105+
double time_scale_override;
106+
bool time_scale_override_enabled;
107+
108+
protected:
109+
void _update_time_scale();
110+
104111
public:
105112
static Engine *get_singleton();
106113

@@ -210,6 +217,12 @@ class Engine {
210217
void set_embedded_in_editor(bool p_enabled);
211218
bool is_embedded_in_editor() const;
212219

220+
void set_time_scale_override(double p_scale);
221+
void set_time_scale_base(double p_scale);
222+
double get_time_scale_override();
223+
void set_time_scale_override_enabled(bool p_enabled);
224+
bool is_time_scale_override_enabled();
225+
213226
Engine();
214227
virtual ~Engine();
215228
};

editor/plugins/game_view_plugin.cpp

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,6 @@ void GameView::_sessions_changed() {
240240
active_sessions++;
241241
}
242242
}
243-
244243
_update_debugger_buttons();
245244

246245
#ifdef MACOS_ENABLED
@@ -419,6 +418,8 @@ void GameView::_update_debugger_buttons() {
419418

420419
suspend_button->set_disabled(empty);
421420
camera_override_button->set_disabled(empty);
421+
speed_state_button->set_disabled(empty);
422+
reset_speed_button->set_disabled(empty);
422423

423424
PopupMenu *menu = camera_override_menu->get_popup();
424425

@@ -431,6 +432,8 @@ void GameView::_update_debugger_buttons() {
431432
camera_override_button->set_pressed(false);
432433
}
433434
next_frame_button->set_disabled(!suspend_button->is_pressed());
435+
436+
_reset_time_scales();
434437
}
435438

436439
void GameView::_handle_shortcut_requested(int p_embed_action) {
@@ -511,6 +514,44 @@ void GameView::_size_mode_button_pressed(int size_mode) {
511514
_update_embed_window_size();
512515
}
513516

517+
void GameView::_reset_time_scales() {
518+
time_scale_index = DEFUALT_TIME_SCALE_INDEX;
519+
_update_time_scales();
520+
}
521+
522+
void GameView::_update_time_scales() {
523+
bool disabled = time_scale_index == DEFUALT_TIME_SCALE_INDEX;
524+
Array message;
525+
message.append(!disabled);
526+
message.append(time_scale_range[time_scale_index]);
527+
Array sessions = debugger->get_sessions();
528+
for (int i = 0; i < sessions.size(); i++) {
529+
if (Object::cast_to<EditorDebuggerSession>(sessions[i])->is_active()) {
530+
Ref<EditorDebuggerSession> session = sessions[i];
531+
session->send_message("scene:speed_changed", message);
532+
}
533+
}
534+
Color text_color;
535+
if (time_scale_index == DEFUALT_TIME_SCALE_INDEX) {
536+
text_color = Color(1.0f, 1.0f, 1.0f);
537+
} else if (time_scale_index > DEFUALT_TIME_SCALE_INDEX) {
538+
text_color = Color(0.0f, 1.0f, 0.0f);
539+
} else if (time_scale_index < DEFUALT_TIME_SCALE_INDEX) {
540+
text_color = Color(1.0f, 1.0f, 0.0f);
541+
}
542+
speed_state_button->add_theme_color_override("font_color", text_color);
543+
speed_state_button->set_text(vformat("%0.2fx", time_scale_range[time_scale_index]));
544+
reset_speed_button->set_disabled(disabled);
545+
}
546+
547+
void GameView::_speed_state_menu_pressed(int p_id) {
548+
if (time_scale_index == p_id) {
549+
return;
550+
}
551+
time_scale_index = p_id;
552+
_update_time_scales();
553+
}
554+
514555
GameView::EmbedAvailability GameView::_get_embed_available() {
515556
if (!DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_WINDOW_EMBEDDING)) {
516557
return EMBED_NOT_AVAILABLE_FEATURE_NOT_SUPPORTED;
@@ -700,6 +741,7 @@ void GameView::_notification(int p_what) {
700741
case NOTIFICATION_THEME_CHANGED: {
701742
suspend_button->set_button_icon(get_editor_theme_icon(SNAME("Pause")));
702743
next_frame_button->set_button_icon(get_editor_theme_icon(SNAME("NextFrame")));
744+
reset_speed_button->set_button_icon(get_editor_theme_icon(SNAME("Reload")));
703745

704746
node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE]->set_button_icon(get_editor_theme_icon(SNAME("InputEventJoypadMotion")));
705747
node_type_button[RuntimeNodeSelect::NODE_TYPE_2D]->set_button_icon(get_editor_theme_icon(SNAME("2DNodes")));
@@ -995,6 +1037,27 @@ GameView::GameView(Ref<GameViewDebugger> p_debugger, EmbeddedProcessBase *p_embe
9951037
next_frame_button->set_accessibility_name(TTRC("Next Frame"));
9961038
next_frame_button->set_shortcut(ED_SHORTCUT("editor/next_frame_embedded_project", TTRC("Next Frame"), Key::F10));
9971039

1040+
speed_state_button = memnew(MenuButton);
1041+
main_menu_hbox->add_child(speed_state_button);
1042+
speed_state_button->set_text(TTRC("1.00x"));
1043+
speed_state_button->set_theme_type_variation("FlatButton");
1044+
speed_state_button->set_tooltip_text(TTRC("Change the game speed."));
1045+
speed_state_button->set_accessibility_name(TTRC("Speed State"));
1046+
speed_state_button->set_custom_minimum_size(Vector2(48, 0));
1047+
1048+
PopupMenu *menu = speed_state_button->get_popup();
1049+
menu->connect(SceneStringName(id_pressed), callable_mp(this, &GameView::_speed_state_menu_pressed));
1050+
for (float f : time_scale_range) {
1051+
menu->add_item(TTRC(vformat("%0.2fx", f)));
1052+
}
1053+
1054+
reset_speed_button = memnew(Button);
1055+
main_menu_hbox->add_child(reset_speed_button);
1056+
reset_speed_button->set_theme_type_variation("FlatButton");
1057+
reset_speed_button->set_tooltip_text(TTRC("Reset the game speed."));
1058+
reset_speed_button->set_accessibility_name(TTRC("Reset Speed"));
1059+
reset_speed_button->connect(SceneStringName(pressed), callable_mp(this, &GameView::_reset_time_scales));
1060+
9981061
main_menu_hbox->add_child(memnew(VSeparator));
9991062

10001063
node_type_button[RuntimeNodeSelect::NODE_TYPE_NONE] = memnew(Button);
@@ -1079,7 +1142,7 @@ GameView::GameView(Ref<GameViewDebugger> p_debugger, EmbeddedProcessBase *p_embe
10791142
camera_override_menu->set_tooltip_text(TTRC("Camera Override Options"));
10801143
camera_override_menu->set_accessibility_name(TTRC("Camera Override Options"));
10811144

1082-
PopupMenu *menu = camera_override_menu->get_popup();
1145+
menu = camera_override_menu->get_popup();
10831146
menu->connect(SceneStringName(id_pressed), callable_mp(this, &GameView::_camera_override_menu_id_pressed));
10841147
menu->add_item(TTRC("Reset 2D Camera"), CAMERA_RESET_2D);
10851148
menu->add_item(TTRC("Reset 3D Camera"), CAMERA_RESET_3D);

editor/plugins/game_view_plugin.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,13 @@ class GameView : public VBoxContainer {
157157
EmbeddedProcessBase *embedded_process = nullptr;
158158
Label *state_label = nullptr;
159159

160+
int const DEFUALT_TIME_SCALE_INDEX = 5;
161+
Array time_scale_range = { 0.0625f, 0.125f, 0.25f, 0.5f, 0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f, 4.0f, 8.0f, 16.0f };
162+
int time_scale_index = DEFUALT_TIME_SCALE_INDEX;
163+
164+
MenuButton *speed_state_button = nullptr;
165+
Button *reset_speed_button = nullptr;
166+
160167
void _sessions_changed();
161168

162169
void _update_debugger_buttons();
@@ -170,6 +177,10 @@ class GameView : public VBoxContainer {
170177
void _embed_options_menu_menu_id_pressed(int p_id);
171178
void _size_mode_button_pressed(int size_mode);
172179

180+
void _reset_time_scales();
181+
void _update_time_scales();
182+
void _speed_state_menu_pressed(int p_id);
183+
173184
void _play_pressed();
174185
static void _instance_starting_static(int p_idx, List<String> &r_arguments);
175186
void _instance_starting(int p_idx, List<String> &r_arguments);

scene/debugger/scene_debugger.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,17 @@ Error SceneDebugger::_msg_next_frame(const Array &p_args) {
183183
return OK;
184184
}
185185

186+
Error SceneDebugger::_msg_speed_changed(const Array &p_args) {
187+
bool enabled = Engine::get_singleton()->is_time_scale_override_enabled();
188+
double time_scale = Engine::get_singleton()->get_time_scale();
189+
if (!enabled) {
190+
Engine::get_singleton()->set_time_scale_base(time_scale);
191+
}
192+
Engine::get_singleton()->set_time_scale_override_enabled(p_args[0]);
193+
Engine::get_singleton()->set_time_scale_override(p_args[1]);
194+
return OK;
195+
}
196+
186197
Error SceneDebugger::_msg_debug_mute_audio(const Array &p_args) {
187198
ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA);
188199
bool do_mute = p_args[0];
@@ -457,6 +468,7 @@ void SceneDebugger::_init_message_handlers() {
457468
message_handlers["clear_selection"] = _msg_clear_selection;
458469
message_handlers["suspend_changed"] = _msg_suspend_changed;
459470
message_handlers["next_frame"] = _msg_next_frame;
471+
message_handlers["speed_changed"] = _msg_speed_changed;
460472
message_handlers["debug_mute_audio"] = _msg_debug_mute_audio;
461473
message_handlers["override_cameras"] = _msg_override_cameras;
462474
message_handlers["transform_camera_2d"] = _msg_transform_camera_2d;

scene/debugger/scene_debugger.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class SceneDebugger {
8686
static Error _msg_clear_selection(const Array &p_args);
8787
static Error _msg_suspend_changed(const Array &p_args);
8888
static Error _msg_next_frame(const Array &p_args);
89+
static Error _msg_speed_changed(const Array &p_args);
8990
static Error _msg_debug_mute_audio(const Array &p_args);
9091
static Error _msg_override_cameras(const Array &p_args);
9192
static Error _msg_transform_camera_2d(const Array &p_args);

0 commit comments

Comments
 (0)