diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/io/pck_packer.cpp | 2 | ||||
-rw-r--r-- | core/io/translation_loader_po.cpp | 27 | ||||
-rw-r--r-- | core/io/translation_loader_po.h | 2 | ||||
-rw-r--r-- | core/math/a_star.cpp | 195 | ||||
-rw-r--r-- | core/math/a_star.h | 10 | ||||
-rw-r--r-- | core/translation.cpp | 17 | ||||
-rw-r--r-- | core/translation.h | 3 | ||||
-rw-r--r-- | core/ustring.cpp | 11 | ||||
-rw-r--r-- | core/ustring.h | 16 |
9 files changed, 245 insertions, 38 deletions
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index fb83f0ac90..11e537c10b 100644 --- a/core/io/pck_packer.cpp +++ b/core/io/pck_packer.cpp @@ -163,7 +163,7 @@ Error PCKPacker::flush(bool p_verbose) { src->close(); memdelete(src); count += 1; - if (p_verbose) { + if (p_verbose && files.size() > 0) { if (count % 100 == 0) { printf("%i/%i (%.2f)\r", count, files.size(), float(count) / files.size() * 100); fflush(stdout); diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp index 4051bf2947..5da236d029 100644 --- a/core/io/translation_loader_po.cpp +++ b/core/io/translation_loader_po.cpp @@ -33,7 +33,7 @@ #include "core/os/file_access.h" #include "core/translation.h" -RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const String &p_path) { +RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) { enum Status { @@ -67,7 +67,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S if (status == STATUS_READING_ID) { memdelete(f); - ERR_FAIL_V_MSG(RES(), p_path + ":" + itos(line) + " Unexpected EOF while reading 'msgid' at file: "); + ERR_FAIL_V_MSG(RES(), f->get_path() + ":" + itos(line) + " Unexpected EOF while reading 'msgid' at file: "); } else { break; } @@ -78,7 +78,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S if (status == STATUS_READING_ID) { memdelete(f); - ERR_FAIL_V_MSG(RES(), p_path + ":" + itos(line) + " Unexpected 'msgid', was expecting 'msgstr' while parsing: "); + ERR_FAIL_V_MSG(RES(), f->get_path() + ":" + itos(line) + " Unexpected 'msgid', was expecting 'msgstr' while parsing: "); } if (msg_id != "") { @@ -100,7 +100,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S if (status != STATUS_READING_ID) { memdelete(f); - ERR_FAIL_V_MSG(RES(), p_path + ":" + itos(line) + " Unexpected 'msgstr', was expecting 'msgid' while parsing: "); + ERR_FAIL_V_MSG(RES(), f->get_path() + ":" + itos(line) + " Unexpected 'msgstr', was expecting 'msgid' while parsing: "); } l = l.substr(6, l.length()).strip_edges(); @@ -115,20 +115,29 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S continue; //nothing to read or comment } - ERR_FAIL_COND_V_MSG(!l.begins_with("\"") || status == STATUS_NONE, RES(), p_path + ":" + itos(line) + " Invalid line '" + l + "' while parsing: "); + ERR_FAIL_COND_V_MSG(!l.begins_with("\"") || status == STATUS_NONE, RES(), f->get_path() + ":" + itos(line) + " Invalid line '" + l + "' while parsing: "); l = l.substr(1, l.length()); - //find final quote + // Find final quote, ignoring escaped ones (\"). + // The escape_next logic is necessary to properly parse things like \\" + // where the blackslash is the one being escaped, not the quote. int end_pos = -1; + bool escape_next = false; for (int i = 0; i < l.length(); i++) { + if (l[i] == '\\' && !escape_next) { + escape_next = true; + continue; + } - if (l[i] == '"' && (i == 0 || l[i - 1] != '\\')) { + if (l[i] == '"' && !escape_next) { end_pos = i; break; } + + escape_next = false; } - ERR_FAIL_COND_V_MSG(end_pos == -1, RES(), p_path + ":" + itos(line) + " Expected '\"' at end of message while parsing file: "); + ERR_FAIL_COND_V_MSG(end_pos == -1, RES(), f->get_path() + ":" + itos(line) + ": Expected '\"' at end of message while parsing file."); l = l.substr(0, end_pos); l = l.c_unescape(); @@ -153,7 +162,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const S config = msg_str; } - ERR_FAIL_COND_V_MSG(config == "", RES(), "No config found in file: " + p_path + "."); + ERR_FAIL_COND_V_MSG(config == "", RES(), "No config found in file: " + f->get_path() + "."); Vector<String> configs = config.split("\n"); for (int i = 0; i < configs.size(); i++) { diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h index fe3a75e5eb..d280729e94 100644 --- a/core/io/translation_loader_po.h +++ b/core/io/translation_loader_po.h @@ -37,7 +37,7 @@ class TranslationLoaderPO : public ResourceFormatLoader { public: - static RES load_translation(FileAccess *f, Error *r_error, const String &p_path = String()); + static RES load_translation(FileAccess *f, Error *r_error = NULL); virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL, bool p_use_sub_threads = false, float *r_progress = nullptr); virtual void get_recognized_extensions(List<String> *p_extensions) const; virtual bool handles_type(const String &p_type) const; diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index 847d4d8681..bfff12ac45 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -399,7 +399,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { return found_route; } -float AStar::_estimate_cost(int p_from_id, int p_to_id) { +real_t AStar::_estimate_cost(int p_from_id, int p_to_id) { if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_estimate_cost)) return get_script_instance()->call(SceneStringNames::get_singleton()->_estimate_cost, p_from_id, p_to_id); @@ -415,7 +415,7 @@ float AStar::_estimate_cost(int p_from_id, int p_to_id) { return from_point->pos.distance_to(to_point->pos); } -float AStar::_compute_cost(int p_from_id, int p_to_id) { +real_t AStar::_compute_cost(int p_from_id, int p_to_id) { if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_compute_cost)) return get_script_instance()->call(SceneStringNames::get_singleton()->_compute_cost, p_from_id, p_to_id); @@ -677,25 +677,195 @@ Vector2 AStar2D::get_closest_position_in_segment(const Vector2 &p_point) const { return Vector2(p.x, p.y); } +real_t AStar2D::_estimate_cost(int p_from_id, int p_to_id) { + + if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_estimate_cost)) + return get_script_instance()->call(SceneStringNames::get_singleton()->_estimate_cost, p_from_id, p_to_id); + + AStar::Point *from_point; + bool from_exists = astar.points.lookup(p_from_id, from_point); + ERR_FAIL_COND_V(!from_exists, 0); + + AStar::Point *to_point; + bool to_exists = astar.points.lookup(p_to_id, to_point); + ERR_FAIL_COND_V(!to_exists, 0); + + return from_point->pos.distance_to(to_point->pos); +} + +real_t AStar2D::_compute_cost(int p_from_id, int p_to_id) { + + if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_compute_cost)) + return get_script_instance()->call(SceneStringNames::get_singleton()->_compute_cost, p_from_id, p_to_id); + + AStar::Point *from_point; + bool from_exists = astar.points.lookup(p_from_id, from_point); + ERR_FAIL_COND_V(!from_exists, 0); + + AStar::Point *to_point; + bool to_exists = astar.points.lookup(p_to_id, to_point); + ERR_FAIL_COND_V(!to_exists, 0); + + return from_point->pos.distance_to(to_point->pos); +} + Vector<Vector2> AStar2D::get_point_path(int p_from_id, int p_to_id) { - PackedVector3Array pv = astar.get_point_path(p_from_id, p_to_id); - int size = pv.size(); - PackedVector2Array path; - path.resize(size); + AStar::Point *a; + bool from_exists = astar.points.lookup(p_from_id, a); + ERR_FAIL_COND_V(!from_exists, Vector<Vector2>()); + + AStar::Point *b; + bool to_exists = astar.points.lookup(p_to_id, b); + ERR_FAIL_COND_V(!to_exists, Vector<Vector2>()); + + if (a == b) { + Vector<Vector2> ret; + ret.push_back(Vector2(a->pos.x, a->pos.y)); + return ret; + } + + AStar::Point *begin_point = a; + AStar::Point *end_point = b; + + bool found_route = _solve(begin_point, end_point); + if (!found_route) return Vector<Vector2>(); + + AStar::Point *p = end_point; + int pc = 1; // Begin point + while (p != begin_point) { + pc++; + p = p->prev_point; + } + + Vector<Vector2> path; + path.resize(pc); + { - const Vector3 *r = pv.ptr(); Vector2 *w = path.ptrw(); - for (int i = 0; i < size; i++) { - Vector3 p = r[i]; - w[i] = Vector2(p.x, p.y); + + AStar::Point *p2 = end_point; + int idx = pc - 1; + while (p2 != begin_point) { + w[idx--] = Vector2(p2->pos.x, p2->pos.y); + p2 = p2->prev_point; } + + w[0] = Vector2(p2->pos.x, p2->pos.y); // Assign first } + return path; } Vector<int> AStar2D::get_id_path(int p_from_id, int p_to_id) { - return astar.get_id_path(p_from_id, p_to_id); + + AStar::Point *a; + bool from_exists = astar.points.lookup(p_from_id, a); + ERR_FAIL_COND_V(!from_exists, Vector<int>()); + + AStar::Point *b; + bool to_exists = astar.points.lookup(p_to_id, b); + ERR_FAIL_COND_V(!to_exists, Vector<int>()); + + if (a == b) { + Vector<int> ret; + ret.push_back(a->id); + return ret; + } + + AStar::Point *begin_point = a; + AStar::Point *end_point = b; + + bool found_route = _solve(begin_point, end_point); + if (!found_route) return Vector<int>(); + + AStar::Point *p = end_point; + int pc = 1; // Begin point + while (p != begin_point) { + pc++; + p = p->prev_point; + } + + Vector<int> path; + path.resize(pc); + + { + int *w = path.ptrw(); + + p = end_point; + int idx = pc - 1; + while (p != begin_point) { + w[idx--] = p->id; + p = p->prev_point; + } + + w[0] = p->id; // Assign first + } + + return path; +} + +bool AStar2D::_solve(AStar::Point *begin_point, AStar::Point *end_point) { + + astar.pass++; + + if (!end_point->enabled) return false; + + bool found_route = false; + + Vector<AStar::Point *> open_list; + SortArray<AStar::Point *, AStar::SortPoints> sorter; + + begin_point->g_score = 0; + begin_point->f_score = _estimate_cost(begin_point->id, end_point->id); + open_list.push_back(begin_point); + + while (!open_list.empty()) { + + AStar::Point *p = open_list[0]; // The currently processed point + + if (p == end_point) { + found_route = true; + break; + } + + sorter.pop_heap(0, open_list.size(), open_list.ptrw()); // Remove the current point from the open list + open_list.remove(open_list.size() - 1); + p->closed_pass = astar.pass; // Mark the point as closed + + for (OAHashMap<int, AStar::Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) { + + AStar::Point *e = *(it.value); // The neighbour point + + if (!e->enabled || e->closed_pass == astar.pass) { + continue; + } + + real_t tentative_g_score = p->g_score + _compute_cost(p->id, e->id) * e->weight_scale; + + bool new_point = false; + + if (e->open_pass != astar.pass) { // The point wasn't inside the open list. + e->open_pass = astar.pass; + open_list.push_back(e); + new_point = true; + } else if (tentative_g_score >= e->g_score) { // The new path is worse than the previous. + continue; + } + + e->prev_point = p; + e->g_score = tentative_g_score; + e->f_score = e->g_score + _estimate_cost(e->id, end_point->id); + + if (new_point) { // The position of the new points is already known. + sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptrw()); + } else { + sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptrw()); + } + } + } + + return found_route; } void AStar2D::_bind_methods() { @@ -728,6 +898,9 @@ void AStar2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id"), &AStar2D::get_point_path); ClassDB::bind_method(D_METHOD("get_id_path", "from_id", "to_id"), &AStar2D::get_id_path); + + BIND_VMETHOD(MethodInfo(Variant::FLOAT, "_estimate_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id"))); + BIND_VMETHOD(MethodInfo(Variant::FLOAT, "_compute_cost", PropertyInfo(Variant::INT, "from_id"), PropertyInfo(Variant::INT, "to_id"))); } AStar2D::AStar2D() { diff --git a/core/math/a_star.h b/core/math/a_star.h index bfcf0c09d3..cc6c4619e9 100644 --- a/core/math/a_star.h +++ b/core/math/a_star.h @@ -43,6 +43,7 @@ class AStar : public Reference { GDCLASS(AStar, Reference); + friend class AStar2D; struct Point { @@ -124,8 +125,8 @@ class AStar : public Reference { protected: static void _bind_methods(); - virtual float _estimate_cost(int p_from_id, int p_to_id); - virtual float _compute_cost(int p_from_id, int p_to_id); + virtual real_t _estimate_cost(int p_from_id, int p_to_id); + virtual real_t _compute_cost(int p_from_id, int p_to_id); public: int get_available_point_id() const; @@ -166,9 +167,14 @@ class AStar2D : public Reference { GDCLASS(AStar2D, Reference); AStar astar; + bool _solve(AStar::Point *begin_point, AStar::Point *end_point); + protected: static void _bind_methods(); + virtual real_t _estimate_cost(int p_from_id, int p_to_id); + virtual real_t _compute_cost(int p_from_id, int p_to_id); + public: int get_available_point_id() const; diff --git a/core/translation.cpp b/core/translation.cpp index 7399fa5619..df3661e5d0 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -1176,7 +1176,6 @@ void TranslationServer::setup() { set_locale(OS::get_singleton()->get_locale()); fallback = GLOBAL_DEF("locale/fallback", "en"); #ifdef TOOLS_ENABLED - { String options = ""; int idx = 0; @@ -1189,7 +1188,6 @@ void TranslationServer::setup() { ProjectSettings::get_singleton()->set_custom_property_info("locale/fallback", PropertyInfo(Variant::STRING, "locale/fallback", PROPERTY_HINT_ENUM, options)); } #endif - //load translations } void TranslationServer::set_tool_translation(const Ref<Translation> &p_translation) { @@ -1197,15 +1195,26 @@ void TranslationServer::set_tool_translation(const Ref<Translation> &p_translati } StringName TranslationServer::tool_translate(const StringName &p_message) const { - if (tool_translation.is_valid()) { StringName r = tool_translation->get_message(p_message); - if (r) { return r; } } + return p_message; +} +void TranslationServer::set_doc_translation(const Ref<Translation> &p_translation) { + doc_translation = p_translation; +} + +StringName TranslationServer::doc_translate(const StringName &p_message) const { + if (doc_translation.is_valid()) { + StringName r = doc_translation->get_message(p_message); + if (r) { + return r; + } + } return p_message; } diff --git a/core/translation.h b/core/translation.h index b9e07fa2b1..29a068f450 100644 --- a/core/translation.h +++ b/core/translation.h @@ -73,6 +73,7 @@ class TranslationServer : public Object { Set<Ref<Translation>> translations; Ref<Translation> tool_translation; + Ref<Translation> doc_translation; Map<String, String> locale_name_map; @@ -109,6 +110,8 @@ public: void set_tool_translation(const Ref<Translation> &p_translation); StringName tool_translate(const StringName &p_message) const; + void set_doc_translation(const Ref<Translation> &p_translation); + StringName doc_translate(const StringName &p_message) const; void setup(); diff --git a/core/ustring.cpp b/core/ustring.cpp index da089dce40..8027ae29b5 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -4412,7 +4412,6 @@ String String::unquote() const { #ifdef TOOLS_ENABLED String TTR(const String &p_text) { - if (TranslationServer::get_singleton()) { return TranslationServer::get_singleton()->tool_translate(p_text); } @@ -4420,10 +4419,18 @@ String TTR(const String &p_text) { return p_text; } +String DTR(const String &p_text) { + if (TranslationServer::get_singleton()) { + // Comes straight from the XML, so remove indentation and any trailing whitespace. + const String text = p_text.dedent().strip_edges(); + return TranslationServer::get_singleton()->doc_translate(text); + } + + return p_text; +} #endif String RTR(const String &p_text) { - if (TranslationServer::get_singleton()) { String rtr = TranslationServer::get_singleton()->tool_translate(p_text); if (rtr == String() || rtr == p_text) { diff --git a/core/ustring.h b/core/ustring.h index e70b2bfe27..33320a0a49 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -415,25 +415,25 @@ _FORCE_INLINE_ bool is_str_less(const L *l_ptr, const R *r_ptr) { /* end of namespace */ -//tool translate +// Tool translate (TTR and variants) for the editor UI, +// and doc translate for the class reference (DTR). #ifdef TOOLS_ENABLED - -//gets parsed +// Gets parsed. String TTR(const String &); -//use for C strings +String DTR(const String &); +// Use for C strings. #define TTRC(m_value) (m_value) -//use to avoid parsing (for use later with C strings) +// Use to avoid parsing (for use later with C strings). #define TTRGET(m_value) TTR(m_value) #else - #define TTR(m_value) (String()) +#define DTR(m_value) (String()) #define TTRC(m_value) (m_value) #define TTRGET(m_value) (m_value) - #endif -//tool or regular translate +// Runtime translate for the public node API. String RTR(const String &); bool is_symbol(CharType c); |