Skip to content

Commit b46b8c2

Browse files
committed
Add game speed controls to the embedded game window
1 parent 1bbfe63 commit b46b8c2

File tree

6 files changed

+136
-1
lines changed

6 files changed

+136
-1
lines changed

core/config/engine.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@
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 * time_scale_base;
43+
44+
if (_time_scale == wanted_time_scale) {
45+
return;
46+
}
47+
48+
_time_scale = wanted_time_scale;
49+
}
50+
4151
void Engine::set_physics_ticks_per_second(int p_ips) {
4252
ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0.");
4353
ips = p_ips;
@@ -113,6 +123,11 @@ uint32_t Engine::get_frame_delay() const {
113123

114124
void Engine::set_time_scale(double p_scale) {
115125
_time_scale = p_scale;
126+
if (time_scale_base == p_scale) {
127+
return;
128+
}
129+
time_scale_base = p_scale;
130+
_update_time_scale();
116131
}
117132

118133
double Engine::get_time_scale() const {
@@ -404,6 +419,28 @@ bool Engine::is_embedded_in_editor() const {
404419
return embedded_in_editor;
405420
}
406421

422+
void Engine::set_time_scale_base(double p_scale) {
423+
time_scale_base = p_scale;
424+
}
425+
426+
void Engine::set_time_scale_override(double p_scale) {
427+
if (time_scale_override == p_scale) {
428+
return;
429+
}
430+
time_scale_override = p_scale;
431+
if (is_time_scale_override_enabled()) {
432+
_update_time_scale();
433+
}
434+
}
435+
436+
double Engine::get_time_scale_override() {
437+
return time_scale_override;
438+
}
439+
440+
bool Engine::is_time_scale_override_enabled() {
441+
return time_scale_override == 1.0;
442+
}
443+
407444
Engine::Engine() {
408445
singleton = this;
409446
}

core/config/engine.h

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

102102
bool freeze_time_scale = false;
103103

104+
double time_scale_base;
105+
double time_scale_override;
106+
107+
protected:
108+
void _update_time_scale();
109+
104110
public:
105111
static Engine *get_singleton();
106112

@@ -210,6 +216,11 @@ class Engine {
210216
void set_embedded_in_editor(bool p_enabled);
211217
bool is_embedded_in_editor() const;
212218

219+
void set_time_scale_override(double p_scale);
220+
void set_time_scale_base(double p_scale);
221+
double get_time_scale_override();
222+
bool is_time_scale_override_enabled();
223+
213224
Engine();
214225
virtual ~Engine();
215226
};

editor/plugins/game_view_plugin.cpp

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,8 @@ void GameView::_update_debugger_buttons() {
419419

420420
suspend_button->set_disabled(empty);
421421
camera_override_button->set_disabled(empty);
422+
speed_state_button->set_disabled(empty);
423+
reset_speed_button->set_disabled(empty);
422424

423425
PopupMenu *menu = camera_override_menu->get_popup();
424426

@@ -431,6 +433,8 @@ void GameView::_update_debugger_buttons() {
431433
camera_override_button->set_pressed(false);
432434
}
433435
next_frame_button->set_disabled(!suspend_button->is_pressed());
436+
437+
_reset_time_scales();
434438
}
435439

436440
void GameView::_handle_shortcut_requested(int p_embed_action) {
@@ -511,6 +515,43 @@ void GameView::_size_mode_button_pressed(int size_mode) {
511515
_update_embed_window_size();
512516
}
513517

518+
void GameView::_reset_time_scales() {
519+
time_scale_index = DEFAULT_TIME_SCALE_INDEX;
520+
_update_time_scales();
521+
}
522+
523+
void GameView::_update_time_scales() {
524+
Array message;
525+
message.append(time_scale_range[time_scale_index]);
526+
Array sessions = debugger->get_sessions();
527+
for (int i = 0; i < sessions.size(); i++) {
528+
if (Object::cast_to<EditorDebuggerSession>(sessions[i])->is_active()) {
529+
Ref<EditorDebuggerSession> session = sessions[i];
530+
session->send_message("scene:speed_changed", message);
531+
}
532+
}
533+
Color text_color;
534+
if (time_scale_index == DEFAULT_TIME_SCALE_INDEX) {
535+
text_color = Color(1.0f, 1.0f, 1.0f);
536+
} else if (time_scale_index > DEFAULT_TIME_SCALE_INDEX) {
537+
text_color = Color(0.0f, 1.0f, 0.0f);
538+
} else if (time_scale_index < DEFAULT_TIME_SCALE_INDEX) {
539+
text_color = Color(1.0f, 1.0f, 0.0f);
540+
}
541+
bool disabled = time_scale_index == DEFAULT_TIME_SCALE_INDEX;
542+
reset_speed_button->set_disabled(disabled);
543+
speed_state_button->add_theme_color_override("font_color", text_color);
544+
speed_state_button->set_text(vformat("%0.2fx", time_scale_range[time_scale_index]));
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 DEFAULT_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 = DEFAULT_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+
double time_scale_override = p_args[0];
193+
Engine::get_singleton()->set_time_scale_override(time_scale_override);
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)