summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/os/dir_access.cpp97
-rw-r--r--core/os/dir_access.h4
-rw-r--r--core/os/os.cpp27
-rw-r--r--core/script_debugger_remote.cpp157
-rw-r--r--core/script_language.h7
-rw-r--r--core/ustring.cpp11
-rw-r--r--core/ustring.h2
7 files changed, 254 insertions, 51 deletions
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index 35e4443f2a..6d4b46f4da 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -98,6 +98,7 @@ static Error _erase_recursive(DirAccess *da) {
err = _erase_recursive(da);
if (err) {
print_line("err recurso " + E->get());
+ da->change_dir("..");
return err;
}
err = da->change_dir("..");
@@ -340,6 +341,102 @@ Error DirAccess::copy(String p_from, String p_to, int chmod_flags) {
return err;
}
+// Changes dir for the current scope, returning back to the original dir
+// when scope exits
+class DirChanger {
+ DirAccess *da;
+ String original_dir;
+
+public:
+ DirChanger(DirAccess *p_da, String p_dir) {
+ da = p_da;
+ original_dir = p_da->get_current_dir();
+ p_da->change_dir(p_dir);
+ }
+
+ ~DirChanger() {
+ da->change_dir(original_dir);
+ }
+};
+
+Error DirAccess::_copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags) {
+ List<String> dirs;
+
+ String curdir = get_current_dir();
+ list_dir_begin();
+ String n = get_next();
+ while (n != String()) {
+
+ if (n != "." && n != "..") {
+
+ if (current_is_dir())
+ dirs.push_back(n);
+ else {
+ String rel_path = n;
+ if (!n.is_rel_path()) {
+ list_dir_end();
+ return ERR_BUG;
+ }
+ Error err = copy(get_current_dir() + "/" + n, p_to + rel_path, p_chmod_flags);
+ if (err) {
+ list_dir_end();
+ return err;
+ }
+ }
+ }
+
+ n = get_next();
+ }
+
+ list_dir_end();
+
+ for (List<String>::Element *E = dirs.front(); E; E = E->next()) {
+ String rel_path = E->get();
+ String target_dir = p_to + rel_path;
+ if (!p_target_da->dir_exists(target_dir)) {
+ Error err = p_target_da->make_dir(target_dir);
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ Error err = change_dir(E->get());
+ ERR_FAIL_COND_V(err, err);
+ err = _copy_dir(p_target_da, p_to + rel_path + "/", p_chmod_flags);
+ if (err) {
+ change_dir("..");
+ ERR_PRINT("Failed to copy recursively");
+ return err;
+ }
+ err = change_dir("..");
+ if (err) {
+ ERR_PRINT("Failed to go back");
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+Error DirAccess::copy_dir(String p_from, String p_to, int p_chmod_flags) {
+ ERR_FAIL_COND_V(!dir_exists(p_from), ERR_FILE_NOT_FOUND);
+
+ DirAccess *target_da = DirAccess::create_for_path(p_to);
+ ERR_FAIL_COND_V(!target_da, ERR_CANT_CREATE);
+
+ if (!target_da->dir_exists(p_to)) {
+ Error err = target_da->make_dir_recursive(p_to);
+ if (err) {
+ memdelete(target_da);
+ }
+ ERR_FAIL_COND_V(err, err);
+ }
+
+ DirChanger dir_changer(this, p_from);
+ Error err = _copy_dir(target_da, p_to + "/", p_chmod_flags);
+ memdelete(target_da);
+
+ return err;
+}
+
bool DirAccess::exists(String p_dir) {
DirAccess *da = DirAccess::create_for_path(p_dir);
diff --git a/core/os/dir_access.h b/core/os/dir_access.h
index 7fa3ce5cf1..f3d1320041 100644
--- a/core/os/dir_access.h
+++ b/core/os/dir_access.h
@@ -52,6 +52,9 @@ public:
private:
AccessType _access_type;
static CreateFunc create_func[ACCESS_MAX]; ///< set this to instance a filesystem object
+
+ Error _copy_dir(DirAccess *p_target_da, String p_to, int p_chmod_flags);
+
protected:
String _get_root_path() const;
String _get_root_string() const;
@@ -89,6 +92,7 @@ public:
static bool exists(String p_dir);
virtual size_t get_space_left() = 0;
+ Error copy_dir(String p_from, String p_to, int chmod_flags = -1);
virtual Error copy(String p_from, String p_to, int chmod_flags = -1);
virtual Error rename(String p_from, String p_to) = 0;
virtual Error remove(String p_name) = 0;
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 65d0b2e05d..dd71f8a9c6 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -548,6 +548,33 @@ bool OS::has_feature(const String &p_feature) {
if (sizeof(void *) == 4 && p_feature == "32") {
return true;
}
+#if defined(__x86_64) || defined(__x86_64__)
+ if (p_feature == "x86_64") {
+ return true;
+ }
+#elif (defined(__i386) || defined(__i386__))
+ if (p_feature == "x86") {
+ return true;
+ }
+#elif defined(__aarch64__)
+ if (p_feature == "arm64") {
+ return true;
+ }
+#elif defined(__arm__)
+#if defined(__ARM_ARCH_7A__)
+ if (p_feature == "armv7a" || p_feature == "armv7") {
+ return true;
+ }
+#endif
+#if defined(__ARM_ARCH_7S__)
+ if (p_feature == "armv7s" || p_feature == "armv7") {
+ return true;
+ }
+#endif
+ if (p_feature == "arm") {
+ return true;
+ }
+#endif
if (_check_internal_feature_support(p_feature))
return true;
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 5655a4d5e4..5e06339b9e 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -35,6 +35,8 @@
#include "os/input.h"
#include "os/os.h"
#include "project_settings.h"
+#include "scene/main/node.h"
+
void ScriptDebuggerRemote::_send_video_memory() {
List<ResourceUsage> usage;
@@ -201,20 +203,39 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue)
List<String> members;
List<Variant> member_vals;
-
+ if (ScriptInstance *inst = p_script->debug_get_stack_level_instance(lv)) {
+ members.push_back("self");
+ member_vals.push_back(inst->get_owner());
+ }
p_script->debug_get_stack_level_members(lv, &members, &member_vals);
-
ERR_CONTINUE(members.size() != member_vals.size());
List<String> locals;
List<Variant> local_vals;
-
p_script->debug_get_stack_level_locals(lv, &locals, &local_vals);
-
ERR_CONTINUE(locals.size() != local_vals.size());
+ List<String> globals;
+ List<Variant> globals_vals;
+ p_script->debug_get_globals(&globals, &globals_vals);
+ ERR_CONTINUE(globals.size() != globals_vals.size());
+
packet_peer_stream->put_var("stack_frame_vars");
- packet_peer_stream->put_var(2 + locals.size() * 2 + members.size() * 2);
+ packet_peer_stream->put_var(3 + (locals.size() + members.size() + globals.size()) * 2);
+
+ { //locals
+ packet_peer_stream->put_var(locals.size());
+
+ List<String>::Element *E = locals.front();
+ List<Variant>::Element *F = local_vals.front();
+
+ while (E) {
+ _put_variable(E->get(), F->get());
+
+ E = E->next();
+ F = F->next();
+ }
+ }
{ //members
packet_peer_stream->put_var(members.size());
@@ -231,11 +252,11 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script, bool p_can_continue)
}
}
- { //locals
- packet_peer_stream->put_var(locals.size());
+ { //globals
+ packet_peer_stream->put_var(globals.size());
- List<String>::Element *E = locals.front();
- List<Variant>::Element *F = local_vals.front();
+ List<String>::Element *E = globals.front();
+ List<Variant>::Element *F = globals_vals.front();
while (E) {
_put_variable(E->get(), F->get());
@@ -532,56 +553,88 @@ void ScriptDebuggerRemote::_send_object_id(ObjectID p_id) {
if (!obj)
return;
- List<PropertyInfo> pinfo;
- obj->get_property_list(&pinfo, true);
+ typedef Pair<PropertyInfo, Variant> PropertyDesc;
+ List<PropertyDesc> properties;
- int props_to_send = 0;
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
+ if (ScriptInstance *si = obj->get_script_instance()) {
+ if (!si->get_script().is_null()) {
- if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) {
- props_to_send++;
- }
- }
+ Set<StringName> members;
+ si->get_script()->get_members(&members);
+ for (Set<StringName>::Element *E = members.front(); E; E = E->next()) {
- packet_peer_stream->put_var("message:inspect_object");
- packet_peer_stream->put_var(props_to_send * 5 + 4);
- packet_peer_stream->put_var(p_id);
- packet_peer_stream->put_var(obj->get_class());
- if (obj->is_class("Resource") || obj->is_class("Node"))
- packet_peer_stream->put_var(obj->call("get_path"));
- else
- packet_peer_stream->put_var("");
+ Variant m;
+ if (si->get(E->get(), m)) {
+ PropertyInfo pi(m.get_type(), String("Members/") + E->get());
+ properties.push_back(PropertyDesc(pi, m));
+ }
+ }
- packet_peer_stream->put_var(props_to_send);
+ Map<StringName, Variant> constants;
+ si->get_script()->get_constants(&constants);
+ for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
+ PropertyInfo pi(E->value().get_type(), (String("Constants/") + E->key()));
+ properties.push_back(PropertyDesc(pi, E->value()));
+ }
+ }
+ }
+ if (Node *node = Object::cast_to<Node>(obj)) {
+ PropertyInfo pi(Variant::NODE_PATH, String("Node/path"));
+ properties.push_front(PropertyDesc(pi, node->get_path()));
+ } else if (Resource *res = Object::cast_to<Resource>(obj)) {
+ if (Script *s = Object::cast_to<Script>(res)) {
+ Map<StringName, Variant> constants;
+ s->get_constants(&constants);
+ for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
+ PropertyInfo pi(E->value().get_type(), String("Constants/") + E->key());
+ properties.push_front(PropertyDesc(pi, E->value()));
+ }
+ }
+ }
+ List<PropertyInfo> pinfo;
+ obj->get_property_list(&pinfo, true);
for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
-
if (E->get().usage & (PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CATEGORY)) {
+ properties.push_back(PropertyDesc(E->get(), obj->get(E->get().name)));
+ }
+ }
- if (E->get().usage & PROPERTY_USAGE_CATEGORY) {
- packet_peer_stream->put_var("*" + E->get().name);
- } else {
- packet_peer_stream->put_var(E->get().name);
- }
-
- Variant var = obj->get(E->get().name);
- packet_peer_stream->put_var(E->get().type);
- //only send information that can be sent..
-
- int len = 0; //test how big is this to encode
- encode_variant(var, NULL, len);
-
- if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
- packet_peer_stream->put_var(PROPERTY_HINT_OBJECT_TOO_BIG);
- packet_peer_stream->put_var("");
- packet_peer_stream->put_var(Variant());
- } else {
- packet_peer_stream->put_var(E->get().hint);
- packet_peer_stream->put_var(E->get().hint_string);
- packet_peer_stream->put_var(var);
- }
+ Array send_props;
+ for (int i = 0; i < properties.size(); i++) {
+ const PropertyInfo &pi = properties[i].first;
+ const Variant &var = properties[i].second;
+ RES res = var;
+
+ Array prop;
+ prop.push_back(pi.name);
+ prop.push_back(pi.type);
+
+ //only send information that can be sent..
+ int len = 0; //test how big is this to encode
+ encode_variant(var, NULL, len);
+ if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
+ prop.push_back(PROPERTY_HINT_OBJECT_TOO_BIG);
+ prop.push_back("");
+ prop.push_back(pi.usage);
+ prop.push_back(Variant());
+ } else {
+ prop.push_back(pi.hint);
+ if (res.is_null())
+ prop.push_back(pi.hint_string);
+ else
+ prop.push_back(String("RES:") + res->get_path());
+ prop.push_back(pi.usage);
+ prop.push_back(var);
}
+ send_props.push_back(prop);
}
+
+ packet_peer_stream->put_var("message:inspect_object");
+ packet_peer_stream->put_var(3);
+ packet_peer_stream->put_var(p_id);
+ packet_peer_stream->put_var(obj->get_class());
+ packet_peer_stream->put_var(send_props);
}
void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String &p_property, const Variant &p_value) {
@@ -590,7 +643,11 @@ void ScriptDebuggerRemote::_set_object_property(ObjectID p_id, const String &p_p
if (!obj)
return;
- obj->set(p_property, p_value);
+ String prop_name = p_property;
+ if (p_property.begins_with("Members/"))
+ prop_name = p_property.substr(8, p_property.length());
+
+ obj->set(prop_name, p_value);
}
void ScriptDebuggerRemote::_poll_events() {
diff --git a/core/script_language.h b/core/script_language.h
index 5da72d0492..3d01381f3b 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -120,6 +120,9 @@ public:
virtual int get_member_line(const StringName &p_member) const { return -1; }
+ virtual void get_constants(Map<StringName, Variant> *p_constants) {}
+ virtual void get_members(Set<StringName> *p_constants) {}
+
Script() {}
};
@@ -130,6 +133,7 @@ public:
virtual void get_property_list(List<PropertyInfo> *p_properties) const = 0;
virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid = NULL) const = 0;
+ virtual Object *get_owner() { return NULL; }
virtual void get_property_state(List<Pair<StringName, Variant> > &state);
virtual void get_method_list(List<MethodInfo> *p_list) const = 0;
@@ -244,7 +248,8 @@ public:
virtual String debug_get_stack_level_source(int p_level) const = 0;
virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
- virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
+ virtual ScriptInstance *debug_get_stack_level_instance(int p_level) { return NULL; }
+ virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) = 0;
virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems = -1, int p_max_depth = -1) = 0;
struct StackInfo {
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 7c3a784c5b..8d40f56386 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -862,6 +862,17 @@ Vector<int> String::split_ints_mk(const Vector<String> &p_splitters, bool p_allo
return ret;
}
+String String::join(Vector<String> parts) {
+ String ret;
+ for (int i = 0; i < parts.size(); ++i) {
+ if (i > 0) {
+ ret += *this;
+ }
+ ret += parts[i];
+ }
+ return ret;
+}
+
CharType String::char_uppercase(CharType p_char) {
return _find_upper(p_char);
diff --git a/core/ustring.h b/core/ustring.h
index 353c8e6c1d..9c24133b55 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -169,6 +169,8 @@ public:
Vector<int> split_ints(const String &p_splitter, bool p_allow_empty = true) const;
Vector<int> split_ints_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const;
+ String join(Vector<String> parts);
+
static CharType char_uppercase(CharType p_char);
static CharType char_lowercase(CharType p_char);
String to_upper() const;