summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
authorreduz <reduzio@gmail.com>2022-06-17 00:55:19 +0200
committerreduz <reduzio@gmail.com>2022-06-21 11:28:47 +0200
commit5786516d4d6b517e6a28aec191f944aecf2f544d (patch)
tree8a79324296035a7aa8b7802d610596912b7c1642 /editor
parent362f53ff02c381ea94640baa16e84e6f6956efef (diff)
Implement Running Godot as Movie Writer
* Allows running the game in "movie writer" mode. * It ensures entirely stable framerate, so your run can be saved stable and with proper sound (which is impossible if your CPU/GPU can't sustain doing this in real-time). * If disabling vsync, it can save movies faster than the game is run, but if you want to control the interaction it can get difficult. * Implements a simple, default MJPEG writer. This new features has two main use cases, which have high demand: * Saving game videos in high quality and ensuring the frame rate is *completely* stable, always. * Using Godot as a tool to make movies and animations (which is ideal if you want interaction, or creating them procedurally. No other software is as good for this). **Note**: This feature **IS NOT** for capturing real-time footage. Use something like OBS, SimpleScreenRecorder or FRAPS to achieve that, as they do a much better job at intercepting the compositor than Godot can probably do using Vulkan or OpenGL natively. If your game runs near real-time when capturing, you can still use this feature but it will play no sound (sound will be saved directly). Usage: $ godot --write-movie movie.avi [scene_file.tscn] Missing: * Options for configuring video writing via GLOBAL_DEF * UI Menu for launching with this mode from the editor. * Add to list of command line options. * Add a feature tag to override configurations when movie writing (fantastic for saving videos with highest quality settings).
Diffstat (limited to 'editor')
-rw-r--r--editor/editor_node.cpp44
-rw-r--r--editor/editor_node.h4
-rw-r--r--editor/editor_properties.cpp6
-rw-r--r--editor/editor_run.cpp12
-rw-r--r--editor/editor_run.h2
-rw-r--r--editor/icons/MainMovieWrite.svg1
-rw-r--r--editor/icons/MainMovieWriteEnabled.svg1
-rw-r--r--editor/project_settings_editor.cpp4
8 files changed, 67 insertions, 7 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 67d0b83bd6..5cff088d0c 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -2342,6 +2342,20 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
return;
}
+ String write_movie_file;
+ if (write_movie_button->is_pressed()) {
+ if (p_current && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->has_meta("movie_file")) {
+ // If the scene file has a movie_file metadata set, use this as file. Quick workaround if you want to have multiple scenes that write to multiple movies.
+ write_movie_file = get_tree()->get_edited_scene_root()->get_meta("movie_file");
+ } else {
+ write_movie_file = GLOBAL_GET("editor/movie_writer/movie_file");
+ }
+ if (write_movie_file == String()) {
+ show_accept(TTR("Movie Maker mode is enabled, but no movie file path has been specified.\nA default movie file path can be specified in the project settings under the 'Editor/Movie Writer' category.\nAlternatively, for running single scenes, a 'movie_path' metadata can be added to the root node,\nspecifying the path to a movie file that will be used when recording that scene."), TTR("OK"));
+ return;
+ }
+ }
+
play_button->set_pressed(false);
play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons")));
play_scene_button->set_pressed(false);
@@ -2405,7 +2419,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
}
EditorDebuggerNode::get_singleton()->start();
- Error error = editor_run.run(run_filename);
+ Error error = editor_run.run(run_filename, write_movie_file);
if (error != OK) {
EditorDebuggerNode::get_singleton()->stop();
show_accept(TTR("Could not start subprocess(es)!"), TTR("OK"));
@@ -2788,6 +2802,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case RUN_SETTINGS: {
project_settings_editor->popup_project_settings();
} break;
+ case RUN_WRITE_MOVIE: {
+ _update_write_movie_icon();
+ } break;
case FILE_INSTALL_ANDROID_SOURCE: {
if (p_confirmed) {
export_template_manager->install_android_template();
@@ -4949,6 +4966,14 @@ String EditorNode::get_run_playing_scene() const {
return run_filename;
}
+void EditorNode::_update_write_movie_icon() {
+ if (write_movie_button->is_pressed()) {
+ write_movie_button->set_icon(gui_base->get_theme_icon(SNAME("MainMovieWriteEnabled"), SNAME("EditorIcons")));
+ } else {
+ write_movie_button->set_icon(gui_base->get_theme_icon(SNAME("MainMovieWrite"), SNAME("EditorIcons")));
+ }
+}
+
void EditorNode::_immediate_dialog_confirmed() {
immediate_dialog_confirmed = true;
}
@@ -6704,6 +6729,23 @@ EditorNode::EditorNode() {
ED_SHORTCUT_OVERRIDE("editor/play_custom_scene", "macos", KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::R);
play_custom_scene_button->set_shortcut(ED_GET_SHORTCUT("editor/play_custom_scene"));
+ write_movie_button = memnew(Button);
+ write_movie_button->set_flat(true);
+ write_movie_button->set_toggle_mode(true);
+ play_hb->add_child(write_movie_button);
+ write_movie_button->set_pressed(false);
+ write_movie_button->set_icon(gui_base->get_theme_icon(SNAME("MainMovieWrite"), SNAME("EditorIcons")));
+ write_movie_button->set_focus_mode(Control::FOCUS_NONE);
+ write_movie_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option), make_binds(RUN_WRITE_MOVIE));
+ write_movie_button->set_tooltip(TTR("Enable Movie Maker mode.\nThe project will run at stable FPS and the visual and audio output will be recorded to a video file."));
+ // Restore these values to something more useful so it ignores the theme
+ write_movie_button->add_theme_color_override("icon_normal_color", Color(1, 1, 1, 0.4));
+ write_movie_button->add_theme_color_override("icon_pressed_color", Color(1, 1, 1, 1));
+ write_movie_button->add_theme_color_override("icon_hover_color", Color(1.2, 1.2, 1.2, 0.4));
+ write_movie_button->add_theme_color_override("icon_hover_pressed_color", Color(1.2, 1.2, 1.2, 1));
+ write_movie_button->add_theme_color_override("icon_focus_color", Color(1, 1, 1, 1));
+ write_movie_button->add_theme_color_override("icon_disabled_color", Color(1, 1, 1, 0.4));
+
HBoxContainer *right_menu_hb = memnew(HBoxContainer);
menu_hb->add_child(right_menu_hb);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 48df767562..89f80baeb9 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -173,6 +173,7 @@ private:
RUN_PLAY_CUSTOM_SCENE,
RUN_SETTINGS,
RUN_USER_DATA_FOLDER,
+ RUN_WRITE_MOVIE,
RELOAD_CURRENT_PROJECT,
RUN_PROJECT_MANAGER,
RUN_VCS_METADATA,
@@ -333,6 +334,7 @@ private:
Button *play_scene_button = nullptr;
Button *play_custom_scene_button = nullptr;
Button *search_button = nullptr;
+ Button *write_movie_button = nullptr;
TextureProgressBar *audio_vu = nullptr;
Timer *screenshot_timer = nullptr;
@@ -667,7 +669,7 @@ private:
void _pick_main_scene_custom_action(const String &p_custom_action_name);
void _immediate_dialog_confirmed();
-
+ void _update_write_movie_icon();
void _select_default_main_screen_plugin();
void _bottom_panel_switch(bool p_enable, int p_idx);
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index a5c02c70d9..61b434a240 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -3747,11 +3747,11 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_
EditorPropertyLocale *editor = memnew(EditorPropertyLocale);
editor->setup(p_hint_text);
return editor;
- } else if (p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_FILE || p_hint == PROPERTY_HINT_SAVE_FILE || p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE) {
+ } else if (p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_FILE || p_hint == PROPERTY_HINT_SAVE_FILE || p_hint == PROPERTY_HINT_GLOBAL_SAVE_FILE || p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE) {
Vector<String> extensions = p_hint_text.split(",");
- bool global = p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE;
+ bool global = p_hint == PROPERTY_HINT_GLOBAL_DIR || p_hint == PROPERTY_HINT_GLOBAL_FILE || p_hint == PROPERTY_HINT_GLOBAL_SAVE_FILE;
bool folder = p_hint == PROPERTY_HINT_DIR || p_hint == PROPERTY_HINT_GLOBAL_DIR;
- bool save = p_hint == PROPERTY_HINT_SAVE_FILE;
+ bool save = p_hint == PROPERTY_HINT_SAVE_FILE || p_hint == PROPERTY_HINT_GLOBAL_SAVE_FILE;
EditorPropertyPath *editor = memnew(EditorPropertyPath);
editor->setup(extensions, folder, global);
if (save) {
diff --git a/editor/editor_run.cpp b/editor/editor_run.cpp
index 6a2ff50ee0..04a3bf2915 100644
--- a/editor/editor_run.cpp
+++ b/editor/editor_run.cpp
@@ -43,7 +43,7 @@ String EditorRun::get_running_scene() const {
return running_scene;
}
-Error EditorRun::run(const String &p_scene) {
+Error EditorRun::run(const String &p_scene, const String &p_write_movie) {
List<String> args;
String resource_path = ProjectSettings::get_singleton()->get_resource_path();
@@ -68,6 +68,16 @@ Error EditorRun::run(const String &p_scene) {
args.push_back("--debug-navigation");
}
+ if (p_write_movie != "") {
+ args.push_back("--write-movie");
+ args.push_back(p_write_movie);
+ args.push_back("--fixed-fps");
+ args.push_back(itos(GLOBAL_GET("editor/movie_writer/fps")));
+ if (bool(GLOBAL_GET("editor/movie_writer/disable_vsync"))) {
+ args.push_back("--disable-vsync");
+ }
+ }
+
int screen = EditorSettings::get_singleton()->get("run/window_placement/screen");
if (screen == 0) {
// Same as editor
diff --git a/editor/editor_run.h b/editor/editor_run.h
index 50604ff032..4cbc6838e4 100644
--- a/editor/editor_run.h
+++ b/editor/editor_run.h
@@ -50,7 +50,7 @@ private:
public:
Status get_status() const;
String get_running_scene() const;
- Error run(const String &p_scene);
+ Error run(const String &p_scene, const String &p_write_movie = "");
void run_native_notify() { status = STATUS_PLAY; }
void stop();
diff --git a/editor/icons/MainMovieWrite.svg b/editor/icons/MainMovieWrite.svg
new file mode 100644
index 0000000000..21464bb57c
--- /dev/null
+++ b/editor/icons/MainMovieWrite.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M8 2a6 6 0 0 0-6 6 6 6 0 0 0 6 6 6 6 0 0 0 4-1.535V14h.002a2 2 0 0 0 .266 1A2 2 0 0 0 14 16h1v-2h-.5a.5.5 0 0 1-.5-.5V8a6 6 0 0 0-6-6zm0 1a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm3.441 2a1 1 0 0 1 .89.5 1 1 0 0 1-.366 1.365 1 1 0 0 1-1.367-.365 1 1 0 0 1 .367-1.365A1 1 0 0 1 11.44 5zm-6.953.002a1 1 0 0 1 .547.133A1 1 0 0 1 5.402 6.5a1 1 0 0 1-1.367.365A1 1 0 0 1 3.67 5.5a1 1 0 0 1 .818-.498zM4.512 9a1 1 0 0 1 .89.5 1 1 0 0 1-.367 1.365A1 1 0 0 1 3.67 10.5a1 1 0 0 1 .365-1.365A1 1 0 0 1 4.512 9zm6.904.002a1 1 0 0 1 .549.133 1 1 0 0 1 .365 1.365 1 1 0 0 1-1.365.365 1 1 0 0 1-.367-1.365 1 1 0 0 1 .818-.498zM8 11a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" fill="#e0e0e0"/></svg>
diff --git a/editor/icons/MainMovieWriteEnabled.svg b/editor/icons/MainMovieWriteEnabled.svg
new file mode 100644
index 0000000000..b12ea38bed
--- /dev/null
+++ b/editor/icons/MainMovieWriteEnabled.svg
@@ -0,0 +1 @@
+<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M8 2a6 6 0 0 0-6 6 6 6 0 0 0 6 6 6 6 0 0 0 4-1.535V14h.002a2 2 0 0 0 .266 1A2 2 0 0 0 14 16h1v-2h-.5a.5.5 0 0 1-.5-.5V8a6 6 0 0 0-6-6zm0 1a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm3.441 2a1 1 0 0 1 .89.5 1 1 0 0 1-.366 1.365 1 1 0 0 1-1.367-.365 1 1 0 0 1 .367-1.365A1 1 0 0 1 11.44 5zm-6.953.002a1 1 0 0 1 .547.133A1 1 0 0 1 5.402 6.5a1 1 0 0 1-1.367.365A1 1 0 0 1 3.67 5.5a1 1 0 0 1 .818-.498zM4.512 9a1 1 0 0 1 .89.5 1 1 0 0 1-.367 1.365A1 1 0 0 1 3.67 10.5a1 1 0 0 1 .365-1.365A1 1 0 0 1 4.512 9zm6.904.002a1 1 0 0 1 .549.133 1 1 0 0 1 .365 1.365 1 1 0 0 1-1.365.365 1 1 0 0 1-.367-1.365 1 1 0 0 1 .818-.498zM8 11a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1z" fill="#e0e0e0" style="fill:#ee5353;fill-opacity:1"/></svg>
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 404199d2da..1524993bd0 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -35,6 +35,7 @@
#include "editor/editor_log.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "servers/movie_writer/movie_writer.h"
ProjectSettingsEditor *ProjectSettingsEditor::singleton = nullptr;
@@ -261,6 +262,7 @@ void ProjectSettingsEditor::_add_feature_overrides() {
presets.insert("standalone");
presets.insert("32");
presets.insert("64");
+ presets.insert("movie");
EditorExport *ee = EditorExport::get_singleton();
@@ -698,4 +700,6 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
import_defaults_editor->set_name(TTR("Import Defaults"));
tab_container->add_child(import_defaults_editor);
import_defaults_editor->connect("project_settings_changed", callable_mp(this, &ProjectSettingsEditor::queue_save));
+
+ MovieWriter::set_extensions_hint(); // ensure extensions are properly displayed.
}