summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editor/editor_export.cpp8
-rw-r--r--editor/editor_export.h10
-rw-r--r--editor/editor_node.cpp8
-rw-r--r--editor/editor_run_native.cpp14
-rw-r--r--editor/script_editor_debugger.cpp14
-rw-r--r--platform/android/export/export.cpp27
-rw-r--r--platform/javascript/export/export.cpp242
-rw-r--r--scene/resources/theme.cpp115
-rw-r--r--scene/resources/theme.h72
9 files changed, 405 insertions, 105 deletions
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index 9510092a86..7ae8a9e0ce 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -376,6 +376,12 @@ Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_pat
return OK;
}
+Ref<ImageTexture> EditorExportPlatform::get_option_icon(int p_index) const {
+ Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
+ ERR_FAIL_COND_V(theme.is_null(), Ref<ImageTexture>());
+ return theme->get_icon("Play", "EditorIcons");
+}
+
String EditorExportPlatform::find_export_template(String template_file_name, String *err) const {
String current_version = VERSION_FULL_CONFIG;
@@ -1403,7 +1409,7 @@ bool EditorExport::poll_export_platforms() {
bool changed = false;
for (int i = 0; i < export_platforms.size(); i++) {
- if (export_platforms.write[i]->poll_devices()) {
+ if (export_platforms.write[i]->poll_export()) {
changed = true;
}
}
diff --git a/editor/editor_export.h b/editor/editor_export.h
index 11dc464b5a..b0e27af629 100644
--- a/editor/editor_export.h
+++ b/editor/editor_export.h
@@ -243,10 +243,12 @@ public:
Error save_pack(const Ref<EditorExportPreset> &p_preset, const String &p_path, Vector<SharedObject> *p_so_files = NULL, bool p_embed = false, int64_t *r_embedded_start = NULL, int64_t *r_embedded_size = NULL);
Error save_zip(const Ref<EditorExportPreset> &p_preset, const String &p_path);
- virtual bool poll_devices() { return false; }
- virtual int get_device_count() const { return 0; }
- virtual String get_device_name(int p_device) const { return ""; }
- virtual String get_device_info(int p_device) const { return ""; }
+ virtual bool poll_export() { return false; }
+ virtual int get_options_count() const { return 0; }
+ virtual String get_options_tooltip() const { return ""; }
+ virtual Ref<ImageTexture> get_option_icon(int p_index) const;
+ virtual String get_option_label(int p_device) const { return ""; }
+ virtual String get_option_tooltip(int p_device) const { return ""; }
enum DebugFlags {
DEBUG_FLAG_DUMB_CLIENT = 1,
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 6e2a4810cd..ae9adc66ae 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -371,7 +371,7 @@ void EditorNode::_notification(int p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
- Ref<Theme> theme = create_editor_theme(theme_base->get_theme());
+ theme = create_editor_theme(theme_base->get_theme());
theme_base->set_theme(theme);
gui_base->set_theme(theme);
@@ -1470,7 +1470,7 @@ void EditorNode::_dialog_action(String p_file) {
config.instance();
Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config());
- if (err == ERR_CANT_OPEN) {
+ if (err == ERR_FILE_CANT_OPEN || err == ERR_FILE_NOT_FOUND) {
config.instance(); // new config
} else if (err != OK) {
show_warning(TTR("Error trying to save layout!"));
@@ -5640,6 +5640,9 @@ EditorNode::EditorNode() {
editor_export = memnew(EditorExport);
add_child(editor_export);
+ // Exporters might need the theme
+ theme = create_custom_theme();
+
register_exporters();
GLOBAL_DEF("editor/main_run_args", "");
@@ -5681,7 +5684,6 @@ EditorNode::EditorNode() {
theme_base->add_child(gui_base);
gui_base->set_anchors_and_margins_preset(Control::PRESET_WIDE);
- Ref<Theme> theme = create_custom_theme();
theme_base->set_theme(theme);
gui_base->set_theme(theme);
gui_base->add_style_override("panel", gui_base->get_stylebox("Background", "EditorStyles"));
diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp
index 585ea0ec69..64e90f2488 100644
--- a/editor/editor_run_native.cpp
+++ b/editor/editor_run_native.cpp
@@ -75,20 +75,18 @@ void EditorRunNative::_notification(int p_what) {
Ref<EditorExportPlatform> eep = EditorExport::get_singleton()->get_export_platform(E->key());
MenuButton *mb = E->get();
- int dc = eep->get_device_count();
+ int dc = eep->get_options_count();
if (dc == 0) {
mb->hide();
} else {
mb->get_popup()->clear();
mb->show();
- if (dc == 1) {
- mb->set_tooltip(eep->get_device_name(0) + "\n\n" + eep->get_device_info(0).strip_edges());
- } else {
- mb->set_tooltip("Select device from the list");
+ mb->set_tooltip(eep->get_options_tooltip());
+ if (dc > 1) {
for (int i = 0; i < dc; i++) {
- mb->get_popup()->add_icon_item(get_icon("Play", "EditorIcons"), eep->get_device_name(i));
- mb->get_popup()->set_item_tooltip(mb->get_popup()->get_item_count() - 1, eep->get_device_info(i).strip_edges());
+ mb->get_popup()->add_icon_item(eep->get_option_icon(i), eep->get_option_label(i));
+ mb->get_popup()->set_item_tooltip(mb->get_popup()->get_item_count() - 1, eep->get_option_tooltip(i));
}
}
}
@@ -111,7 +109,7 @@ void EditorRunNative::_run_native(int p_idx, int p_platform) {
ERR_FAIL_COND(eep.is_null());
if (p_idx == -1) {
- if (eep->get_device_count() == 1) {
+ if (eep->get_options_count() == 1) {
menus[p_platform]->get_popup()->hide();
p_idx = 0;
} else {
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index 89d275a90b..ccee38422c 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -597,7 +597,19 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
if (var.is_zero()) {
var = RES();
} else if (var.get_type() == Variant::STRING) {
- var = ResourceLoader::load(var);
+ String path = var;
+ if (path.find("::") != -1) {
+ // built-in resource
+ String base_path = path.get_slice("::", 0);
+ if (ResourceLoader::get_resource_type(base_path) == "PackedScene") {
+ if (!EditorNode::get_singleton()->is_scene_open(base_path)) {
+ EditorNode::get_singleton()->load_scene(base_path);
+ }
+ } else {
+ EditorNode::get_singleton()->load_resource(base_path);
+ }
+ }
+ var = ResourceLoader::load(path);
if (pinfo.hint_string == "Script")
debugObj->set_script(var);
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index a43f195b84..6d021ad33a 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -1345,7 +1345,7 @@ public:
return logo;
}
- virtual bool poll_devices() {
+ virtual bool poll_export() {
bool dc = devices_changed;
if (dc) {
@@ -1355,7 +1355,7 @@ public:
return dc;
}
- virtual int get_device_count() const {
+ virtual int get_options_count() const {
device_lock->lock();
int dc = devices.size();
@@ -1364,20 +1364,31 @@ public:
return dc;
}
- virtual String get_device_name(int p_device) const {
+ virtual String get_options_tooltip() const {
- ERR_FAIL_INDEX_V(p_device, devices.size(), "");
+ return TTR("Select device from the list");
+ }
+
+ virtual String get_option_label(int p_index) const {
+
+ ERR_FAIL_INDEX_V(p_index, devices.size(), "");
device_lock->lock();
- String s = devices[p_device].name;
+ String s = devices[p_index].name;
device_lock->unlock();
return s;
}
- virtual String get_device_info(int p_device) const {
+ virtual String get_option_tooltip(int p_index) const {
- ERR_FAIL_INDEX_V(p_device, devices.size(), "");
+ ERR_FAIL_INDEX_V(p_index, devices.size(), "");
device_lock->lock();
- String s = devices[p_device].description;
+ String s = devices[p_index].description;
+ if (devices.size() == 1) {
+ // Tooltip will be:
+ // Name
+ // Description
+ s = devices[p_index].name + "\n\n" + s;
+ }
device_lock->unlock();
return s;
}
diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp
index 4de98f7039..f3e8d6911a 100644
--- a/platform/javascript/export/export.cpp
+++ b/platform/javascript/export/export.cpp
@@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#include "core/io/tcp_server.h"
#include "core/io/zip_io.h"
#include "editor/editor_export.h"
#include "editor/editor_node.h"
@@ -38,16 +39,153 @@
#define EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE "webassembly_release.zip"
#define EXPORT_TEMPLATE_WEBASSEMBLY_DEBUG "webassembly_debug.zip"
+class EditorHTTPServer : public Reference {
+
+private:
+ Ref<TCP_Server> server;
+ Ref<StreamPeerTCP> connection;
+ uint64_t time;
+ uint8_t req_buf[4096];
+ int req_pos;
+
+ void _clear_client() {
+ connection = Ref<StreamPeerTCP>();
+ memset(req_buf, 0, sizeof(req_buf));
+ time = 0;
+ req_pos = 0;
+ }
+
+public:
+ EditorHTTPServer() {
+ server.instance();
+ stop();
+ }
+
+ void stop() {
+ server->stop();
+ _clear_client();
+ }
+
+ Error listen(int p_port, IP_Address p_address) {
+ return server->listen(p_port, p_address);
+ }
+
+ bool is_listening() const {
+ return server->is_listening();
+ }
+
+ void _send_response() {
+ Vector<String> psa = String((char *)req_buf).split("\r\n");
+ int len = psa.size();
+ ERR_FAIL_COND_MSG(len < 4, "Not enough response headers, got: " + itos(len) + ", expected >= 4.");
+
+ Vector<String> req = psa[0].split(" ", false);
+ ERR_FAIL_COND_MSG(req.size() < 2, "Invalid protocol or status code.");
+
+ // Wrong protocol
+ ERR_FAIL_COND_MSG(req[0] != "GET" || req[2] != "HTTP/1.1", "Invalid method or HTTP version.");
+
+ String filepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_js_export");
+ String basereq = "/tmp_js_export";
+ if (req[1] == basereq + ".html") {
+ filepath += ".html";
+ } else if (req[1] == basereq + ".js") {
+ filepath += ".js";
+ } else if (req[1] == basereq + ".pck") {
+ filepath += ".pck";
+ } else if (req[1] == basereq + ".png") {
+ filepath += ".png";
+ } else if (req[1] == basereq + ".wasm") {
+ filepath += ".wasm";
+ } else {
+ String s = "HTTP/1.1 404 Not Found\r\n";
+ s += "Connection: Close\r\n";
+ s += "\r\n";
+ CharString cs = s.utf8();
+ connection->put_data((const uint8_t *)cs.get_data(), cs.size() - 1);
+ return;
+ }
+ FileAccess *f = FileAccess::open(filepath, FileAccess::READ);
+ ERR_FAIL_COND(!f);
+ String s = "HTTP/1.1 200 OK\r\n";
+ s += "Connection: Close\r\n";
+ s += "\r\n";
+ CharString cs = s.utf8();
+ Error err = connection->put_data((const uint8_t *)cs.get_data(), cs.size() - 1);
+ ERR_FAIL_COND(err != OK);
+
+ while (true) {
+ uint8_t bytes[4096];
+ int read = f->get_buffer(bytes, 4096);
+ if (read < 1) {
+ break;
+ }
+ err = connection->put_data(bytes, read);
+ ERR_FAIL_COND(err != OK);
+ }
+ }
+
+ void poll() {
+ if (!server->is_listening())
+ return;
+ if (connection.is_null()) {
+ if (!server->is_connection_available())
+ return;
+ connection = server->take_connection();
+ time = OS::get_singleton()->get_ticks_usec();
+ }
+ if (OS::get_singleton()->get_ticks_usec() - time > 1000000) {
+ _clear_client();
+ return;
+ }
+ if (connection->get_status() != StreamPeerTCP::STATUS_CONNECTED)
+ return;
+
+ while (true) {
+
+ char *r = (char *)req_buf;
+ int l = req_pos - 1;
+ if (l > 3 && r[l] == '\n' && r[l - 1] == '\r' && r[l - 2] == '\n' && r[l - 3] == '\r') {
+ _send_response();
+ _clear_client();
+ return;
+ }
+
+ int read = 0;
+ ERR_FAIL_COND(req_pos >= 4096);
+ Error err = connection->get_partial_data(&req_buf[req_pos], 1, read);
+ if (err != OK) {
+ // Got an error
+ _clear_client();
+ return;
+ } else if (read != 1) {
+ // Busy, wait next poll
+ return;
+ }
+ req_pos += read;
+ }
+ }
+};
+
class EditorExportPlatformJavaScript : public EditorExportPlatform {
GDCLASS(EditorExportPlatformJavaScript, EditorExportPlatform);
Ref<ImageTexture> logo;
Ref<ImageTexture> run_icon;
- bool runnable_when_last_polled;
+ Ref<ImageTexture> stop_icon;
+ int menu_options;
void _fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug);
+private:
+ Ref<EditorHTTPServer> server;
+ bool server_quit;
+ Mutex *server_lock;
+ Thread *server_thread;
+
+ static void _server_thread_poll(void *data);
+
public:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features);
@@ -61,11 +199,12 @@ public:
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const;
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
- virtual bool poll_devices();
- virtual int get_device_count() const;
- virtual String get_device_name(int p_device) const { return TTR("Run in Browser"); }
- virtual String get_device_info(int p_device) const { return TTR("Run exported HTML in the system's default browser."); }
- virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags);
+ virtual bool poll_export();
+ virtual int get_options_count() const;
+ virtual String get_option_label(int p_index) const { return p_index ? TTR("Stop HTTP Server") : TTR("Run in Browser"); }
+ virtual String get_option_tooltip(int p_index) const { return p_index ? TTR("Stop HTTP Server") : TTR("Run exported HTML in the system's default browser."); }
+ virtual Ref<ImageTexture> get_option_icon(int p_index) const;
+ virtual Error run(const Ref<EditorExportPreset> &p_preset, int p_option, int p_debug_flags);
virtual Ref<Texture> get_run_icon() const;
virtual void get_platform_features(List<String> *r_features) {
@@ -78,6 +217,7 @@ public:
}
EditorExportPlatformJavaScript();
+ ~EditorExportPlatformJavaScript();
};
void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug) {
@@ -337,7 +477,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
return OK;
}
-bool EditorExportPlatformJavaScript::poll_devices() {
+bool EditorExportPlatformJavaScript::poll_export() {
Ref<EditorExportPreset> preset;
@@ -350,17 +490,37 @@ bool EditorExportPlatformJavaScript::poll_devices() {
}
}
- bool prev = runnable_when_last_polled;
- runnable_when_last_polled = preset.is_valid();
- return runnable_when_last_polled != prev;
+ int prev = menu_options;
+ menu_options = preset.is_valid();
+ if (server->is_listening()) {
+ if (menu_options == 0) {
+ server_lock->lock();
+ server->stop();
+ server_lock->unlock();
+ } else {
+ menu_options += 1;
+ }
+ }
+ return menu_options != prev;
+}
+
+Ref<ImageTexture> EditorExportPlatformJavaScript::get_option_icon(int p_index) const {
+ return p_index == 1 ? stop_icon : EditorExportPlatform::get_option_icon(p_index);
}
-int EditorExportPlatformJavaScript::get_device_count() const {
+int EditorExportPlatformJavaScript::get_options_count() const {
- return runnable_when_last_polled;
+ return menu_options;
}
-Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_preset, int p_device, int p_debug_flags) {
+Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_preset, int p_option, int p_debug_flags) {
+
+ if (p_option == 1) {
+ server_lock->lock();
+ server->stop();
+ server_lock->unlock();
+ return OK;
+ }
String basepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_js_export");
String path = basepath + ".html";
@@ -374,7 +534,26 @@ Error EditorExportPlatformJavaScript::run(const Ref<EditorExportPreset> &p_prese
DirAccess::remove_file_or_error(basepath + ".wasm");
return err;
}
- OS::get_singleton()->shell_open(String("file://") + path);
+
+ IP_Address bind_ip;
+ uint16_t bind_port = EDITOR_GET("export/web/http_port");
+ // Resolve host if needed.
+ String bind_host = EDITOR_GET("export/web/http_host");
+ if (bind_host.is_valid_ip_address()) {
+ bind_ip = bind_host;
+ } else {
+ bind_ip = IP::get_singleton()->resolve_hostname(bind_host);
+ }
+ ERR_FAIL_COND_V_MSG(!bind_ip.is_valid(), ERR_INVALID_PARAMETER, "Invalid editor setting 'export/web/http_host': '" + bind_host + "'. Try using '127.0.0.1'.");
+
+ // Restart server.
+ server_lock->lock();
+ server->stop();
+ err = server->listen(bind_port, bind_ip);
+ server_lock->unlock();
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Unable to start HTTP server.");
+
+ OS::get_singleton()->shell_open(String("http://" + bind_host + ":" + itos(bind_port) + "/tmp_js_export.html"));
// FIXME: Find out how to clean up export files after running the successfully
// exported game. Might not be trivial.
return OK;
@@ -385,8 +564,23 @@ Ref<Texture> EditorExportPlatformJavaScript::get_run_icon() const {
return run_icon;
}
+void EditorExportPlatformJavaScript::_server_thread_poll(void *data) {
+ EditorExportPlatformJavaScript *ej = (EditorExportPlatformJavaScript *)data;
+ while (!ej->server_quit) {
+ OS::get_singleton()->delay_usec(1000);
+ ej->server_lock->lock();
+ ej->server->poll();
+ ej->server_lock->unlock();
+ }
+}
+
EditorExportPlatformJavaScript::EditorExportPlatformJavaScript() {
+ server.instance();
+ server_quit = false;
+ server_lock = Mutex::create();
+ server_thread = Thread::create(_server_thread_poll, this);
+
Ref<Image> img = memnew(Image(_javascript_logo));
logo.instance();
logo->create_from_image(img);
@@ -395,11 +589,29 @@ EditorExportPlatformJavaScript::EditorExportPlatformJavaScript() {
run_icon.instance();
run_icon->create_from_image(img);
- runnable_when_last_polled = false;
+ Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
+ if (theme.is_valid())
+ stop_icon = theme->get_icon("Stop", "EditorIcons");
+ else
+ stop_icon.instance();
+
+ menu_options = 0;
+}
+
+EditorExportPlatformJavaScript::~EditorExportPlatformJavaScript() {
+ server->stop();
+ server_quit = true;
+ Thread::wait_to_finish(server_thread);
+ memdelete(server_lock);
+ memdelete(server_thread);
}
void register_javascript_exporter() {
+ EDITOR_DEF("export/web/http_host", "localhost");
+ EDITOR_DEF("export/web/http_port", 8060);
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::INT, "export/web/http_port", PROPERTY_HINT_RANGE, "1,65535,1"));
+
Ref<EditorExportPlatformJavaScript> platform;
platform.instance();
EditorExport::get_singleton()->add_export_platform(platform);
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index ae18be1695..f1429a7d7b 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -37,6 +37,97 @@ void Theme::_emit_theme_changed() {
emit_changed();
}
+PoolVector<String> Theme::_get_icon_list(const String &p_type) const {
+
+ PoolVector<String> ilret;
+ List<StringName> il;
+
+ get_icon_list(p_type, &il);
+ ilret.resize(il.size());
+ for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
+ ilret.push_back(E->get());
+ }
+ return ilret;
+}
+
+PoolVector<String> Theme::_get_stylebox_list(const String &p_type) const {
+
+ PoolVector<String> ilret;
+ List<StringName> il;
+
+ get_stylebox_list(p_type, &il);
+ ilret.resize(il.size());
+ for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
+ ilret.push_back(E->get());
+ }
+ return ilret;
+}
+
+PoolVector<String> Theme::_get_stylebox_types(void) const {
+
+ PoolVector<String> ilret;
+ List<StringName> il;
+
+ get_stylebox_types(&il);
+ ilret.resize(il.size());
+ for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
+ ilret.push_back(E->get());
+ }
+ return ilret;
+}
+
+PoolVector<String> Theme::_get_font_list(const String &p_type) const {
+
+ PoolVector<String> ilret;
+ List<StringName> il;
+
+ get_font_list(p_type, &il);
+ ilret.resize(il.size());
+ for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
+ ilret.push_back(E->get());
+ }
+ return ilret;
+}
+
+PoolVector<String> Theme::_get_color_list(const String &p_type) const {
+
+ PoolVector<String> ilret;
+ List<StringName> il;
+
+ get_color_list(p_type, &il);
+ ilret.resize(il.size());
+ for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
+ ilret.push_back(E->get());
+ }
+ return ilret;
+}
+
+PoolVector<String> Theme::_get_constant_list(const String &p_type) const {
+
+ PoolVector<String> ilret;
+ List<StringName> il;
+
+ get_constant_list(p_type, &il);
+ ilret.resize(il.size());
+ for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
+ ilret.push_back(E->get());
+ }
+ return ilret;
+}
+
+PoolVector<String> Theme::_get_type_list(const String &p_type) const {
+
+ PoolVector<String> ilret;
+ List<StringName> il;
+
+ get_type_list(&il);
+ ilret.resize(il.size());
+ for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
+ ilret.push_back(E->get());
+ }
+ return ilret;
+}
+
bool Theme::_set(const StringName &p_name, const Variant &p_value) {
String sname = p_name;
@@ -300,6 +391,8 @@ void Theme::clear_icon(const StringName &p_name, const StringName &p_type) {
void Theme::get_icon_list(StringName p_type, List<StringName> *p_list) const {
+ ERR_FAIL_NULL(p_list);
+
if (!icon_map.has(p_type))
return;
@@ -344,6 +437,9 @@ void Theme::clear_shader(const StringName &p_name, const StringName &p_type) {
}
void Theme::get_shader_list(const StringName &p_type, List<StringName> *p_list) const {
+
+ ERR_FAIL_NULL(p_list);
+
if (!shader_map.has(p_type))
return;
@@ -408,6 +504,8 @@ void Theme::clear_stylebox(const StringName &p_name, const StringName &p_type) {
void Theme::get_stylebox_list(StringName p_type, List<StringName> *p_list) const {
+ ERR_FAIL_NULL(p_list);
+
if (!style_map.has(p_type))
return;
@@ -420,6 +518,8 @@ void Theme::get_stylebox_list(StringName p_type, List<StringName> *p_list) const
}
void Theme::get_stylebox_types(List<StringName> *p_list) const {
+ ERR_FAIL_NULL(p_list);
+
const StringName *key = NULL;
while ((key = style_map.next(key))) {
p_list->push_back(*key);
@@ -478,6 +578,8 @@ void Theme::clear_font(const StringName &p_name, const StringName &p_type) {
void Theme::get_font_list(StringName p_type, List<StringName> *p_list) const {
+ ERR_FAIL_NULL(p_list);
+
if (!font_map.has(p_type))
return;
@@ -526,6 +628,8 @@ void Theme::clear_color(const StringName &p_name, const StringName &p_type) {
void Theme::get_color_list(StringName p_type, List<StringName> *p_list) const {
+ ERR_FAIL_NULL(p_list);
+
if (!color_map.has(p_type))
return;
@@ -574,6 +678,8 @@ void Theme::clear_constant(const StringName &p_name, const StringName &p_type) {
void Theme::get_constant_list(StringName p_type, List<StringName> *p_list) const {
+ ERR_FAIL_NULL(p_list);
+
if (!constant_map.has(p_type))
return;
@@ -637,6 +743,12 @@ void Theme::copy_default_theme() {
void Theme::copy_theme(const Ref<Theme> &p_other) {
+ if (p_other.is_null()) {
+ clear();
+
+ return;
+ }
+
//these need reconnecting, so add normally
{
const StringName *K = NULL;
@@ -680,8 +792,9 @@ void Theme::copy_theme(const Ref<Theme> &p_other) {
void Theme::get_type_list(List<StringName> *p_list) const {
- Set<StringName> types;
+ ERR_FAIL_NULL(p_list);
+ Set<StringName> types;
const StringName *key = NULL;
while ((key = icon_map.next(key))) {
diff --git a/scene/resources/theme.h b/scene/resources/theme.h
index 187694de65..471e5b1a51 100644
--- a/scene/resources/theme.h
+++ b/scene/resources/theme.h
@@ -52,6 +52,14 @@ class Theme : public Resource {
HashMap<StringName, HashMap<StringName, Color> > color_map;
HashMap<StringName, HashMap<StringName, int> > constant_map;
+ PoolVector<String> _get_icon_list(const String &p_type) const;
+ PoolVector<String> _get_stylebox_list(const String &p_type) const;
+ PoolVector<String> _get_stylebox_types(void) const;
+ PoolVector<String> _get_font_list(const String &p_type) const;
+ PoolVector<String> _get_color_list(const String &p_type) const;
+ PoolVector<String> _get_constant_list(const String &p_type) const;
+ PoolVector<String> _get_type_list(const String &p_type) const;
+
protected:
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
@@ -65,70 +73,6 @@ protected:
Ref<Font> default_theme_font;
- PoolVector<String> _get_icon_list(const String &p_type) const {
- PoolVector<String> ilret;
- List<StringName> il;
- get_icon_list(p_type, &il);
- for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
- ilret.push_back(E->get());
- }
- return ilret;
- }
- PoolVector<String> _get_stylebox_list(const String &p_type) const {
- PoolVector<String> ilret;
- List<StringName> il;
- get_stylebox_list(p_type, &il);
- for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
- ilret.push_back(E->get());
- }
- return ilret;
- }
- PoolVector<String> _get_stylebox_types(void) const {
- PoolVector<String> ilret;
- List<StringName> il;
- get_stylebox_types(&il);
- for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
- ilret.push_back(E->get());
- }
- return ilret;
- }
- PoolVector<String> _get_font_list(const String &p_type) const {
- PoolVector<String> ilret;
- List<StringName> il;
- get_font_list(p_type, &il);
- for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
- ilret.push_back(E->get());
- }
- return ilret;
- }
- PoolVector<String> _get_color_list(const String &p_type) const {
- PoolVector<String> ilret;
- List<StringName> il;
- get_color_list(p_type, &il);
- for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
- ilret.push_back(E->get());
- }
- return ilret;
- }
- PoolVector<String> _get_constant_list(const String &p_type) const {
- PoolVector<String> ilret;
- List<StringName> il;
- get_constant_list(p_type, &il);
- for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
- ilret.push_back(E->get());
- }
- return ilret;
- }
- PoolVector<String> _get_type_list(const String &p_type) const {
- PoolVector<String> ilret;
- List<StringName> il;
- get_type_list(&il);
- for (List<StringName>::Element *E = il.front(); E; E = E->next()) {
- ilret.push_back(E->get());
- }
- return ilret;
- }
-
static void _bind_methods();
public: