summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
authorPedro J. Estébanez <pedrojrulez@gmail.com>2019-02-24 21:44:00 +0100
committerPedro J. Estébanez <pedrojrulez@gmail.com>2019-03-20 20:44:43 +0100
commit4db0f51b9aa76cfc7649787fe1970af606ce8dab (patch)
treef7d94d81e8de8bde54db97aebbe858d2663cc340 /editor
parentfb37284c027b494ed3ec21124001fcb729f42cc4 (diff)
Create live view dock [wip]
Diffstat (limited to 'editor')
-rw-r--r--editor/editor_node.cpp26
-rw-r--r--editor/editor_node.h3
-rw-r--r--editor/live_view.cpp170
-rw-r--r--editor/live_view.h62
-rw-r--r--editor/script_editor_debugger.cpp14
-rw-r--r--editor/script_editor_debugger.h2
6 files changed, 272 insertions, 5 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 6140412a32..1ce45c93f1 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -56,6 +56,7 @@
#include "editor/editor_properties.h"
#include "editor/editor_settings.h"
#include "editor/editor_themes.h"
+#include "editor/live_view.h"
#include "editor/import/editor_import_collada.h"
#include "editor/import/editor_scene_importer_gltf.h"
#include "editor/import/resource_importer_bitmask.h"
@@ -1808,6 +1809,8 @@ void EditorNode::_run(bool p_current, const String &p_custom) {
return;
}
+ live_view_dock->start();
+
emit_signal("play_pressed");
if (p_current) {
play_scene_button->set_pressed(true);
@@ -2149,6 +2152,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
break;
editor_run.stop();
+ live_view_dock->stop();
run_custom_filename.clear();
play_button->set_pressed(false);
play_button->set_icon(gui_base->get_icon("MainPlay", "EditorIcons"));
@@ -3125,6 +3129,10 @@ InspectorDock *EditorNode::get_inspector_dock() {
return inspector_dock;
}
+LiveViewDock *EditorNode::get_live_view_dock() {
+
+ return live_view_dock;
+}
void EditorNode::_instance_request(const Vector<String> &p_files) {
@@ -3217,6 +3225,7 @@ void EditorNode::notify_child_process_exited() {
_menu_option_confirm(RUN_STOP, false);
stop_button->set_pressed(false);
editor_run.stop();
+ live_view_dock->stop();
}
void EditorNode::add_io_error(const String &p_error) {
@@ -5690,6 +5699,7 @@ EditorNode::EditorNode() {
scene_tree_dock = memnew(SceneTreeDock(this, scene_root, editor_selection, editor_data));
inspector_dock = memnew(InspectorDock(this, editor_data));
+ live_view_dock = memnew(LiveViewDock);
import_dock = memnew(ImportDock);
node_dock = memnew(NodeDock);
@@ -5710,18 +5720,21 @@ EditorNode::EditorNode() {
dock_slot[DOCK_SLOT_LEFT_BR]->add_child(filesystem_dock);
dock_slot[DOCK_SLOT_LEFT_BR]->set_tab_title(filesystem_dock->get_index(), TTR("FileSystem"));
- // Inspector: Full height right
+ // Inspector: Right
dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(inspector_dock);
dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(inspector_dock->get_index(), TTR("Inspector"));
- // Node: Full height right, behind Inspector
+ // Node: Right, behind Inspector
dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(node_dock);
dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(node_dock->get_index(), TTR("Node"));
+ // Game preview: Bottom right
+ dock_slot[DOCK_SLOT_RIGHT_BL]->add_child(live_view_dock);
+ dock_slot[DOCK_SLOT_RIGHT_BL]->set_tab_title(live_view_dock->get_index(), TTR("LiveView"));
+
// Hide unused dock slots and vsplits
dock_slot[DOCK_SLOT_LEFT_UL]->hide();
dock_slot[DOCK_SLOT_LEFT_BL]->hide();
- dock_slot[DOCK_SLOT_RIGHT_BL]->hide();
dock_slot[DOCK_SLOT_RIGHT_UR]->hide();
dock_slot[DOCK_SLOT_RIGHT_BR]->hide();
left_l_vsplit->hide();
@@ -5740,9 +5753,12 @@ EditorNode::EditorNode() {
default_layout->set_value(docks_section, "dock_3", "Scene,Import");
default_layout->set_value(docks_section, "dock_4", "FileSystem");
default_layout->set_value(docks_section, "dock_5", "Inspector,Node");
+ default_layout->set_value(docks_section, "dock_6", "LiveView");
- for (int i = 0; i < vsplits.size(); i++)
- default_layout->set_value(docks_section, "dock_split_" + itos(i + 1), 0);
+ default_layout->set_value(docks_section, "dock_split_1", 0);
+ default_layout->set_value(docks_section, "dock_split_2", 0);
+ default_layout->set_value(docks_section, "dock_split_3", 160 * EDSCALE);
+ default_layout->set_value(docks_section, "dock_split_4", 0);
default_layout->set_value(docks_section, "dock_hsplit_1", 0);
default_layout->set_value(docks_section, "dock_hsplit_2", 70 * EDSCALE);
default_layout->set_value(docks_section, "dock_hsplit_3", -70 * EDSCALE);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 267c70c773..3fcf20d796 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -94,6 +94,7 @@ typedef void (*EditorPluginInitializeCallback)();
typedef bool (*EditorBuildCallback)();
class EditorPluginList;
+class LiveViewDock;
class EditorNode : public Node {
@@ -271,6 +272,7 @@ private:
PopupMenu *recent_scenes;
SceneTreeDock *scene_tree_dock;
InspectorDock *inspector_dock;
+ LiveViewDock *live_view_dock;
NodeDock *node_dock;
ImportDock *import_dock;
FileSystemDock *filesystem_dock;
@@ -713,6 +715,7 @@ public:
ImportDock *get_import_dock();
SceneTreeDock *get_scene_tree_dock();
InspectorDock *get_inspector_dock();
+ LiveViewDock *get_live_view_dock();
static UndoRedo *get_undo_redo() { return &singleton->editor_data.get_undo_redo(); }
EditorSelection *get_editor_selection() { return editor_selection; }
diff --git a/editor/live_view.cpp b/editor/live_view.cpp
new file mode 100644
index 0000000000..951d7dd5b6
--- /dev/null
+++ b/editor/live_view.cpp
@@ -0,0 +1,170 @@
+/*************************************************************************/
+/* live_view.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "editor/live_view.h"
+#include "core/os/shared_mem_access.h"
+#include "editor/script_editor_debugger.h"
+#include "scene/main/scene_tree.h"
+#include "scene/main/viewport.h"
+
+void LiveViewDock::_notification(int p_what) {
+
+ switch (p_what) {
+ case NOTIFICATION_PROCESS: {
+
+ if (!is_visible_in_tree()) {
+ waiting = false;
+ break;
+ }
+ if (waiting) {
+ break;
+ }
+
+ ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
+ if (sed) {
+ Array msg;
+ msg.push_back("request_framebuffer");
+ if (sed->send_message(msg)) {
+ waiting = true;
+ }
+ }
+ } break;
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+
+ if (!is_visible_in_tree()) {
+ waiting = false;
+ }
+ } break;
+ }
+}
+
+void LiveViewDock::start() {
+
+ fb_data->open
+
+ set_process(true);
+ waiting = false;
+}
+
+void LiveViewDock::stop() {
+
+ fb_data->close();
+
+ set_process(false);
+ waiting = false;
+}
+
+void LiveViewDock::update() {
+
+ if (!waiting) {
+ return;
+ }
+
+ if (!fb_data->is_open()) {
+ if (fb_data->open() != OK) {
+ return;
+ }
+ }
+
+ const uint32_t *data = (uint32_t *)fb_data->lock();
+ if (data) {
+
+ int width = data[0];
+ int height = data[1];
+ Image::Format format = (Image::Format)data[2];
+
+ int data_size = data[3];
+ PoolByteArray pixel_data;
+ pixel_data.resize(data_size);
+ {
+ PoolByteArray::Write w = pixel_data.write();
+ memcpy(w.ptr(), &data[4], data_size);
+ }
+
+ Ref<Image> img = memnew(Image);
+ img->create(width, height, false, format, pixel_data);
+
+ Ref<ImageTexture> tex = get_texture();
+ // Create if no texture or recreate if size or format changed
+ if (!tex.is_valid() ||
+ tex->get_width() != width ||
+ tex->get_height() != height ||
+ tex->get_data()->get_format() != format) {
+
+ tex = Ref<ImageTexture>(memnew(ImageTexture));
+ tex->create(width, height, format, Texture::FLAG_FILTER);
+ set_texture(tex);
+ }
+
+ tex->set_data(img);
+
+ fb_data->unlock();
+ }
+
+ waiting = false;
+}
+
+LiveViewDock::LiveViewDock() :
+ waiting(false),
+ fb_data(SharedMemAccess::create("godot_live_view")) {
+
+ fb_data->open(1);
+ fb_data->close();
+
+ set_expand(true);
+ set_stretch_mode(STRETCH_KEEP_ASPECT_CENTERED);
+
+ set_name("LiveView");
+}
+
+LiveViewDock::~LiveViewDock() {
+
+ memdelete(fb_data);
+}
+
+void LiveViewDebugHelper::_debugger_request_framebuffer(void *user_data) {
+
+ Ref<ViewportTexture> vp_texture = SceneTree::get_singleton()->get_root()->get_texture();
+ Ref<Image> framebuffer = vp_texture->get_data();
+
+ SharedMemAccess *fb_data = SharedMemAccess::create("godot_live_view");
+ fb_data->
+
+ uint32_t data_size = framebuffer->get_data().size();
+
+ Array result;
+ result.append(framebuffer->get_width());
+ result.append(framebuffer->get_height());
+ result.append(framebuffer->get_format());
+ result.append(framebuffer->get_data().size());
+ result.append(framebuffer->get_data());
+
+ ScriptDebugger::get_singleton()->send_message("framebuffer", result);
+}
diff --git a/editor/live_view.h b/editor/live_view.h
new file mode 100644
index 0000000000..be0b61d087
--- /dev/null
+++ b/editor/live_view.h
@@ -0,0 +1,62 @@
+/*************************************************************************/
+/* live_view.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef LIVE_VIEW_H
+#define LIVE_VIEW_H
+
+#include "scene/gui/texture_rect.h"
+
+class SharedMemAccess;
+
+class LiveViewDock : public TextureRect {
+
+ GDCLASS(LiveViewDock, TextureRect);
+
+ bool waiting;
+ SharedMemAccess *fb_data;
+
+protected:
+ void _notification(int p_what);
+
+public:
+ void start();
+ void stop();
+ void update();
+
+ LiveViewDock();
+ ~LiveViewDock();
+};
+
+class LiveViewDebugHelper {
+public:
+ static void _debugger_request_framebuffer(void *user_data);
+};
+
+#endif // LIVE_VIEW_H
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index dda46d2414..160832305a 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -33,6 +33,7 @@
#include "core/io/marshalls.h"
#include "core/project_settings.h"
#include "core/ustring.h"
+#include "editor/live_view.h"
#include "editor_node.h"
#include "editor_profiler.h"
#include "editor_settings.h"
@@ -459,6 +460,10 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
le_clear->set_disabled(false);
le_set->set_disabled(false);
+ } else if (p_msg == "message:framebuffer") {
+
+ EditorNode::get_singleton()->get_live_view_dock()->update();
+
} else if (p_msg == "message:inspect_object") {
ScriptEditorDebuggerInspectedObject *debugObj = NULL;
@@ -1680,6 +1685,15 @@ void ScriptEditorDebugger::live_debug_reparent_node(const NodePath &p_at, const
}
}
+bool ScriptEditorDebugger::send_message(const Array &p_message) {
+
+ if (!connection.is_valid()) {
+ return false;
+ }
+ ppeer->put_var(p_message);
+ return true;
+}
+
void ScriptEditorDebugger::set_breakpoint(const String &p_path, int p_line, bool p_enabled) {
if (connection.is_valid()) {
diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h
index fb1545559c..195462090c 100644
--- a/editor/script_editor_debugger.h
+++ b/editor/script_editor_debugger.h
@@ -230,6 +230,8 @@ public:
void set_breakpoint(const String &p_path, int p_line, bool p_enabled);
+ bool send_message(const Array &p_message);
+
void update_live_edit_root();
void set_hide_on_stop(bool p_hide);