summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/io/pck_packer.cpp2
-rw-r--r--core/io/translation_loader_po.cpp27
-rw-r--r--core/io/translation_loader_po.h2
-rw-r--r--core/math/a_star.cpp195
-rw-r--r--core/math/a_star.h10
-rw-r--r--core/translation.cpp17
-rw-r--r--core/translation.h3
-rw-r--r--core/ustring.cpp11
-rw-r--r--core/ustring.h16
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);