summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/array.cpp20
-rw-r--r--core/array.h4
-rw-r--r--core/dvector.h28
-rw-r--r--core/func_ref.cpp6
-rw-r--r--core/image.cpp1
-rw-r--r--core/input_map.cpp58
-rw-r--r--core/input_map.h9
-rw-r--r--core/io/file_access_pack.cpp2
-rw-r--r--core/io/pck_packer.cpp191
-rw-r--r--core/io/pck_packer.h59
-rw-r--r--core/math/a_star.cpp412
-rw-r--r--core/math/a_star.h92
-rw-r--r--core/math/math_2d.cpp24
-rw-r--r--core/math/math_2d.h15
-rw-r--r--core/math/triangulate.cpp5
-rw-r--r--core/math/vector3.cpp22
-rw-r--r--core/math/vector3.h197
-rw-r--r--core/method_bind.h19
-rw-r--r--core/object.cpp34
-rw-r--r--core/object_type_db.cpp181
-rw-r--r--core/object_type_db.h19
-rw-r--r--core/os/input.cpp8
-rw-r--r--core/os/input.h25
-rw-r--r--core/os/input_event.cpp6
-rw-r--r--core/os/os.cpp3
-rw-r--r--core/os/os.h9
-rw-r--r--core/register_core_types.cpp5
-rw-r--r--core/script_debugger_remote.cpp9
-rw-r--r--core/script_language.h20
-rw-r--r--core/translation.cpp438
-rw-r--r--core/undo_redo.cpp16
-rw-r--r--core/ustring.cpp7
-rw-r--r--core/ustring.h2
-rw-r--r--core/variant.cpp14
-rw-r--r--core/variant.h2
-rw-r--r--core/variant_call.cpp26
-rw-r--r--core/variant_parser.cpp16
37 files changed, 1690 insertions, 314 deletions
diff --git a/core/array.cpp b/core/array.cpp
index 23792f90fc..683a43e3d0 100644
--- a/core/array.cpp
+++ b/core/array.cpp
@@ -276,16 +276,26 @@ void Array::push_front(const Variant& p_value) {
_p->array.insert(0,p_value);
}
-void Array::pop_back(){
+Variant Array::pop_back(){
- if (!_p->array.empty())
- _p->array.resize( _p->array.size() -1 );
+ if (!_p->array.empty()) {
+ int n = _p->array.size() - 1;
+ Variant ret = _p->array.get(n);
+ _p->array.resize(n);
+ return ret;
+ }
+ return Variant();
}
-void Array::pop_front(){
- if (!_p->array.empty())
+Variant Array::pop_front(){
+
+ if (!_p->array.empty()) {
+ Variant ret = _p->array.get(0);
_p->array.remove(0);
+ return ret;
+ }
+ return Variant();
}
diff --git a/core/array.h b/core/array.h
index dfc902525c..eb79b0cf33 100644
--- a/core/array.h
+++ b/core/array.h
@@ -80,8 +80,8 @@ public:
void erase(const Variant& p_value);
void push_front(const Variant& p_value);
- void pop_back();
- void pop_front();
+ Variant pop_back();
+ Variant pop_front();
Array(const Array& p_from);
Array(bool p_shared=false);
diff --git a/core/dvector.h b/core/dvector.h
index a5519ed604..9a54641617 100644
--- a/core/dvector.h
+++ b/core/dvector.h
@@ -262,6 +262,34 @@ public:
w[bs+i]=r[i];
}
+ DVector<T> subarray(int p_from, int p_to) {
+
+ if (p_from<0) {
+ p_from=size()+p_from;
+ }
+ if (p_to<0) {
+ p_to=size()+p_to;
+ }
+ if (p_from<0 || p_from>=size()) {
+ DVector<T>& aux=*((DVector<T>*)0); // nullreturn
+ ERR_FAIL_COND_V(p_from<0 || p_from>=size(),aux)
+ }
+ if (p_to<0 || p_to>=size()) {
+ DVector<T>& aux=*((DVector<T>*)0); // nullreturn
+ ERR_FAIL_COND_V(p_to<0 || p_to>=size(),aux)
+ }
+
+ DVector<T> slice;
+ int span=1 + p_to - p_from;
+ slice.resize(span);
+ Read r = read();
+ Write w = slice.write();
+ for (int i=0; i<span; ++i) {
+ w[i] = r[p_from+i];
+ }
+
+ return slice;
+ }
Error insert(int p_pos,const T& p_val) {
diff --git a/core/func_ref.cpp b/core/func_ref.cpp
index 644d8b5b63..ca890111be 100644
--- a/core/func_ref.cpp
+++ b/core/func_ref.cpp
@@ -61,11 +61,7 @@ void FuncRef::_bind_methods() {
MethodInfo mi;
mi.name="call_func";
Vector<Variant> defargs;
- for(int i=0;i<10;i++) {
- mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
- defargs.push_back(Variant());
- }
- ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_func:Variant",&FuncRef::call_func,mi,defargs);
+ ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_func:Variant",&FuncRef::call_func,mi,defargs);
}
diff --git a/core/image.cpp b/core/image.cpp
index d6ac3f28ea..90051d7d0d 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -2052,6 +2052,7 @@ Error Image::_decompress_bc() {
ht/=2;
} break;
+ default: {}
}
}
diff --git a/core/input_map.cpp b/core/input_map.cpp
index 08ee8138a3..09cb7ce426 100644
--- a/core/input_map.cpp
+++ b/core/input_map.cpp
@@ -232,62 +232,8 @@ bool InputMap::event_is_action(const InputEvent& p_event, const StringName& p_ac
return _find_event(E->get().inputs,p_event)!=NULL;
}
-bool InputMap::event_is_joy_motion_action_pressed(const InputEvent& p_event) const {
-
- ERR_FAIL_COND_V(p_event.type!=InputEvent::JOYSTICK_MOTION,false);
- bool pressed=false;
-
- //this could be optimized by having a separate list of joymotions?
-
- for (Map<StringName, Action>::Element *A=input_map.front();A;A=A->next()) {
-
- for (List<InputEvent>::Element *E=A->get().inputs.front();E;E=E->next()) {
-
- const InputEvent& e=E->get();
- if(e.type!=p_event.type)
- continue;
- if (e.type!=InputEvent::KEY && e.device!=p_event.device)
- continue;
-
- switch(p_event.type) {
-
- case InputEvent::KEY: {
-
- if (e.key.scancode==p_event.key.scancode && e.key.mod == p_event.key.mod)
- return e.key.pressed;
-
- } break;
- case InputEvent::JOYSTICK_BUTTON: {
-
- if (e.joy_button.button_index==p_event.joy_button.button_index) {
- return e.joy_button.pressed;
- }
-
- } break;
- case InputEvent::MOUSE_BUTTON: {
-
- if (e.mouse_button.button_index==p_event.mouse_button.button_index) {
- return e.mouse_button.pressed;
- }
-
- } break;
- case InputEvent::JOYSTICK_MOTION: {
-
- if (e.joy_motion.axis==p_event.joy_motion.axis) {
- if (
- (e.joy_motion.axis_value * p_event.joy_motion.axis_value >0) && //same axis
- ABS(e.joy_motion.axis_value)>0.5 && ABS(p_event.joy_motion.axis_value)>0.5 )
- pressed=true;
- }
-
- } break;
- }
-
- }
- }
-
- return pressed;
-
+const Map<StringName, InputMap::Action>& InputMap::get_action_map() const {
+ return input_map;
}
void InputMap::load_from_globals() {
diff --git a/core/input_map.h b/core/input_map.h
index dc5a911963..21c479588d 100644
--- a/core/input_map.h
+++ b/core/input_map.h
@@ -35,12 +35,14 @@
class InputMap : public Object {
OBJ_TYPE( InputMap, Object );
- static InputMap *singleton;
-
+public:
struct Action {
int id;
List<InputEvent> inputs;
};
+private:
+ static InputMap *singleton;
+
mutable Map<StringName, Action> input_map;
mutable Map<int,StringName> input_id_map;
@@ -70,9 +72,8 @@ public:
const List<InputEvent> *get_action_list(const StringName& p_action);
bool event_is_action(const InputEvent& p_event, const StringName& p_action) const;
- bool event_is_joy_motion_action_pressed(const InputEvent& p_event) const;
-
+ const Map<StringName, Action>& get_action_map() const;
void load_from_globals();
void load_default();
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index 5c8c741f28..1632b841c6 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -409,6 +409,8 @@ Error DirAccessPack::change_dir(String p_dir) {
nd=nd.simplify_path();
+ if (nd == "") nd = ".";
+
if (nd.begins_with("/")) {
nd=nd.replace_first("/","") ;
absolute=true;
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
new file mode 100644
index 0000000000..04b88ea028
--- /dev/null
+++ b/core/io/pck_packer.cpp
@@ -0,0 +1,191 @@
+/*************************************************************************/
+/* pkc_packer.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 "pck_packer.h"
+
+#include "core/os/file_access.h"
+
+static uint64_t _align(uint64_t p_n, int p_alignment) {
+
+ if (p_alignment == 0)
+ return p_n;
+
+ uint64_t rest = p_n % p_alignment;
+ if (rest == 0)
+ return p_n;
+ else
+ return p_n + (p_alignment - rest);
+};
+
+static void _pad(FileAccess* p_file, int p_bytes) {
+
+ for (int i=0; i<p_bytes; i++) {
+
+ p_file->store_8(0);
+ };
+};
+
+void PCKPacker::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("pck_start","pck_name","alignment"),&PCKPacker::pck_start);
+ ObjectTypeDB::bind_method(_MD("add_file","pck_path","source_path"),&PCKPacker::add_file);
+ ObjectTypeDB::bind_method(_MD("flush","verbose"),&PCKPacker::flush);
+};
+
+
+Error PCKPacker::pck_start(const String& p_file, int p_alignment) {
+
+ file = FileAccess::open(p_file, FileAccess::WRITE);
+ if (file == NULL) {
+
+ return ERR_CANT_CREATE;
+ };
+
+ alignment = p_alignment;
+
+ file->store_32(0x43504447); // MAGIC
+ file->store_32(0); // # version
+ file->store_32(0); // # major
+ file->store_32(0); // # minor
+ file->store_32(0); // # revision
+
+ for (int i=0; i<16; i++) {
+
+ file->store_32(0); // reserved
+ };
+
+ files.clear();
+
+ return OK;
+};
+
+Error PCKPacker::add_file(const String& p_file, const String& p_src) {
+
+ FileAccess* f = FileAccess::open(p_src, FileAccess::READ);
+ if (!f) {
+ return ERR_FILE_CANT_OPEN;
+ };
+
+ File pf;
+ pf.path = p_file;
+ pf.src_path = p_src;
+ pf.size = f->get_len();
+ pf.offset_offset = 0;
+
+ files.push_back(pf);
+
+ f->close();
+ memdelete(f);
+
+ return OK;
+};
+
+Error PCKPacker::flush(bool p_verbose) {
+
+ if (!file) {
+ ERR_FAIL_COND_V(!file, ERR_INVALID_PARAMETER);
+ return ERR_INVALID_PARAMETER;
+ };
+
+ // write the index
+
+ file->store_32(files.size());
+
+ for (int i=0; i<files.size(); i++) {
+
+ file->store_pascal_string(files[i].path);
+ files[i].offset_offset = file->get_pos();
+ file->store_64(0); // offset
+ file->store_64(files[i].size); // size
+
+ // # empty md5
+ file->store_32(0);
+ file->store_32(0);
+ file->store_32(0);
+ file->store_32(0);
+ };
+
+
+ uint64_t ofs = file->get_pos();
+ ofs = _align(ofs, alignment);
+
+ _pad(file, ofs - file->get_pos());
+
+ const uint32_t buf_max = 65536;
+ uint8_t *buf = memnew_arr(uint8_t, buf_max);
+
+ int count = 0;
+ for (int i=0; i<files.size(); i++) {
+
+ FileAccess* src = FileAccess::open(files[i].src_path, FileAccess::READ);
+ uint64_t to_write = files[i].size;
+ while (to_write > 0) {
+
+ int read = src->get_buffer(buf, MIN(to_write, buf_max));
+ file->store_buffer(buf, read);
+ to_write -= read;
+ };
+
+ uint64_t pos = file->get_pos();
+ file->seek(files[i].offset_offset); // go back to store the file's offset
+ file->store_64(ofs);
+ file->seek(pos);
+
+ ofs = _align(ofs + files[i].size, alignment);
+ _pad(file, ofs - pos);
+
+ src->close();
+ memdelete(src);
+ count += 1;
+ if (p_verbose) {
+ if (count % 100 == 0) {
+ printf("%i/%i (%.2f)\r", count, files.size(), float(count) / files.size() * 100);
+ fflush(stdout);
+ };
+ };
+ };
+
+ if (p_verbose)
+ printf("\n");
+
+ file->close();
+
+ return OK;
+};
+
+PCKPacker::PCKPacker() {
+
+ file = NULL;
+};
+
+PCKPacker::~PCKPacker() {
+ if (file != NULL) {
+ memdelete(file);
+ };
+ file = NULL;
+};
diff --git a/core/io/pck_packer.h b/core/io/pck_packer.h
new file mode 100644
index 0000000000..b1182335e2
--- /dev/null
+++ b/core/io/pck_packer.h
@@ -0,0 +1,59 @@
+/*************************************************************************/
+/* pck_packer.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* */
+/* 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 "core/reference.h"
+
+class FileAccess;
+
+class PCKPacker : public Reference {
+
+ OBJ_TYPE(PCKPacker, Reference);
+
+ FileAccess* file;
+ int alignment;
+
+ static void _bind_methods();
+
+ struct File {
+
+ String path;
+ String src_path;
+ int size;
+ uint64_t offset_offset;
+ };
+ Vector<File> files;
+
+public:
+ Error pck_start(const String& p_file, int p_alignment);
+ Error add_file(const String& p_file, const String& p_src);
+ Error flush(bool p_verbose = false);
+
+
+ PCKPacker();
+ ~PCKPacker();
+};
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
new file mode 100644
index 0000000000..5bbbbdaa5a
--- /dev/null
+++ b/core/math/a_star.cpp
@@ -0,0 +1,412 @@
+#include "a_star.h"
+#include "geometry.h"
+
+
+int AStar::get_available_point_id() const {
+
+ if (points.empty()) {
+ return 1;
+ }
+
+ return points.back()->key()+1;
+}
+
+void AStar::add_point(int p_id, const Vector3 &p_pos, float p_weight_scale) {
+ ERR_FAIL_COND(p_id<0);
+ if (!points.has(p_id)) {
+ Point *pt = memnew( Point );
+ pt->id=p_id;
+ pt->pos=p_pos;
+ pt->weight_scale=p_weight_scale;
+ pt->prev_point=NULL;
+ pt->last_pass=0;
+ points[p_id]=pt;
+ } else {
+ points[p_id]->pos=p_pos;
+ points[p_id]->weight_scale=p_weight_scale;
+ }
+}
+
+Vector3 AStar::get_point_pos(int p_id) const{
+
+ ERR_FAIL_COND_V(!points.has(p_id),Vector3());
+
+ return points[p_id]->pos;
+
+}
+float AStar::get_point_weight_scale(int p_id) const{
+
+ ERR_FAIL_COND_V(!points.has(p_id),0);
+
+ return points[p_id]->weight_scale;
+
+}
+void AStar::remove_point(int p_id){
+
+ ERR_FAIL_COND(!points.has(p_id));
+
+ Point* p = points[p_id];
+
+ for(int i=0;i<p->neighbours.size();i++) {
+
+ Segment s(p_id,p->neighbours[i]->id);
+ segments.erase(s);
+ p->neighbours[i]->neighbours.erase(p);
+ }
+
+ memdelete(p);
+ points.erase(p_id);
+}
+
+void AStar::connect_points(int p_id,int p_with_id){
+
+ ERR_FAIL_COND(!points.has(p_id));
+ ERR_FAIL_COND(!points.has(p_with_id));
+ ERR_FAIL_COND(p_id==p_with_id);
+
+
+ Point* a = points[p_id];
+ Point* b = points[p_with_id];
+ a->neighbours.push_back(b);
+ b->neighbours.push_back(a);
+
+ Segment s(p_id,p_with_id);
+ if (s.from==p_id) {
+ s.from_point=a;
+ s.to_point=b;
+ } else {
+ s.from_point=b;
+ s.to_point=a;
+ }
+
+ segments.insert(s);
+
+
+}
+void AStar::disconnect_points(int p_id,int p_with_id){
+
+ Segment s(p_id,p_with_id);
+ ERR_FAIL_COND(!segments.has(s));
+
+
+ segments.erase(s);
+
+ Point *a = points[p_id];
+ Point *b = points[p_with_id];
+ a->neighbours.erase(b);
+ b->neighbours.erase(a);
+
+}
+bool AStar::are_points_connected(int p_id,int p_with_id) const{
+
+ Segment s(p_id,p_with_id);
+ return segments.has(s);
+}
+
+void AStar::clear(){
+
+ for (const Map<int,Point*>::Element *E=points.front();E;E=E->next()) {
+
+ memdelete(E->get());
+ }
+ segments.clear();
+ points.clear();
+}
+
+
+int AStar::get_closest_point(const Vector3& p_point) const{
+
+ int closest_id=-1;
+ float closest_dist=1e20;
+
+ for (const Map<int,Point*>::Element *E=points.front();E;E=E->next()) {
+
+ float d = p_point.distance_squared_to(E->get()->pos);
+ if (closest_id<0 || d<closest_dist) {
+ closest_dist=d;
+ closest_id=E->key();
+ }
+ }
+
+ return closest_id;
+
+
+}
+Vector3 AStar::get_closest_pos_in_segment(const Vector3& p_point) const {
+
+ float closest_dist = 1e20;
+ bool found=false;
+ Vector3 closest_point;
+
+
+ for (const Set<Segment>::Element *E=segments.front();E;E=E->next()) {
+
+ Vector3 segment[2]={
+ E->get().from_point->pos,
+ E->get().to_point->pos,
+ };
+
+ Vector3 p = Geometry::get_closest_point_to_segment(p_point,segment);
+ float d = p_point.distance_squared_to(p);
+ if (!found || d<closest_dist) {
+
+ closest_point=p;
+ closest_dist=d;
+ found=true;
+ }
+ }
+
+ return closest_point;
+}
+
+bool AStar::_solve(Point* begin_point, Point* end_point) {
+
+ pass++;
+
+ SelfList<Point>::List open_list;
+
+ bool found_route=false;
+
+
+ for(int i=0;i<begin_point->neighbours.size();i++) {
+
+ Point *n = begin_point->neighbours[i];
+ n->prev_point=begin_point;
+ n->distance=n->pos.distance_to(begin_point->pos);
+ n->distance*=n->weight_scale;
+ n->last_pass=pass;
+ open_list.add(&n->list);
+
+ if (end_point==n) {
+ found_route=true;
+ break;
+ }
+ }
+
+ while(!found_route) {
+
+ if (open_list.first()==NULL) {
+ //could not find path sadly
+ break;
+ }
+ //check open list
+
+ SelfList<Point> *least_cost_point=NULL;
+ float least_cost=1e30;
+
+ //this could be faster (cache previous results)
+ for (SelfList<Point> *E=open_list.first();E;E=E->next()) {
+
+ Point *p=E->self();
+
+ float cost=p->distance;
+ cost+=p->pos.distance_to(end_point->pos);
+ cost*=p->weight_scale;
+
+ if (cost<least_cost) {
+
+ least_cost_point=E;
+ least_cost=cost;
+ }
+ }
+
+
+ Point *p=least_cost_point->self();
+ //open the neighbours for search
+ int es = p->neighbours.size();
+
+ for(int i=0;i<es;i++) {
+
+
+ Point* e=p->neighbours[i];
+
+
+ float distance = p->pos.distance_to(e->pos) + p->distance;
+ distance*=e->weight_scale;
+
+
+
+ if (e->last_pass==pass) {
+ //oh this was visited already, can we win the cost?
+
+ if (e->distance>distance) {
+
+ e->prev_point=p;
+ e->distance=distance;
+ }
+ } else {
+ //add to open neighbours
+
+ e->prev_point=p;
+ e->distance=distance;
+ e->last_pass=pass; //mark as used
+ open_list.add(&e->list);
+
+ if (e==end_point) {
+ //oh my reached end! stop algorithm
+ found_route=true;
+ break;
+
+ }
+
+ }
+ }
+
+ if (found_route)
+ break;
+
+ open_list.remove(least_cost_point);
+ }
+
+ //clear the openf list
+ while(open_list.first()) {
+ open_list.remove( open_list.first() );
+ }
+
+ return found_route;
+
+}
+
+DVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) {
+
+ ERR_FAIL_COND_V(!points.has(p_from_id),DVector<Vector3>());
+ ERR_FAIL_COND_V(!points.has(p_to_id),DVector<Vector3>());
+
+
+ pass++;
+
+ Point* a = points[p_from_id];
+ Point* b = points[p_to_id];
+
+ if (a==b) {
+ DVector<Vector3> ret;
+ ret.push_back(a->pos);
+ return ret;
+ }
+
+
+ Point *begin_point=a;
+ Point *end_point=b;
+
+ bool found_route=_solve(begin_point,end_point);
+
+ if (!found_route)
+ return DVector<Vector3>();
+
+ //midpoints
+ Point *p=end_point;
+ int pc=1; //begin point
+ while(p!=begin_point) {
+ pc++;
+ p=p->prev_point;
+ }
+
+ DVector<Vector3> path;
+ path.resize(pc);
+
+ {
+ DVector<Vector3>::Write w = path.write();
+
+ Point *p=end_point;
+ int idx=pc-1;
+ while(p!=begin_point) {
+ w[idx--]=p->pos;
+ p=p->prev_point;
+ }
+
+ w[0]=p->pos; //assign first
+
+ }
+
+ return path;
+
+}
+
+
+DVector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
+
+ ERR_FAIL_COND_V(!points.has(p_from_id),DVector<int>());
+ ERR_FAIL_COND_V(!points.has(p_to_id),DVector<int>());
+
+
+ pass++;
+
+ Point* a = points[p_from_id];
+ Point* b = points[p_to_id];
+
+ if (a==b) {
+ DVector<int> ret;
+ ret.push_back(a->id);
+ return ret;
+ }
+
+
+ Point *begin_point=a;
+ Point *end_point=b;
+
+ bool found_route=_solve(begin_point,end_point);
+
+ if (!found_route)
+ return DVector<int>();
+
+ //midpoints
+ Point *p=end_point;
+ int pc=1; //begin point
+ while(p!=begin_point) {
+ pc++;
+ p=p->prev_point;
+ }
+
+ DVector<int> path;
+ path.resize(pc);
+
+ {
+ DVector<int>::Write w = path.write();
+
+ 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;
+}
+
+void AStar::_bind_methods() {
+
+ ObjectTypeDB::bind_method(_MD("get_available_point_id"),&AStar::get_available_point_id);
+ ObjectTypeDB::bind_method(_MD("add_point","id","pos","weight_scale"),&AStar::add_point,DEFVAL(1.0));
+ ObjectTypeDB::bind_method(_MD("get_point_pos","id"),&AStar::get_point_pos);
+ ObjectTypeDB::bind_method(_MD("get_point_weight_scale","id"),&AStar::get_point_weight_scale);
+ ObjectTypeDB::bind_method(_MD("remove_point","id"),&AStar::remove_point);
+
+ ObjectTypeDB::bind_method(_MD("connect_points","id","to_id"),&AStar::connect_points);
+ ObjectTypeDB::bind_method(_MD("disconnect_points","id","to_id"),&AStar::disconnect_points);
+ ObjectTypeDB::bind_method(_MD("are_points_connected","id","to_id"),&AStar::are_points_connected);
+
+ ObjectTypeDB::bind_method(_MD("clear"),&AStar::clear);
+
+ ObjectTypeDB::bind_method(_MD("get_closest_point","to_pos"),&AStar::get_closest_point);
+ ObjectTypeDB::bind_method(_MD("get_closest_pos_in_segment","to_pos"),&AStar::get_closest_pos_in_segment);
+
+ ObjectTypeDB::bind_method(_MD("get_point_path","from_id","to_id"),&AStar::get_point_path);
+ ObjectTypeDB::bind_method(_MD("get_id_path","from_id","to_id"),&AStar::get_id_path);
+
+}
+
+
+AStar::AStar() {
+
+ pass=1;
+}
+
+
+AStar::~AStar() {
+
+ pass=1;
+}
diff --git a/core/math/a_star.h b/core/math/a_star.h
new file mode 100644
index 0000000000..a0517b5941
--- /dev/null
+++ b/core/math/a_star.h
@@ -0,0 +1,92 @@
+#ifndef ASTAR_H
+#define ASTAR_H
+
+#include "reference.h"
+#include "self_list.h"
+
+class AStar: public Reference {
+
+ OBJ_TYPE(AStar,Reference)
+
+
+ uint64_t pass;
+
+ struct Point {
+
+ SelfList<Point> list;
+
+ int id;
+ Vector3 pos;
+ float weight_scale;
+ uint64_t last_pass;
+
+ Vector<Point*> neighbours;
+
+ //used for pathfinding
+ Point *prev_point;
+ float distance;
+
+ Point() : list(this) {}
+ };
+
+ Map<int,Point*> points;
+
+ struct Segment {
+ union {
+ struct {
+ int32_t from;
+ int32_t to;
+ };
+ uint64_t key;
+ };
+
+ Point *from_point;
+ Point *to_point;
+
+ bool operator<(const Segment& p_s) const { return key<p_s.key; }
+ Segment() { key=0; }
+ Segment(int p_from,int p_to) {
+ if (p_from > p_to) {
+ SWAP(p_from,p_to);
+ }
+
+ from=p_from;
+ to=p_to;
+ }
+ };
+
+
+ Set<Segment> segments;
+
+ bool _solve(Point *begin_point, Point *end_point);
+
+protected:
+
+ static void _bind_methods();
+public:
+
+ int get_available_point_id() const;
+
+ void add_point(int p_id,const Vector3& p_pos,float p_weight_scale=1);
+ Vector3 get_point_pos(int p_id) const;
+ float get_point_weight_scale(int p_id) const;
+ void remove_point(int p_id);
+
+ void connect_points(int p_id,int p_with_id);
+ void disconnect_points(int p_id,int p_with_id);
+ bool are_points_connected(int p_id,int p_with_id) const;
+
+ void clear();
+
+
+ int get_closest_point(const Vector3& p_point) const;
+ Vector3 get_closest_pos_in_segment(const Vector3& p_point) const;
+
+ DVector<Vector3> get_point_path(int p_from_id, int p_to_id);
+ DVector<int> get_id_path(int p_from_id, int p_to_id);
+
+ AStar();
+ ~AStar();
+};
+
+#endif // ASTAR_H
diff --git a/core/math/math_2d.cpp b/core/math/math_2d.cpp
index 0e2060008c..e616f05914 100644
--- a/core/math/math_2d.cpp
+++ b/core/math/math_2d.cpp
@@ -424,7 +424,7 @@ Matrix32 Matrix32::inverse() const {
void Matrix32::affine_invert() {
- float det = elements[0][0]*elements[1][1] - elements[1][0]*elements[0][1];
+ float det = basis_determinant();
ERR_FAIL_COND(det==0);
float idet = 1.0 / det;
@@ -475,18 +475,18 @@ Matrix32::Matrix32(real_t p_rot, const Vector2& p_pos) {
elements[2]=p_pos;
}
-Vector2 Matrix32::get_scale() const {
+Size2 Matrix32::get_scale() const {
- return Vector2( elements[0].length(), elements[1].length() );
+ return Size2( elements[0].length(), elements[1].length() );
}
-void Matrix32::scale(const Vector2& p_scale) {
+void Matrix32::scale(const Size2& p_scale) {
elements[0]*=p_scale;
elements[1]*=p_scale;
elements[2]*=p_scale;
}
-void Matrix32::scale_basis(const Vector2& p_scale) {
+void Matrix32::scale_basis(const Size2& p_scale) {
elements[0]*=p_scale;
elements[1]*=p_scale;
@@ -501,7 +501,6 @@ void Matrix32::translate( const Vector2& p_translation ) {
elements[2]+=basis_xform(p_translation);
}
-
void Matrix32::orthonormalize() {
// Gram-Schmidt Process
@@ -550,11 +549,6 @@ void Matrix32::operator*=(const Matrix32& p_transform) {
elements[2] = xform(p_transform.elements[2]);
float x0,x1,y0,y1;
-/*
- x0 = p_transform.tdotx(elements[0]);
- x1 = p_transform.tdoty(elements[0]);
- y0 = p_transform.tdotx(elements[1]);
- y1 = p_transform.tdoty(elements[1]);*/
x0 = tdotx(p_transform.elements[0]);
x1 = tdoty(p_transform.elements[0]);
@@ -576,7 +570,7 @@ Matrix32 Matrix32::operator*(const Matrix32& p_transform) const {
}
-Matrix32 Matrix32::scaled(const Vector2& p_scale) const {
+Matrix32 Matrix32::scaled(const Size2& p_scale) const {
Matrix32 copy=*this;
copy.scale(p_scale);
@@ -584,7 +578,7 @@ Matrix32 Matrix32::scaled(const Vector2& p_scale) const {
}
-Matrix32 Matrix32::basis_scaled(const Vector2& p_scale) const {
+Matrix32 Matrix32::basis_scaled(const Size2& p_scale) const {
Matrix32 copy=*this;
copy.scale_basis(p_scale);
@@ -629,8 +623,8 @@ Matrix32 Matrix32::interpolate_with(const Matrix32& p_transform, float p_c) cons
real_t r1 = get_rotation();
real_t r2 = p_transform.get_rotation();
- Vector2 s1 = get_scale();
- Vector2 s2 = p_transform.get_scale();
+ Size2 s1 = get_scale();
+ Size2 s2 = p_transform.get_scale();
//slerp rotation
Vector2 v1(Math::cos(r1), Math::sin(r1));
diff --git a/core/math/math_2d.h b/core/math/math_2d.h
index 90aae9fe50..38c1ac9656 100644
--- a/core/math/math_2d.h
+++ b/core/math/math_2d.h
@@ -553,10 +553,8 @@ struct Rect2i {
struct Matrix32 {
-
Vector2 elements[3];
-
_FORCE_INLINE_ float tdotx(const Vector2& v) const { return elements[0][0] * v.x + elements[1][0] * v.y; }
_FORCE_INLINE_ float tdoty(const Vector2& v) const { return elements[0][1] * v.x + elements[1][1] * v.y; }
@@ -577,26 +575,25 @@ struct Matrix32 {
_FORCE_INLINE_ void set_rotation_and_scale(real_t p_phi,const Size2& p_scale);
void rotate(real_t p_phi);
- void scale(const Vector2& p_scale);
- void scale_basis(const Vector2& p_scale);
+ void scale(const Size2& p_scale);
+ void scale_basis(const Size2& p_scale);
void translate( real_t p_tx, real_t p_ty);
void translate( const Vector2& p_translation );
float basis_determinant() const;
- Vector2 get_scale() const;
+ Size2 get_scale() const;
_FORCE_INLINE_ const Vector2& get_origin() const { return elements[2]; }
_FORCE_INLINE_ void set_origin(const Vector2& p_origin) { elements[2]=p_origin; }
- Matrix32 scaled(const Vector2& p_scale) const;
- Matrix32 basis_scaled(const Vector2& p_scale) const;
+ Matrix32 scaled(const Size2& p_scale) const;
+ Matrix32 basis_scaled(const Size2& p_scale) const;
Matrix32 translated(const Vector2& p_offset) const;
Matrix32 rotated(float p_phi) const;
Matrix32 untranslated() const;
-
void orthonormalize();
Matrix32 orthonormalized() const;
@@ -615,7 +612,6 @@ struct Matrix32 {
_FORCE_INLINE_ Rect2 xform(const Rect2& p_vec) const;
_FORCE_INLINE_ Rect2 xform_inv(const Rect2& p_vec) const;
-
operator String() const;
Matrix32(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) {
@@ -630,7 +626,6 @@ struct Matrix32 {
Matrix32(real_t p_rot, const Vector2& p_pos);
Matrix32() { elements[0][0]=1.0; elements[1][1]=1.0; }
-
};
bool Rect2::intersects_transformed(const Matrix32& p_xform, const Rect2& p_rect) const {
diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp
index 27b7c86675..1f5d5ed6b3 100644
--- a/core/math/triangulate.cpp
+++ b/core/math/triangulate.cpp
@@ -157,7 +157,10 @@ bool Triangulate::triangulate(const Vector<Vector2> &contour,Vector<int> &result
m++;
/* remove v from remaining polygon */
- for(s=v,t=v+1;t<nv;s++,t++) V[s] = V[t]; nv--;
+ for(s=v,t=v+1;t<nv;s++,t++)
+ V[s] = V[t];
+
+ nv--;
/* resest error detection counter */
count = 2*nv;
diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp
index 8afd73f482..fae3831dd6 100644
--- a/core/math/vector3.cpp
+++ b/core/math/vector3.cpp
@@ -49,13 +49,13 @@ void Vector3::set_axis(int p_axis,real_t p_value) {
}
real_t Vector3::get_axis(int p_axis) const {
- ERR_FAIL_INDEX_V(p_axis,3,0);
- return operator[](p_axis);
+ ERR_FAIL_INDEX_V(p_axis,3,0);
+ return operator[](p_axis);
}
int Vector3::min_axis() const {
- return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2);
+ return x < y ? (x < z ? 0 : 2) : (y < z ? 1 : 2);
}
int Vector3::max_axis() const {
@@ -65,19 +65,15 @@ int Vector3::max_axis() const {
void Vector3::snap(float p_val) {
- x+=p_val/2.0;
- x-=Math::fmod(x,p_val);
- y+=p_val/2.0;
- y-=Math::fmod(y,p_val);
- z+=p_val/2.0;
- z-=Math::fmod(z,p_val);
-
+ x=Math::stepify(x,p_val);
+ y=Math::stepify(y,p_val);
+ z=Math::stepify(z,p_val);
}
Vector3 Vector3::snapped(float p_val) const {
- Vector3 v=*this;
- v.snap(p_val);
- return v;
+ Vector3 v=*this;
+ v.snap(p_val);
+ return v;
}
diff --git a/core/math/vector3.h b/core/math/vector3.h
index 910446023a..06840be5e7 100644
--- a/core/math/vector3.h
+++ b/core/math/vector3.h
@@ -63,77 +63,78 @@ struct Vector3 {
return coord[p_axis];
}
- void set_axis(int p_axis,real_t p_value);
- real_t get_axis(int p_axis) const;
+ void set_axis(int p_axis,real_t p_value);
+ real_t get_axis(int p_axis) const;
- int min_axis() const;
- int max_axis() const;
+ int min_axis() const;
+ int max_axis() const;
- _FORCE_INLINE_ real_t length() const;
- _FORCE_INLINE_ real_t length_squared() const;
+ _FORCE_INLINE_ real_t length() const;
+ _FORCE_INLINE_ real_t length_squared() const;
- _FORCE_INLINE_ void normalize();
- _FORCE_INLINE_ Vector3 normalized() const;
- _FORCE_INLINE_ Vector3 inverse() const;
+ _FORCE_INLINE_ void normalize();
+ _FORCE_INLINE_ Vector3 normalized() const;
+ _FORCE_INLINE_ Vector3 inverse() const;
_FORCE_INLINE_ void zero();
- void snap(float p_val);
- Vector3 snapped(float p_val) const;
+ void snap(float p_val);
+ Vector3 snapped(float p_val) const;
void rotate(const Vector3& p_axis,float p_phi);
Vector3 rotated(const Vector3& p_axis,float p_phi) const;
- /* Static Methods between 2 vector3s */
+ /* Static Methods between 2 vector3s */
- _FORCE_INLINE_ Vector3 linear_interpolate(const Vector3& p_b,float p_t) const;
+ _FORCE_INLINE_ Vector3 linear_interpolate(const Vector3& p_b,float p_t) const;
Vector3 cubic_interpolate(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,float p_t) const;
Vector3 cubic_interpolaten(const Vector3& p_b,const Vector3& p_pre_a, const Vector3& p_post_b,float p_t) const;
- _FORCE_INLINE_ Vector3 cross(const Vector3& p_b) const;
- _FORCE_INLINE_ real_t dot(const Vector3& p_b) const;
+ _FORCE_INLINE_ Vector3 cross(const Vector3& p_b) const;
+ _FORCE_INLINE_ real_t dot(const Vector3& p_b) const;
- _FORCE_INLINE_ Vector3 abs() const;
- _FORCE_INLINE_ Vector3 floor() const;
- _FORCE_INLINE_ Vector3 ceil() const;
+ _FORCE_INLINE_ Vector3 abs() const;
+ _FORCE_INLINE_ Vector3 floor() const;
+ _FORCE_INLINE_ Vector3 ceil() const;
- _FORCE_INLINE_ real_t distance_to(const Vector3& p_b) const;
- _FORCE_INLINE_ real_t distance_squared_to(const Vector3& p_b) const;
+ _FORCE_INLINE_ real_t distance_to(const Vector3& p_b) const;
+ _FORCE_INLINE_ real_t distance_squared_to(const Vector3& p_b) const;
+ _FORCE_INLINE_ real_t angle_to(const Vector3& p_b) const;
_FORCE_INLINE_ Vector3 slide(const Vector3& p_vec) const;
_FORCE_INLINE_ Vector3 reflect(const Vector3& p_vec) const;
- /* Operators */
+ /* Operators */
- _FORCE_INLINE_ Vector3& operator+=(const Vector3& p_v);
- _FORCE_INLINE_ Vector3 operator+(const Vector3& p_v) const;
- _FORCE_INLINE_ Vector3& operator-=(const Vector3& p_v);
- _FORCE_INLINE_ Vector3 operator-(const Vector3& p_v) const;
- _FORCE_INLINE_ Vector3& operator*=(const Vector3& p_v);
- _FORCE_INLINE_ Vector3 operator*(const Vector3& p_v) const;
- _FORCE_INLINE_ Vector3& operator/=(const Vector3& p_v);
- _FORCE_INLINE_ Vector3 operator/(const Vector3& p_v) const;
+ _FORCE_INLINE_ Vector3& operator+=(const Vector3& p_v);
+ _FORCE_INLINE_ Vector3 operator+(const Vector3& p_v) const;
+ _FORCE_INLINE_ Vector3& operator-=(const Vector3& p_v);
+ _FORCE_INLINE_ Vector3 operator-(const Vector3& p_v) const;
+ _FORCE_INLINE_ Vector3& operator*=(const Vector3& p_v);
+ _FORCE_INLINE_ Vector3 operator*(const Vector3& p_v) const;
+ _FORCE_INLINE_ Vector3& operator/=(const Vector3& p_v);
+ _FORCE_INLINE_ Vector3 operator/(const Vector3& p_v) const;
- _FORCE_INLINE_ Vector3& operator*=(real_t p_scalar);
- _FORCE_INLINE_ Vector3 operator*(real_t p_scalar) const;
- _FORCE_INLINE_ Vector3& operator/=(real_t p_scalar);
- _FORCE_INLINE_ Vector3 operator/(real_t p_scalar) const;
+ _FORCE_INLINE_ Vector3& operator*=(real_t p_scalar);
+ _FORCE_INLINE_ Vector3 operator*(real_t p_scalar) const;
+ _FORCE_INLINE_ Vector3& operator/=(real_t p_scalar);
+ _FORCE_INLINE_ Vector3 operator/(real_t p_scalar) const;
- _FORCE_INLINE_ Vector3 operator-() const;
+ _FORCE_INLINE_ Vector3 operator-() const;
- _FORCE_INLINE_ bool operator==(const Vector3& p_v) const;
- _FORCE_INLINE_ bool operator!=(const Vector3& p_v) const;
- _FORCE_INLINE_ bool operator<(const Vector3& p_v) const;
+ _FORCE_INLINE_ bool operator==(const Vector3& p_v) const;
+ _FORCE_INLINE_ bool operator!=(const Vector3& p_v) const;
+ _FORCE_INLINE_ bool operator<(const Vector3& p_v) const;
_FORCE_INLINE_ bool operator<=(const Vector3& p_v) const;
operator String() const;
- _FORCE_INLINE_ Vector3() { x=y=z=0; }
- _FORCE_INLINE_ Vector3(real_t p_x,real_t p_y,real_t p_z) { x=p_x; y=p_y; z=p_z; }
+ _FORCE_INLINE_ Vector3() { x=y=z=0; }
+ _FORCE_INLINE_ Vector3(real_t p_x,real_t p_y,real_t p_z) { x=p_x; y=p_y; z=p_z; }
};
@@ -151,11 +152,12 @@ Vector3 Vector3::cross(const Vector3& p_b) const {
(x * p_b.y) - (y * p_b.x)
);
- return ret;
+ return ret;
}
+
real_t Vector3::dot(const Vector3& p_b) const {
- return x*p_b.x + y*p_b.y + z*p_b.z;
+ return x*p_b.x + y*p_b.y + z*p_b.z;
}
Vector3 Vector3::abs() const {
@@ -180,115 +182,119 @@ Vector3 Vector3::linear_interpolate(const Vector3& p_b,float p_t) const {
y+(p_t * (p_b.y-y)),
z+(p_t * (p_b.z-z))
);
-
}
-
-
real_t Vector3::distance_to(const Vector3& p_b) const {
+
return (p_b-*this).length();
}
+
real_t Vector3::distance_squared_to(const Vector3& p_b) const {
- return (p_b-*this).length_squared();
+ return (p_b-*this).length_squared();
+}
+
+real_t Vector3::angle_to(const Vector3& p_b) const {
+
+ return Math::acos(this->dot(p_b) / Math::sqrt(this->length_squared() * p_b.length_squared()));
}
/* Operators */
Vector3& Vector3::operator+=(const Vector3& p_v) {
- x+=p_v.x;
- y+=p_v.y;
- z+=p_v.z;
- return *this;
+ x+=p_v.x;
+ y+=p_v.y;
+ z+=p_v.z;
+ return *this;
}
+
Vector3 Vector3::operator+(const Vector3& p_v) const {
- return Vector3(x+p_v.x, y+p_v.y, z+ p_v.z);
+ return Vector3(x+p_v.x, y+p_v.y, z+ p_v.z);
}
Vector3& Vector3::operator-=(const Vector3& p_v) {
- x-=p_v.x;
- y-=p_v.y;
- z-=p_v.z;
- return *this;
+ x-=p_v.x;
+ y-=p_v.y;
+ z-=p_v.z;
+ return *this;
}
Vector3 Vector3::operator-(const Vector3& p_v) const {
- return Vector3(x-p_v.x, y-p_v.y, z- p_v.z);
+ return Vector3(x-p_v.x, y-p_v.y, z- p_v.z);
}
-
-
Vector3& Vector3::operator*=(const Vector3& p_v) {
- x*=p_v.x;
- y*=p_v.y;
- z*=p_v.z;
- return *this;
+ x*=p_v.x;
+ y*=p_v.y;
+ z*=p_v.z;
+ return *this;
}
Vector3 Vector3::operator*(const Vector3& p_v) const {
- return Vector3(x*p_v.x, y*p_v.y, z* p_v.z);
+ return Vector3(x*p_v.x, y*p_v.y, z* p_v.z);
}
Vector3& Vector3::operator/=(const Vector3& p_v) {
- x/=p_v.x;
- y/=p_v.y;
- z/=p_v.z;
- return *this;
+ x/=p_v.x;
+ y/=p_v.y;
+ z/=p_v.z;
+ return *this;
}
+
Vector3 Vector3::operator/(const Vector3& p_v) const {
- return Vector3(x/p_v.x, y/p_v.y, z/ p_v.z);
+ return Vector3(x/p_v.x, y/p_v.y, z/ p_v.z);
}
Vector3& Vector3::operator*=(real_t p_scalar) {
- x*=p_scalar;
- y*=p_scalar;
- z*=p_scalar;
- return *this;
+ x*=p_scalar;
+ y*=p_scalar;
+ z*=p_scalar;
+ return *this;
}
_FORCE_INLINE_ Vector3 operator*(real_t p_scalar, const Vector3& p_vec) {
+
return p_vec * p_scalar;
}
Vector3 Vector3::operator*(real_t p_scalar) const {
- return Vector3( x*p_scalar, y*p_scalar, z*p_scalar);
+ return Vector3( x*p_scalar, y*p_scalar, z*p_scalar);
}
Vector3& Vector3::operator/=(real_t p_scalar) {
- x/=p_scalar;
- y/=p_scalar;
- z/=p_scalar;
- return *this;
+ x/=p_scalar;
+ y/=p_scalar;
+ z/=p_scalar;
+ return *this;
}
Vector3 Vector3::operator/(real_t p_scalar) const {
- return Vector3( x/p_scalar, y/p_scalar, z/p_scalar);
+ return Vector3( x/p_scalar, y/p_scalar, z/p_scalar);
}
Vector3 Vector3::operator-() const {
- return Vector3( -x, -y, -z );
+ return Vector3( -x, -y, -z );
}
-
bool Vector3::operator==(const Vector3& p_v) const {
- return (x==p_v.x && y==p_v.y && z==p_v.z);
+ return (x==p_v.x && y==p_v.y && z==p_v.z);
}
bool Vector3::operator!=(const Vector3& p_v) const {
- return (x!=p_v.x || y!=p_v.y || z!=p_v.z);
+ return (x!=p_v.x || y!=p_v.y || z!=p_v.z);
}
bool Vector3::operator<(const Vector3& p_v) const {
@@ -298,9 +304,9 @@ bool Vector3::operator<(const Vector3& p_v) const {
return z<p_v.z;
else
return y<p_v.y;
- } else
+ } else {
return x<p_v.x;
-
+ }
}
bool Vector3::operator<=(const Vector3& p_v) const {
@@ -310,9 +316,9 @@ bool Vector3::operator<=(const Vector3& p_v) const {
return z<=p_v.z;
else
return y<p_v.y;
- } else
+ } else {
return x<p_v.x;
-
+ }
}
_FORCE_INLINE_ Vector3 vec3_cross(const Vector3& p_a, const Vector3& p_b) {
@@ -333,6 +339,7 @@ real_t Vector3::length() const {
return Math::sqrt(x2+y2+z2);
}
+
real_t Vector3::length_squared() const {
real_t x2=x*x;
@@ -340,27 +347,25 @@ real_t Vector3::length_squared() const {
real_t z2=z*z;
return x2+y2+z2;
-
}
void Vector3::normalize() {
- real_t l=length();
- if (l==0) {
-
+ real_t l=length();
+ if (l==0) {
x=y=z=0;
- } else {
-
+ } else {
x/=l;
y/=l;
z/=l;
- }
+ }
}
+
Vector3 Vector3::normalized() const {
- Vector3 v=*this;
- v.normalize();
- return v;
+ Vector3 v=*this;
+ v.normalize();
+ return v;
}
Vector3 Vector3::inverse() const {
@@ -377,10 +382,10 @@ Vector3 Vector3::slide(const Vector3& p_vec) const {
return p_vec - *this * this->dot(p_vec);
}
+
Vector3 Vector3::reflect(const Vector3& p_vec) const {
return p_vec - *this * this->dot(p_vec) * 2.0;
-
}
#endif
diff --git a/core/method_bind.h b/core/method_bind.h
index 072953743c..04ff5c22c6 100644
--- a/core/method_bind.h
+++ b/core/method_bind.h
@@ -52,6 +52,7 @@ enum MethodFlags {
METHOD_FLAG_REVERSE=16, // used for events
METHOD_FLAG_VIRTUAL=32,
METHOD_FLAG_FROM_SCRIPT=64,
+ METHOD_FLAG_VARARG=128,
METHOD_FLAGS_DEFAULT=METHOD_FLAG_NORMAL,
};
@@ -229,7 +230,7 @@ public:
Vector<StringName> get_argument_names() const;
#endif
void set_hint_flags(uint32_t p_hint) { hint_flags=p_hint; }
- uint32_t get_hint_flags() const { return hint_flags|(is_const()?METHOD_FLAG_CONST:0); }
+ uint32_t get_hint_flags() const { return hint_flags|(is_const()?METHOD_FLAG_CONST:0)|(is_vararg()?METHOD_FLAG_VARARG:0); }
virtual String get_instance_type() const=0;
_FORCE_INLINE_ int get_argument_count() const { return argument_count; };
@@ -267,7 +268,7 @@ public:
_FORCE_INLINE_ int get_method_id() const { return method_id; }
_FORCE_INLINE_ bool is_const() const { return _const; }
_FORCE_INLINE_ bool has_return() const { return _returns; }
-
+ virtual bool is_vararg() const { return false; }
void set_default_arguments(const Vector<Variant>& p_defargs);
@@ -277,7 +278,7 @@ public:
template<class T>
-class MethodBindNative : public MethodBind {
+class MethodBindVarArg : public MethodBind {
public:
typedef Variant (T::*NativeCall)(const Variant**,int ,Variant::CallError &);
protected:
@@ -319,7 +320,9 @@ public:
}
#ifdef PTRCALL_ENABLED
- virtual void ptrcall(Object* p_object,const void** p_args,void* r_ret) {} //todo
+ virtual void ptrcall(Object* p_object,const void** p_args,void* r_ret) {
+ ERR_FAIL(); //can't call
+ } //todo
#endif
@@ -327,14 +330,16 @@ public:
virtual bool is_const() const { return false; }
virtual String get_instance_type() const { return T::get_type_static(); }
- MethodBindNative() { call_method=NULL; _set_returns(true);}
+ virtual bool is_vararg() const { return true; }
+
+ MethodBindVarArg() { call_method=NULL; _set_returns(true);}
};
template<class T >
-MethodBind* create_native_method_bind( Variant (T::*p_method)(const Variant**,int ,Variant::CallError &), const MethodInfo& p_info ) {
+MethodBind* create_vararg_method_bind( Variant (T::*p_method)(const Variant**,int ,Variant::CallError &), const MethodInfo& p_info ) {
- MethodBindNative<T > * a = memnew( (MethodBindNative<T >) );
+ MethodBindVarArg<T > * a = memnew( (MethodBindVarArg<T >) );
a->set_method(p_method);
a->set_method_info(p_info);
return a;
diff --git a/core/object.cpp b/core/object.cpp
index b036efa501..9a1e9be8d5 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1215,6 +1215,15 @@ void Object::emit_signal(const StringName& p_name,const Variant** p_args,int p_a
Signal *s = signal_map.getptr(p_name);
if (!s) {
+#ifdef DEBUG_ENABLED
+ bool signal_is_valid = ObjectTypeDB::has_signal(get_type_name(),p_name);
+ //check in script
+ if (!signal_is_valid && !script.is_null() && !Ref<Script>(script)->has_script_signal(p_name)) {
+ ERR_EXPLAIN("Can't emit non-existing signal " + String("\"")+p_name+"\".");
+ ERR_FAIL();
+ }
+#endif
+ //not connected? just return
return;
}
@@ -1644,6 +1653,7 @@ void Object::_clear_internal_resource_paths(const Variant &p_var) {
_clear_internal_resource_paths(d[E->get()]);
}
} break;
+ default: {}
}
}
@@ -1693,42 +1703,26 @@ void Object::_bind_methods() {
MethodInfo mi;
mi.name="emit_signal";
mi.arguments.push_back( PropertyInfo( Variant::STRING, "signal"));
- Vector<Variant> defargs;
- for(int i=0;i<VARIANT_ARG_MAX;i++) {
- mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
- defargs.push_back(Variant());
- }
-
- ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"emit_signal",&Object::_emit_signal,mi,defargs);
+ ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"emit_signal",&Object::_emit_signal,mi);
}
{
MethodInfo mi;
mi.name="call";
mi.arguments.push_back( PropertyInfo( Variant::STRING, "method"));
- Vector<Variant> defargs;
- for(int i=0;i<10;i++) {
- mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
- defargs.push_back(Variant());
- }
- ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call:Variant",&Object::_call_bind,mi,defargs);
+
+ ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call:Variant",&Object::_call_bind,mi);
}
{
MethodInfo mi;
mi.name="call_deferred";
mi.arguments.push_back( PropertyInfo( Variant::STRING, "method"));
- Vector<Variant> defargs;
- for(int i=0;i<VARIANT_ARG_MAX;i++) {
- mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
- defargs.push_back(Variant());
- }
-
- ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_deferred",&Object::_call_deferred_bind,mi,defargs);
+ ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_deferred",&Object::_call_deferred_bind,mi);
}
ObjectTypeDB::bind_method(_MD("callv:Variant","method","arg_array"),&Object::callv);
diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp
index b6a69e3bd4..e121dc9e98 100644
--- a/core/object_type_db.cpp
+++ b/core/object_type_db.cpp
@@ -189,6 +189,14 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,co
#endif
+
+ObjectTypeDB::APIType ObjectTypeDB::current_api=API_CORE;
+
+void ObjectTypeDB::set_current_api(APIType p_api) {
+
+ current_api=p_api;
+}
+
HashMap<StringName,ObjectTypeDB::TypeInfo,StringNameHasher> ObjectTypeDB::types;
HashMap<StringName,StringName,StringNameHasher> ObjectTypeDB::resource_base_extensions;
HashMap<StringName,StringName,StringNameHasher> ObjectTypeDB::compat_types;
@@ -258,6 +266,171 @@ StringName ObjectTypeDB::type_inherits_from(const StringName& p_type) {
return ti->inherits;
}
+ObjectTypeDB::APIType ObjectTypeDB::get_api_type(const StringName &p_type) {
+
+ OBJTYPE_LOCK;
+
+ TypeInfo *ti = types.getptr(p_type);
+ ERR_FAIL_COND_V(!ti,API_NONE);
+ return ti->api;
+}
+
+uint64_t ObjectTypeDB::get_api_hash(APIType p_api) {
+
+#ifdef DEBUG_METHODS_ENABLED
+
+ uint64_t hash = hash_djb2_one_64(HashMapHahserDefault::hash(VERSION_FULL_NAME));
+
+ List<StringName> names;
+
+ const StringName *k=NULL;
+
+ while((k=types.next(k))) {
+
+ names.push_back(*k);
+ }
+ //must be alphabetically sorted for hash to compute
+ names.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *E=names.front();E;E=E->next()) {
+
+ TypeInfo *t = types.getptr(E->get());
+ ERR_FAIL_COND_V(!t,0);
+ if (t->api!=p_api)
+ continue;
+ hash = hash_djb2_one_64(t->name.hash(),hash);
+ hash = hash_djb2_one_64(t->inherits.hash(),hash);
+
+ { //methods
+
+ List<StringName> snames;
+
+ k=NULL;
+
+ while((k=t->method_map.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *F=snames.front();F;F=F->next()) {
+
+ MethodBind *mb = t->method_map[F->get()];
+ hash = hash_djb2_one_64( mb->get_name().hash(), hash);
+ hash = hash_djb2_one_64( mb->get_argument_count(), hash);
+ hash = hash_djb2_one_64( mb->get_argument_type(-1), hash); //return
+
+ for(int i=0;i<mb->get_argument_count();i++) {
+ hash = hash_djb2_one_64( mb->get_argument_info(i).type, hash );
+ hash = hash_djb2_one_64( mb->get_argument_info(i).name.hash(), hash );
+ hash = hash_djb2_one_64( mb->get_argument_info(i).hint, hash );
+ hash = hash_djb2_one_64( mb->get_argument_info(i).hint_string.hash(), hash );
+ }
+
+ hash = hash_djb2_one_64( mb->get_default_argument_count(), hash);
+
+ for(int i=0;i<mb->get_default_argument_count();i++) {
+ //hash should not change, i hope for tis
+ Variant da = mb->get_default_argument(i);
+ hash = hash_djb2_one_64( da.hash(), hash );
+ }
+
+ hash = hash_djb2_one_64( mb->get_hint_flags(), hash);
+
+ }
+ }
+
+
+ { //constants
+
+ List<StringName> snames;
+
+ k=NULL;
+
+ while((k=t->constant_map.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *F=snames.front();F;F=F->next()) {
+
+ hash = hash_djb2_one_64(F->get().hash(), hash);
+ hash = hash_djb2_one_64( t->constant_map[F->get()], hash);
+ }
+ }
+
+
+ { //signals
+
+ List<StringName> snames;
+
+ k=NULL;
+
+ while((k=t->signal_map.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *F=snames.front();F;F=F->next()) {
+
+ MethodInfo &mi = t->signal_map[F->get()];
+ hash = hash_djb2_one_64( F->get().hash(), hash);
+ for(int i=0;i<mi.arguments.size();i++) {
+ hash = hash_djb2_one_64( mi.arguments[i].type, hash);
+ }
+ }
+ }
+
+ { //properties
+
+ List<StringName> snames;
+
+ k=NULL;
+
+ while((k=t->property_setget.next(k))) {
+
+ snames.push_back(*k);
+ }
+
+ snames.sort_custom<StringName::AlphCompare>();
+
+ for (List<StringName>::Element *F=snames.front();F;F=F->next()) {
+
+ PropertySetGet *psg=t->property_setget.getptr(F->get());
+
+ hash = hash_djb2_one_64( F->get().hash(), hash);
+ hash = hash_djb2_one_64( psg->setter.hash(), hash);
+ hash = hash_djb2_one_64( psg->getter.hash(), hash);
+
+ }
+ }
+
+ //property list
+ for (List<PropertyInfo>::Element *F=t->property_list.front();F;F=F->next()) {
+
+ hash = hash_djb2_one_64( F->get().name.hash(), hash);
+ hash = hash_djb2_one_64( F->get().type, hash);
+ hash = hash_djb2_one_64( F->get().hint, hash);
+ hash = hash_djb2_one_64( F->get().hint_string.hash(), hash);
+ hash = hash_djb2_one_64( F->get().usage, hash);
+ }
+
+
+ }
+
+
+ return hash;
+#else
+ return 0;
+#endif
+
+}
+
bool ObjectTypeDB::type_exists(const StringName &p_type) {
OBJTYPE_LOCK;
@@ -309,6 +482,7 @@ void ObjectTypeDB::_add_type2(const StringName& p_type, const StringName& p_inhe
TypeInfo &ti=types[name];
ti.name=name;
ti.inherits=p_inherits;
+ ti.api=current_api;
if (ti.inherits) {
@@ -866,21 +1040,14 @@ MethodBind* ObjectTypeDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind , c
Vector<Variant> defvals;
-#define PARSE_DEFVAL(m_defval)\
-if (d##m_defval.used) defvals.insert(0,d##m_defval.val);\
-else goto set_defvals;
-
defvals.resize(p_defcount);
for(int i=0;i<p_defcount;i++) {
defvals[i]=*p_defs[p_defcount-i-1];
}
- set_defvals:
-
p_bind->set_default_arguments(defvals);
p_bind->set_hint_flags(p_flags);
-#undef PARSE_DEFVAL
return p_bind;
}
diff --git a/core/object_type_db.h b/core/object_type_db.h
index 3fcd38aa31..9e9029ff2f 100644
--- a/core/object_type_db.h
+++ b/core/object_type_db.h
@@ -109,7 +109,13 @@ static _FORCE_INLINE_ const char* _MD(const char* m_name, ...) { return m_name;
#endif
class ObjectTypeDB {
-
+public:
+ enum APIType {
+ API_CORE,
+ API_EDITOR,
+ API_NONE
+ };
+public:
struct PropertySetGet {
int index;
@@ -122,6 +128,7 @@ class ObjectTypeDB {
struct TypeInfo {
+ APIType api;
TypeInfo *inherits_ptr;
HashMap<StringName,MethodBind*,StringNameHasher> method_map;
HashMap<StringName,int,StringNameHasher> constant_map;
@@ -161,6 +168,7 @@ class ObjectTypeDB {
#endif
+ static APIType current_api;
static void _add_type2(const StringName& p_type, const StringName& p_inherits);
public:
@@ -236,6 +244,9 @@ public:
static bool is_type(const StringName &p_type,const StringName& p_inherits);
static bool can_instance(const StringName &p_type);
static Object *instance(const StringName &p_type);
+ static APIType get_api_type(const StringName &p_type);
+
+ static uint64_t get_api_hash(APIType p_api);
#if 0
template<class N, class M>
@@ -415,13 +426,13 @@ public:
#endif
template<class M>
- static MethodBind* bind_native_method(uint32_t p_flags, StringName p_name, M p_method,const MethodInfo& p_info=MethodInfo(),const Vector<Variant>& p_default_args=Vector<Variant>()) {
+ static MethodBind* bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method,const MethodInfo& p_info=MethodInfo(),const Vector<Variant>& p_default_args=Vector<Variant>()) {
GLOBAL_LOCK_FUNCTION;
- MethodBind *bind = create_native_method_bind(p_method,p_info);
+ MethodBind *bind = create_vararg_method_bind(p_method,p_info);
ERR_FAIL_COND_V(!bind,NULL);
String rettype;
@@ -499,6 +510,8 @@ public:
static void add_compatibility_type(const StringName& p_type,const StringName& p_fallback);
static void init();
+
+ static void set_current_api(APIType p_api);
static void cleanup();
};
diff --git a/core/os/input.cpp b/core/os/input.cpp
index 531db73838..4ab57a84ea 100644
--- a/core/os/input.cpp
+++ b/core/os/input.cpp
@@ -53,6 +53,8 @@ void Input::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_mouse_button_pressed","button"),&Input::is_mouse_button_pressed);
ObjectTypeDB::bind_method(_MD("is_joy_button_pressed","device","button"),&Input::is_joy_button_pressed);
ObjectTypeDB::bind_method(_MD("is_action_pressed","action"),&Input::is_action_pressed);
+ ObjectTypeDB::bind_method(_MD("is_action_just_pressed","action"),&Input::is_action_just_pressed);
+ ObjectTypeDB::bind_method(_MD("is_action_just_released","action"),&Input::is_action_just_released);
ObjectTypeDB::bind_method(_MD("add_joy_mapping","mapping", "update_existing"),&Input::add_joy_mapping, DEFVAL(false));
ObjectTypeDB::bind_method(_MD("remove_joy_mapping","guid"),&Input::remove_joy_mapping);
ObjectTypeDB::bind_method(_MD("is_joy_known","device"),&Input::is_joy_known);
@@ -62,6 +64,10 @@ void Input::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_connected_joysticks"),&Input::get_connected_joysticks);
ObjectTypeDB::bind_method(_MD("get_joy_vibration_strength", "device"), &Input::get_joy_vibration_strength);
ObjectTypeDB::bind_method(_MD("get_joy_vibration_duration", "device"), &Input::get_joy_vibration_duration);
+ ObjectTypeDB::bind_method(_MD("get_joy_button_string", "button_index"), &Input::get_joy_button_string);
+ ObjectTypeDB::bind_method(_MD("get_joy_button_index_from_string", "button"), &Input::get_joy_button_index_from_string);
+ ObjectTypeDB::bind_method(_MD("get_joy_axis_string", "axis_index"), &Input::get_joy_axis_string);
+ ObjectTypeDB::bind_method(_MD("get_joy_axis_index_from_string", "axis"), &Input::get_joy_axis_index_from_string);
ObjectTypeDB::bind_method(_MD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &Input::start_joy_vibration, DEFVAL(0));
ObjectTypeDB::bind_method(_MD("stop_joy_vibration", "device"), &Input::stop_joy_vibration);
ObjectTypeDB::bind_method(_MD("get_accelerometer"),&Input::get_accelerometer);
@@ -88,7 +94,7 @@ void Input::get_argument_options(const StringName& p_function,int p_idx,List<Str
#ifdef TOOLS_ENABLED
String pf=p_function;
- if (p_idx==0 && (pf=="is_action_pressed" || pf=="action_press" || pf=="action_release")) {
+ if (p_idx==0 && (pf=="is_action_pressed" || pf=="action_press" || pf=="action_release" || pf=="is_action_just_pressed" || pf=="is_action_just_released")) {
List<PropertyInfo> pinfo;
Globals::get_singleton()->get_property_list(&pinfo);
diff --git a/core/os/input.h b/core/os/input.h
index 16bcc0ff9a..d8f3be09df 100644
--- a/core/os/input.h
+++ b/core/os/input.h
@@ -55,12 +55,14 @@ public:
static Input *get_singleton();
- virtual bool is_key_pressed(int p_scancode)=0;
- virtual bool is_mouse_button_pressed(int p_button)=0;
- virtual bool is_joy_button_pressed(int p_device, int p_button)=0;
- virtual bool is_action_pressed(const StringName& p_action)=0;
-
- virtual float get_joy_axis(int p_device,int p_axis)=0;
+ virtual bool is_key_pressed(int p_scancode) const=0;
+ virtual bool is_mouse_button_pressed(int p_button) const=0;
+ virtual bool is_joy_button_pressed(int p_device, int p_button) const=0;
+ virtual bool is_action_pressed(const StringName& p_action) const=0;
+ virtual bool is_action_just_pressed(const StringName& p_action) const=0;
+ virtual bool is_action_just_released(const StringName& p_action) const=0;
+
+ virtual float get_joy_axis(int p_device,int p_axis) const=0;
virtual String get_joy_name(int p_idx)=0;
virtual Array get_connected_joysticks()=0;
virtual void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid)=0;
@@ -80,9 +82,9 @@ public:
virtual void warp_mouse_pos(const Vector2& p_to)=0;
- virtual Vector3 get_accelerometer()=0;
- virtual Vector3 get_magnetometer()=0;
- virtual Vector3 get_gyroscope()=0;
+ virtual Vector3 get_accelerometer() const=0;
+ virtual Vector3 get_magnetometer() const=0;
+ virtual Vector3 get_gyroscope() const=0;
virtual void action_press(const StringName& p_action)=0;
virtual void action_release(const StringName& p_action)=0;
@@ -94,6 +96,11 @@ public:
virtual void set_custom_mouse_cursor(const RES& p_cursor,const Vector2& p_hotspot=Vector2())=0;
virtual void set_mouse_in_window(bool p_in_window)=0;
+ virtual String get_joy_button_string(int p_button)=0;
+ virtual String get_joy_axis_string(int p_axis)=0;
+ virtual int get_joy_button_index_from_string(String p_button)=0;
+ virtual int get_joy_axis_index_from_string(String p_axis)=0;
+
Input();
};
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index f4a6de0e96..9982767be1 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -39,6 +39,8 @@ bool InputEvent::operator==(const InputEvent &p_event) const {
}
switch(type) {
+ case NONE:
+ return true;
case KEY:
return key.unicode == p_event.key.unicode
&& key.scancode == p_event.key.scancode
@@ -77,6 +79,8 @@ bool InputEvent::operator==(const InputEvent &p_event) const {
case ACTION:
return action.action == p_event.action.action
&& action.pressed == p_event.action.pressed;
+ default:
+ ERR_PRINT("No logic to compare InputEvents of this type, this shouldn't happen.");
}
return false;
@@ -200,7 +204,7 @@ bool InputEvent::is_pressed() const {
case MOUSE_BUTTON: return mouse_button.pressed;
case JOYSTICK_BUTTON: return joy_button.pressed;
case SCREEN_TOUCH: return screen_touch.pressed;
- case JOYSTICK_MOTION: return InputMap::get_singleton()->event_is_joy_motion_action_pressed(*this);
+ case JOYSTICK_MOTION: return ABS(joy_motion.axis_value) > 0.5;
case ACTION: return action.pressed;
default: {}
}
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 5f86962048..ee32476234 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -587,6 +587,9 @@ OS::OS() {
_time_scale=1.0;
_pixel_snap=false;
_allow_hidpi=true;
+ _fixed_frames=0;
+ _idle_frames=0;
+ _in_fixed=false;
Math::seed(1234567);
}
diff --git a/core/os/os.h b/core/os/os.h
index 2521d67e29..c2b46a5420 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -62,6 +62,10 @@ class OS {
bool _pixel_snap;
bool _allow_hidpi;
+ uint64_t _fixed_frames;
+ uint64_t _idle_frames;
+ bool _in_fixed;
+
char *last_error;
public:
@@ -282,6 +286,10 @@ public:
uint64_t get_frames_drawn();
+ uint64_t get_fixed_frames() const { return _fixed_frames; }
+ uint64_t get_idle_frames() const { return _idle_frames; }
+ bool is_in_fixed_frame() const { return _in_fixed; }
+
bool is_stdout_verbose() const;
enum CursorShape {
@@ -364,6 +372,7 @@ public:
virtual void set_screen_orientation(ScreenOrientation p_orientation);
ScreenOrientation get_screen_orientation() const;
+ virtual void enable_for_stealing_focus(ProcessID pid) {}
virtual void move_window_to_foreground() {}
virtual void debug_break();
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 3de26573f4..c3a127afb9 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -33,6 +33,7 @@
#include "io/config_file.h"
#include "os/main_loop.h"
#include "io/packet_peer.h"
+#include "math/a_star.h"
#include "globals.h"
#include "object_type_db.h"
#include "geometry.h"
@@ -48,6 +49,7 @@
#include "os/input.h"
#include "core/io/xml_parser.h"
#include "io/http_client.h"
+#include "io/pck_packer.h"
#include "packed_data_container.h"
#include "func_ref.h"
#include "input_map.h"
@@ -145,8 +147,11 @@ void register_core_types() {
ObjectTypeDB::register_type<ConfigFile>();
+ ObjectTypeDB::register_type<PCKPacker>();
+
ObjectTypeDB::register_type<PackedDataContainer>();
ObjectTypeDB::register_virtual_type<PackedDataContainerRef>();
+ ObjectTypeDB::register_type<AStar>();
ip = IP::create();
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index 99d1e22c07..6d685d3c43 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -134,6 +134,8 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) {
ERR_FAIL();
}
+ OS::get_singleton()->enable_for_stealing_focus(Globals::get_singleton()->get("editor_pid"));
+
packet_peer_stream->put_var("debug_enter");
packet_peer_stream->put_var(2);
packet_peer_stream->put_var(p_can_continue);
@@ -219,7 +221,8 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) {
if (F->get().get_type()==Variant::OBJECT) {
packet_peer_stream->put_var("*"+E->get());
- packet_peer_stream->put_var(safe_get_instance_id(F->get()));
+ String pretty_print = F->get().operator String();
+ packet_peer_stream->put_var(pretty_print.ascii().get_data());
} else {
packet_peer_stream->put_var(E->get());
packet_peer_stream->put_var(F->get());
@@ -242,7 +245,8 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) {
if (F->get().get_type()==Variant::OBJECT) {
packet_peer_stream->put_var("*"+E->get());
- packet_peer_stream->put_var(safe_get_instance_id(F->get()));
+ String pretty_print = F->get().operator String();
+ packet_peer_stream->put_var(pretty_print.ascii().get_data());
} else {
packet_peer_stream->put_var(E->get());
packet_peer_stream->put_var(F->get());
@@ -271,6 +275,7 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) {
set_depth(-1);
set_lines_left(-1);
+ OS::get_singleton()->move_window_to_foreground();
break;
} else if (command=="break") {
ERR_PRINT("Got break when already broke!");
diff --git a/core/script_language.h b/core/script_language.h
index 1b037e908c..53af4c74d1 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -122,6 +122,7 @@ public:
virtual void get_script_method_list(List<MethodInfo> *p_list) const=0;
virtual void get_script_property_list(List<PropertyInfo> *p_list) const=0;
+ virtual int get_member_line(const StringName& p_member) const { return 0; }
Script() {}
};
@@ -207,7 +208,26 @@ public:
virtual bool has_named_classes() const=0;
virtual int find_function(const String& p_function,const String& p_code) const=0;
virtual String make_function(const String& p_class,const String& p_name,const StringArray& p_args) const=0;
+
virtual Error complete_code(const String& p_code, const String& p_base_path, Object*p_owner,List<String>* r_options,String& r_call_hint) { return ERR_UNAVAILABLE; }
+
+ struct LookupResult {
+ enum Type {
+ RESULT_SCRIPT_LOCATION,
+ RESULT_CLASS,
+ RESULT_CLASS_CONSTANT,
+ RESULT_CLASS_PROPERTY,
+ RESULT_CLASS_METHOD
+ };
+ Type type;
+ Ref<Script> script;
+ String class_name;
+ String class_member;
+ int location;
+ };
+
+ virtual Error lookup_code(const String& p_code, const String& p_symbol,const String& p_base_path, Object*p_owner,LookupResult& r_result) { return ERR_UNAVAILABLE; }
+
virtual void auto_indent_code(String& p_code,int p_from_line,int p_to_line) const=0;
virtual void add_global_constant(const StringName& p_variable,const Variant& p_value)=0;
diff --git a/core/translation.cpp b/core/translation.cpp
index 01789747ea..4592d00598 100644
--- a/core/translation.cpp
+++ b/core/translation.cpp
@@ -32,11 +32,23 @@
#include "os/os.h"
static const char* locale_list[]={
+"aa", // Afar
+"aa_DJ", // Afar (Djibouti)
+"aa_ER", // Afar (Eritrea)
+"aa_ET", // Afar (Ethiopia)
+"af", // Afrikaans
+"af_ZA", // Afrikaans (South Africa)
+"agr_PE", // Aguaruna (Peru)
+"ak_GH", // Akan (Ghana)
+"am_ET", // Amharic (Ethiopia)
+"an_ES", // Aragonese (Spain)
+"anp_IN", // Angika (India)
"ar", // Arabic
"ar_AE", // Arabic (United Arab Emirates)
"ar_BH", // Arabic (Bahrain)
"ar_DZ", // Arabic (Algeria)
"ar_EG", // Arabic (Egypt)
+"ar_IN", // Arabic (India)
"ar_IQ", // Arabic (Iraq)
"ar_JO", // Arabic (Jordan)
"ar_KW", // Arabic (Kuwait)
@@ -47,48 +59,91 @@ static const char* locale_list[]={
"ar_QA", // Arabic (Qatar)
"ar_SA", // Arabic (Saudi Arabia)
"ar_SD", // Arabic (Sudan)
+"ar_SS", // Arabic (South Soudan)
"ar_SY", // Arabic (Syria)
"ar_TN", // Arabic (Tunisia)
"ar_YE", // Arabic (Yemen)
+"as_IN", // Assamese (India)
+"ast_ES", // Asturian (Spain)
+"ayc_PE", // Southern Aymara (Peru)
+"ay_PE", // Aymara (Peru)
+"az_AZ", // Azerbaijani (Azerbaijan)
"be", // Belarusian
"be_BY", // Belarusian (Belarus)
+"bem_ZM", // Bemba (Zambia)
+"ber_DZ", // Berber languages (Algeria)
+"ber_MA", // Berber languages (Morocco)
"bg", // Bulgarian
"bg_BG", // Bulgarian (Bulgaria)
+"bhb_IN", // Bhili (India)
+"bho_IN", // Bhojpuri (India)
+"bi_TV", // Bislama (Tuvalu)
"bn", // Bengali
"bn_BD", // Bengali (Bangladesh)
"bn_IN", // Bengali (India)
+"bo", // Tibetan
+"bo_CN", // Tibetan (China)
+"bo_IN", // Tibetan (India)
+"br_FR", // Breton (France)
+"brx_IN", // Bodo (India)
+"bs_BA", // Bosnian (Bosnia and Herzegovina)
+"byn_ER", // Bilin (Eritrea)
"ca", // Catalan
+"ca_AD", // Catalan (Andorra)
"ca_ES", // Catalan (Spain)
+"ca_FR", // Catalan (France)
+"ca_IT", // Catalan (Italy)
+"ce_RU", // Chechen (Russia)
+"chr_US", // Cherokee (United States)
+"cmn_TW", // Mandarin Chinese (Taiwan)
+"crh_UA", // Crimean Tatar (Ukraine)
+"csb_PL", // Kashubian (Poland)
"cs", // Czech
"cs_CZ", // Czech (Czech Republic)
+"cv_RU", // Chuvash (Russia)
+"cy_GB", // Welsh (United Kingdom)
"da", // Danish
"da_DK", // Danish (Denmark)
"de", // German
"de_AT", // German (Austria)
+"de_BE", // German (Belgium)
"de_CH", // German (Switzerland)
"de_DE", // German (Germany)
+"de_IT", // German (Italy)
"de_LU", // German (Luxembourg)
+"doi_IN", // Dogri (India)
+"dv_MV", // Dhivehi (Maldives)
+"dz_BT", // Dzongkha (Bhutan)
"el", // Greek
"el_CY", // Greek (Cyprus)
"el_GR", // Greek (Greece)
"en", // English
+"en_AG", // English (Antigua and Barbuda)
"en_AU", // English (Australia)
+"en_BW", // English (Botswana)
"en_CA", // English (Canada)
+"en_DK", // English (Denmark)
"en_GB", // English (United Kingdom)
+"en_HK", // English (Hong Kong)
"en_IE", // English (Ireland)
+"en_IL", // English (Israel)
"en_IN", // English (India)
-"en_MT", // English (Malta)
+"en_NG", // English (Nigeria)
"en_NZ", // English (New Zealand)
"en_PH", // English (Philippines)
"en_SG", // English (Singapore)
"en_US", // English (United States)
"en_ZA", // English (South Africa)
+"en_ZM", // English (Zambia)
+"en_ZW", // English (Zimbabwe)
+"eo", // Esperanto
"es", // Spanish
"es_AR", // Spanish (Argentina)
"es_BO", // Spanish (Bolivia)
"es_CL", // Spanish (Chile)
"es_CO", // Spanish (Colombia)
"es_CR", // Spanish (Costa Rica)
+"es_CU", // Spanish (Cuba)
"es_DO", // Spanish (Dominican Republic)
"es_EC", // Spanish (Ecuador)
"es_ES", // Spanish (Spain)
@@ -106,100 +161,252 @@ static const char* locale_list[]={
"es_VE", // Spanish (Venezuela)
"et", // Estonian
"et_EE", // Estonian (Estonia)
+"eu", // Basque
+"eu_ES", // Basque (Spain)
+"fa", // Persian
+"fa_IR", // Persian (Iran)
+"ff_SN", // Fulah (Senegal)
"fi", // Finnish
"fi_FI", // Finnish (Finland)
+"fil_PH", // Filipino (Philippines)
+"fo_FO", // Faroese (Faroe Islands)
"fr", // French
"fr_BE", // French (Belgium)
"fr_CA", // French (Canada)
"fr_CH", // French (Switzerland)
"fr_FR", // French (France)
"fr_LU", // French (Luxembourg)
+"fur_IT", // Friulian (Italy)
+"fy_DE", // Western Frisian (Germany)
+"fy_NL", // Western Frisian (Netherlands)
"ga", // Irish
"ga_IE", // Irish (Ireland)
-"hi", // Hindi (India)
+"gd_GB", // Scottish Gaelic (United Kingdom)
+"gez_ER", // Geez (Eritrea)
+"gez_ET", // Geez (Ethiopia)
+"gl_ES", // Galician (Spain)
+"gu_IN", // Gujarati (India)
+"gv_GB", // Manx (United Kingdom)
+"hak_TW", // Hakka Chinese (Taiwan)
+"ha_NG", // Hausa (Nigeria)
+"he", // Hebrew
+"he_IL", // Hebrew (Israel)
+"hi", // Hindi
"hi_IN", // Hindi (India)
+"hne_IN", // Chhattisgarhi (India)
"hr", // Croatian
"hr_HR", // Croatian (Croatia)
+"hsb_DE", // Upper Sorbian (Germany)
+"ht_HT", // Haitian (Haiti)
"hu", // Hungarian
"hu_HU", // Hungarian (Hungary)
-"in", // Indonesian
-"in_ID", // Indonesian (Indonesia)
+"hus_MX", // Huastec (Mexico)
+"hy_AM", // Armenian (Armenia)
+"ia_FR", // Interlingua (France)
+"id", // Indonesian
+"id_ID", // Indonesian (Indonesia)
+"ig_NG", // Igbo (Nigeria)
+"ik_CA", // Inupiaq (Canada)
"is", // Icelandic
"is_IS", // Icelandic (Iceland)
"it", // Italian
"it_CH", // Italian (Switzerland)
"it_IT", // Italian (Italy)
-"iw", // Hebrew
-"iw_IL", // Hebrew (Israel)
+"iu_CA", // Inuktitut (Canada)
"ja", // Japanese
"ja_JP", // Japanese (Japan)
-"ja_JP_JP", // Japanese (Japan,JP)
+"kab_DZ", // Kabyle (Algeria)
+"ka_GE", // Georgian (Georgia)
+"kk_KZ", // Kazakh (Kazakhstan)
+"kl_GL", // Kalaallisut (Greenland)
+"km_KH", // Central Khmer (Cambodia)
+"kn_IN", // Kannada (India)
+"kok_IN", // Konkani (India)
"ko", // Korean
"ko_KR", // Korean (South Korea)
+"ks_IN", // Kashmiri (India)
+"ku", // Kurdish
+"ku_TR", // Kurdish (Turkey)
+"kw_GB", // Cornish (United Kingdom)
+"ky_KG", // Kirghiz (Kyrgyzstan)
+"lb_LU", // Luxembourgish (Luxembourg)
+"lg_UG", // Ganda (Uganda)
+"li_BE", // Limburgan (Belgium)
+"li_NL", // Limburgan (Netherlands)
+"lij_IT", // Ligurian (Italy)
+"ln_CD", // Lingala (Congo)
+"lo_LA", // Lao (Laos)
"lt", // Lithuanian
"lt_LT", // Lithuanian (Lithuania)
"lv", // Latvian
"lv_LV", // Latvian (Latvia)
+"lzh_TW", // Literary Chinese (Taiwan)
+"mag_IN", // Magahi (India)
+"mai_IN", // Maithili (India)
+"mg_MG", // Malagasy (Madagascar)
+"mh_MH", // Marshallese (Marshall Islands)
+"mhr_RU", // Eastern Mari (Russia)
+"mi_NZ", // Maori (New Zealand)
+"miq_NI", // Mískito (Nicaragua)
"mk", // Macedonian
"mk_MK", // Macedonian (Macedonia)
+"ml_IN", // Malayalam (India)
+"mni_IN", // Manipuri (India)
+"mn_MN", // Mongolian (Mongolia)
+"mr_IN", // Marathi (India)
"ms", // Malay
"ms_MY", // Malay (Malaysia)
"mt", // Maltese
"mt_MT", // Maltese (Malta)
+"my_MM", // Burmese (Myanmar)
+"myv_RU", // Erzya (Russia)
+"nah_MX", // Nahuatl languages (Mexico)
+"nan_TW", // Min Nan Chinese (Taiwan)
+"nb", // Norwegian Bokmål
+"nb_NO", // Norwegian Bokmål (Norway)
+"nds_DE", // Low German (Germany)
+"nds_NL", // Low German (Netherlands)
+"ne_NP", // Nepali (Nepal)
+"nhn_MX", // Central Nahuatl (Mexico)
+"niu_NU", // Niuean (Niue)
+"niu_NZ", // Niuean (New Zealand)
"nl", // Dutch
+"nl_AW", // Dutch (Aruba)
"nl_BE", // Dutch (Belgium)
"nl_NL", // Dutch (Netherlands)
-"no", // Norwegian
-"no_NO", // Norwegian (Norway)
-"no_NO_NY", // Norwegian (Norway,Nynorsk)
+"nn", // Norwegian Nynorsk
+"nn_NO", // Norwegian Nynorsk (Norway)
+"nr_ZA", // South Ndebele (South Africa)
+"nso_ZA", // Pedi (South Africa)
+"oc_FR", // Occitan (France)
+"om", // Oromo
+"om_ET", // Oromo (Ethiopia)
+"om_KE", // Oromo (Kenya)
+"or_IN", // Oriya (India)
+"os_RU", // Ossetian (Russia)
+"pa_IN", // Panjabi (India)
+"pap", // Papiamento
+"pap_AN", // Papiamento (Netherlands Antilles)
+"pap_AW", // Papiamento (Aruba)
+"pap_CW", // Papiamento (Curaçao)
+"pa_PK", // Panjabi (Pakistan)
"pl", // Polish
"pl_PL", // Polish (Poland)
+"ps_AF", // Pushto (Afghanistan)
"pt", // Portuguese
"pt_BR", // Portuguese (Brazil)
"pt_PT", // Portuguese (Portugal)
+"quy_PE", // Ayacucho Quechua (Peru)
+"quz_PE", // Cusco Quechua (Peru)
+"raj_IN", // Rajasthani (India)
"ro", // Romanian
"ro_RO", // Romanian (Romania)
"ru", // Russian
"ru_RU", // Russian (Russia)
+"ru_UA", // Russian (Ukraine)
+"rw_RW", // Kinyarwanda (Rwanda)
+"sa_IN", // Sanskrit (India)
+"sat_IN", // Santali (India)
+"sc_IT", // Sardinian (Italy)
+"sd_IN", // Sindhi (India)
+"se_NO", // Northern Sami (Norway)
+"sgs_LT", // Samogitian (Lithuania)
+"shs_CA", // Shuswap (Canada)
+"sid_ET", // Sidamo (Ethiopia)
+"si_LK", // Sinhala (Sri Lanka)
"sk", // Slovak
"sk_SK", // Slovak (Slovakia)
"sl", // Slovenian
"sl_SI", // Slovenian (Slovenia)
+"so", // Somali
+"so_DJ", // Somali (Djibouti)
+"so_ET", // Somali (Ethiopia)
+"so_KE", // Somali (Kenya)
+"so_SO", // Somali (Somalia)
+"son_ML", // Songhai languages (Mali)
"sq", // Albanian
"sq_AL", // Albanian (Albania)
+"sq_KV", // Albanian (Kosovo)
+"sq_MK", // Albanian (Macedonia)
"sr", // Serbian
-"sr_BA", // Serbian (Bosnia and Herzegovina)
-"sr_CS", // Serbian (Serbia and Montenegro)
"sr_ME", // Serbian (Montenegro)
"sr_RS", // Serbian (Serbia)
+"ss_ZA", // Swati (South Africa)
+"st_ZA", // Southern Sotho (South Africa)
"sv", // Swedish
+"sv_FI", // Swedish (Finland)
"sv_SE", // Swedish (Sweden)
+"sw_KE", // Swahili (Kenya)
+"sw_TZ", // Swahili (Tanzania)
+"szl_PL", // Silesian (Poland)
+"ta", // Tamil
+"ta_IN", // Tamil (India)
+"ta_LK", // Tamil (Sri Lanka)
+"tcy_IN", // Tulu (India)
+"te_IN", // Telugu (India)
+"tg_TJ", // Tajik (Tajikistan)
+"the_NP", // Chitwania Tharu (Nepal)
"th", // Thai
"th_TH", // Thai (Thailand)
-"th_TH_TH", // Thai (Thailand,TH)
+"ti", // Tigrinya
+"ti_ER", // Tigrinya (Eritrea)
+"ti_ET", // Tigrinya (Ethiopia)
+"tig_ER", // Tigre (Eritrea)
+"tk_TM", // Turkmen (Turkmenistan)
+"tl_PH", // Tagalog (Philippines)
+"tn_ZA", // Tswana (South Africa)
"tr", // Turkish
+"tr_CY", // Turkish (Cyprus)
"tr_TR", // Turkish (Turkey)
+"ts_ZA", // Tsonga (South Africa)
+"tt_RU", // Tatar (Russia)
+"ug_CN", // Uighur (China)
"uk", // Ukrainian
"uk_UA", // Ukrainian (Ukraine)
+"unm_US", // Unami (United States)
"ur", // Urdu
"ur_IN", // Urdu (India)
"ur_PK", // Urdu (Pakistan)
+"uz", // Uzbek
+"uz_UZ", // Uzbek (Uzbekistan)
+"ve_ZA", // Venda (South Africa)
"vi", // Vietnamese
"vi_VN", // Vietnamese (Vietnam)
+"wa_BE", // Walloon (Belgium)
+"wae_CH", // Walser (Switzerland)
+"wal_ET", // Wolaytta (Ethiopia)
+"wo_SN", // Wolof (Senegal)
+"xh_ZA", // Xhosa (South Africa)
+"yi_US", // Yiddish (United States)
+"yo_NG", // Yoruba (Nigeria)
+"yue_HK", // Yue Chinese (Hong Kong)
"zh", // Chinese
"zh_CN", // Chinese (China)
"zh_HK", // Chinese (Hong Kong)
"zh_SG", // Chinese (Singapore)
"zh_TW", // Chinese (Taiwan)
+"zu_ZA", // Zulu (South Africa)
0
};
static const char* locale_names[]={
+"Afar",
+"Afar (Djibouti)",
+"Afar (Eritrea)",
+"Afar (Ethiopia)",
+"Afrikaans",
+"Afrikaans (South Africa)",
+"Aguaruna (Peru)",
+"Akan (Ghana)",
+"Amharic (Ethiopia)",
+"Aragonese (Spain)",
+"Angika (India)",
"Arabic",
"Arabic (United Arab Emirates)",
"Arabic (Bahrain)",
"Arabic (Algeria)",
"Arabic (Egypt)",
+"Arabic (India)",
"Arabic (Iraq)",
"Arabic (Jordan)",
"Arabic (Kuwait)",
@@ -210,48 +417,91 @@ static const char* locale_names[]={
"Arabic (Qatar)",
"Arabic (Saudi Arabia)",
"Arabic (Sudan)",
+"Arabic (South Soudan)",
"Arabic (Syria)",
"Arabic (Tunisia)",
"Arabic (Yemen)",
+"Assamese (India)",
+"Asturian (Spain)",
+"Southern Aymara (Peru)",
+"Aymara (Peru)",
+"Azerbaijani (Azerbaijan)",
"Belarusian",
"Belarusian (Belarus)",
+"Bemba (Zambia)",
+"Berber languages (Algeria)",
+"Berber languages (Morocco)",
"Bulgarian",
"Bulgarian (Bulgaria)",
+"Bhili (India)",
+"Bhojpuri (India)",
+"Bislama (Tuvalu)",
"Bengali",
"Bengali (Bangladesh)",
"Bengali (India)",
+"Tibetan",
+"Tibetan (China)",
+"Tibetan (India)",
+"Breton (France)",
+"Bodo (India)",
+"Bosnian (Bosnia and Herzegovina)",
+"Bilin (Eritrea)",
"Catalan",
+"Catalan (Andorra)",
"Catalan (Spain)",
+"Catalan (France)",
+"Catalan (Italy)",
+"Chechen (Russia)",
+"Cherokee (United States)",
+"Mandarin Chinese (Taiwan)",
+"Crimean Tatar (Ukraine)",
+"Kashubian (Poland)",
"Czech",
"Czech (Czech Republic)",
+"Chuvash (Russia)",
+"Welsh (United Kingdom)",
"Danish",
"Danish (Denmark)",
"German",
"German (Austria)",
+"German (Belgium)",
"German (Switzerland)",
"German (Germany)",
+"German (Italy)",
"German (Luxembourg)",
+"Dogri (India)",
+"Dhivehi (Maldives)",
+"Dzongkha (Bhutan)",
"Greek",
"Greek (Cyprus)",
"Greek (Greece)",
"English",
+"English (Antigua and Barbuda)",
"English (Australia)",
+"English (Botswana)",
"English (Canada)",
+"English (Denmark)",
"English (United Kingdom)",
+"English (Hong Kong)",
"English (Ireland)",
+"English (Israel)",
"English (India)",
-"English (Malta)",
+"English (Nigeria)",
"English (New Zealand)",
"English (Philippines)",
"English (Singapore)",
"English (United States)",
"English (South Africa)",
+"English (Zambia)",
+"English (Zimbabwe)",
+"Esperanto",
"Spanish",
"Spanish (Argentina)",
"Spanish (Bolivia)",
"Spanish (Chile)",
"Spanish (Colombia)",
"Spanish (Costa Rica)",
+"Spanish (Cuba)",
"Spanish (Dominican Republic)",
"Spanish (Ecuador)",
"Spanish (Spain)",
@@ -269,91 +519,231 @@ static const char* locale_names[]={
"Spanish (Venezuela)",
"Estonian",
"Estonian (Estonia)",
+"Basque",
+"Basque (Spain)",
+"Persian",
+"Persian (Iran)",
+"Fulah (Senegal)",
"Finnish",
"Finnish (Finland)",
+"Filipino (Philippines)",
+"Faroese (Faroe Islands)",
"French",
"French (Belgium)",
"French (Canada)",
"French (Switzerland)",
"French (France)",
"French (Luxembourg)",
+"Friulian (Italy)",
+"Western Frisian (Germany)",
+"Western Frisian (Netherlands)",
"Irish",
"Irish (Ireland)",
+"Scottish Gaelic (United Kingdom)",
+"Geez (Eritrea)",
+"Geez (Ethiopia)",
+"Galician (Spain)",
+"Gujarati (India)",
+"Manx (United Kingdom)",
+"Hakka Chinese (Taiwan)",
+"Hausa (Nigeria)",
+"Hebrew",
+"Hebrew (Israel)",
+"Hindi",
"Hindi (India)",
-"Hindi (India)",
+"Chhattisgarhi (India)",
"Croatian",
"Croatian (Croatia)",
+"Upper Sorbian (Germany)",
+"Haitian (Haiti)",
"Hungarian",
"Hungarian (Hungary)",
+"Huastec (Mexico)",
+"Armenian (Armenia)",
+"Interlingua (France)",
"Indonesian",
"Indonesian (Indonesia)",
+"Igbo (Nigeria)",
+"Inupiaq (Canada)",
"Icelandic",
"Icelandic (Iceland)",
"Italian",
"Italian (Switzerland)",
"Italian (Italy)",
-"Hebrew",
-"Hebrew (Israel)",
+"Inuktitut (Canada)",
"Japanese",
"Japanese (Japan)",
-"Japanese (Japan JP)",
+"Kabyle (Algeria)",
+"Georgian (Georgia)",
+"Kazakh (Kazakhstan)",
+"Kalaallisut (Greenland)",
+"Central Khmer (Cambodia)",
+"Kannada (India)",
+"Konkani (India)",
"Korean",
"Korean (South Korea)",
+"Kashmiri (India)",
+"Kurdish",
+"Kurdish (Turkey)",
+"Cornish (United Kingdom)",
+"Kirghiz (Kyrgyzstan)",
+"Luxembourgish (Luxembourg)",
+"Ganda (Uganda)",
+"Limburgan (Belgium)",
+"Limburgan (Netherlands)",
+"Ligurian (Italy)",
+"Lingala (Congo)",
+"Lao (Laos)",
"Lithuanian",
"Lithuanian (Lithuania)",
"Latvian",
"Latvian (Latvia)",
+"Literary Chinese (Taiwan)",
+"Magahi (India)",
+"Maithili (India)",
+"Malagasy (Madagascar)",
+"Marshallese (Marshall Islands)",
+"Eastern Mari (Russia)",
+"Maori (New Zealand)",
+"Mískito (Nicaragua)",
"Macedonian",
"Macedonian (Macedonia)",
+"Malayalam (India)",
+"Manipuri (India)",
+"Mongolian (Mongolia)",
+"Marathi (India)",
"Malay",
"Malay (Malaysia)",
"Maltese",
"Maltese (Malta)",
+"Burmese (Myanmar)",
+"Erzya (Russia)",
+"Nahuatl languages (Mexico)",
+"Min Nan Chinese (Taiwan)",
+"Norwegian Bokmål",
+"Norwegian Bokmål (Norway)",
+"Low German (Germany)",
+"Low German (Netherlands)",
+"Nepali (Nepal)",
+"Central Nahuatl (Mexico)",
+"Niuean (Niue)",
+"Niuean (New Zealand)",
"Dutch",
+"Dutch (Aruba)",
"Dutch (Belgium)",
"Dutch (Netherlands)",
-"Norwegian",
-"Norwegian (Norway)",
-"Norwegian (Norway Nynorsk)",
+"Norwegian Nynorsk",
+"Norwegian Nynorsk (Norway)",
+"South Ndebele (South Africa)",
+"Pedi (South Africa)",
+"Occitan (France)",
+"Oromo",
+"Oromo (Ethiopia)",
+"Oromo (Kenya)",
+"Oriya (India)",
+"Ossetian (Russia)",
+"Panjabi (India)",
+"Papiamento",
+"Papiamento (Netherlands Antilles)",
+"Papiamento (Aruba)",
+"Papiamento (Curaçao)",
+"Panjabi (Pakistan)",
"Polish",
"Polish (Poland)",
+"Pushto (Afghanistan)",
"Portuguese",
"Portuguese (Brazil)",
"Portuguese (Portugal)",
+"Ayacucho Quechua (Peru)",
+"Cusco Quechua (Peru)",
+"Rajasthani (India)",
"Romanian",
"Romanian (Romania)",
"Russian",
"Russian (Russia)",
+"Russian (Ukraine)",
+"Kinyarwanda (Rwanda)",
+"Sanskrit (India)",
+"Santali (India)",
+"Sardinian (Italy)",
+"Sindhi (India)",
+"Northern Sami (Norway)",
+"Samogitian (Lithuania)",
+"Shuswap (Canada)",
+"Sidamo (Ethiopia)",
+"Sinhala (Sri Lanka)",
"Slovak",
"Slovak (Slovakia)",
"Slovenian",
"Slovenian (Slovenia)",
+"Somali",
+"Somali (Djibouti)",
+"Somali (Ethiopia)",
+"Somali (Kenya)",
+"Somali (Somalia)",
+"Songhai languages (Mali)",
"Albanian",
"Albanian (Albania)",
+"Albanian (Kosovo)",
+"Albanian (Macedonia)",
"Serbian",
-"Serbian (Bosnia and Herzegovina)",
-"Serbian (Serbia and Montenegro)",
"Serbian (Montenegro)",
"Serbian (Serbia)",
+"Swati (South Africa)",
+"Southern Sotho (South Africa)",
"Swedish",
+"Swedish (Finland)",
"Swedish (Sweden)",
+"Swahili (Kenya)",
+"Swahili (Tanzania)",
+"Silesian (Poland)",
+"Tamil",
+"Tamil (India)",
+"Tamil (Sri Lanka)",
+"Tulu (India)",
+"Telugu (India)",
+"Tajik (Tajikistan)",
+"Chitwania Tharu (Nepal)",
"Thai",
"Thai (Thailand)",
-"Thai (Thailand TH)",
+"Tigrinya",
+"Tigrinya (Eritrea)",
+"Tigrinya (Ethiopia)",
+"Tigre (Eritrea)",
+"Turkmen (Turkmenistan)",
+"Tagalog (Philippines)",
+"Tswana (South Africa)",
"Turkish",
+"Turkish (Cyprus)",
"Turkish (Turkey)",
+"Tsonga (South Africa)",
+"Tatar (Russia)",
+"Uighur (China)",
"Ukrainian",
"Ukrainian (Ukraine)",
+"Unami (United States)",
"Urdu",
"Urdu (India)",
"Urdu (Pakistan)",
+"Uzbek",
+"Uzbek (Uzbekistan)",
+"Venda (South Africa)",
"Vietnamese",
"Vietnamese (Vietnam)",
+"Walloon (Belgium)",
+"Walser (Switzerland)",
+"Wolaytta (Ethiopia)",
+"Wolof (Senegal)",
+"Xhosa (South Africa)",
+"Yiddish (United States)",
+"Yoruba (Nigeria)",
+"Yue Chinese (Hong Kong)",
"Chinese",
"Chinese (China)",
"Chinese (Hong Kong)",
"Chinese (Singapore)",
"Chinese (Taiwan)",
+"Zulu (South Africa)",
0
};
diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp
index 99740b365c..e8a71d4991 100644
--- a/core/undo_redo.cpp
+++ b/core/undo_redo.cpp
@@ -490,13 +490,9 @@ void UndoRedo::_bind_methods() {
mi.name="add_do_method";
mi.arguments.push_back( PropertyInfo( Variant::OBJECT, "object"));
mi.arguments.push_back( PropertyInfo( Variant::STRING, "method"));
- Vector<Variant> defargs;
- for(int i=0;i<VARIANT_ARG_MAX;++i) {
- mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
- defargs.push_back(Variant());
- }
- ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"add_do_method",&UndoRedo::_add_do_method,mi,defargs);
+
+ ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"add_do_method",&UndoRedo::_add_do_method,mi);
}
{
@@ -504,13 +500,9 @@ void UndoRedo::_bind_methods() {
mi.name="add_undo_method";
mi.arguments.push_back( PropertyInfo( Variant::OBJECT, "object"));
mi.arguments.push_back( PropertyInfo( Variant::STRING, "method"));
- Vector<Variant> defargs;
- for(int i=0;i<VARIANT_ARG_MAX;++i) {
- mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
- defargs.push_back(Variant());
- }
- ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"add_undo_method",&UndoRedo::_add_undo_method,mi,defargs);
+
+ ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"add_undo_method",&UndoRedo::_add_undo_method,mi);
}
ObjectTypeDB::bind_method(_MD("add_do_property","object", "property", "value:Variant"),&UndoRedo::add_do_property);
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 0d887210c3..2e907381f7 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -3073,6 +3073,11 @@ String String::simplify_path() const {
}
s =s.replace("\\","/");
+ while(true){ // in case of using 2 or more slash
+ String compare = s.replace("//","/");
+ if (s==compare) break;
+ else s=compare;
+ }
Vector<String> dirs = s.split("/",false);
for(int i=0;i<dirs.size();i++) {
@@ -3173,7 +3178,7 @@ bool String::is_valid_identifier() const {
//kind of poor should be rewritten properly
-String String::world_wrap(int p_chars_per_line) const {
+String String::word_wrap(int p_chars_per_line) const {
int from=0;
int last_space=0;
diff --git a/core/ustring.h b/core/ustring.h
index bb57b11d88..09d13a9e64 100644
--- a/core/ustring.h
+++ b/core/ustring.h
@@ -218,7 +218,7 @@ public:
String c_escape() const;
String c_unescape() const;
String json_escape() const;
- String world_wrap(int p_chars_per_line) const;
+ String word_wrap(int p_chars_per_line) const;
String percent_encode() const;
String percent_decode() const;
diff --git a/core/variant.cpp b/core/variant.cpp
index a78c07d819..b2afc9d080 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -429,6 +429,7 @@ bool Variant::can_convert(Variant::Type p_type_from,Variant::Type p_type_to) {
return true;
i++;
}
+
} else if (invalid_types) {
@@ -439,6 +440,8 @@ bool Variant::can_convert(Variant::Type p_type_from,Variant::Type p_type_to) {
return false;
i++;
}
+
+ return true;
}
return false;
@@ -457,7 +460,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from,Variant::Type p_type_
};
const Type *valid_types=NULL;
- const Type *invalid_types=NULL;
switch(p_type_to) {
case BOOL: {
@@ -679,16 +681,6 @@ bool Variant::can_convert_strict(Variant::Type p_type_from,Variant::Type p_type_
return true;
i++;
}
- } else if (invalid_types) {
-
-
- int i=0;
- while(invalid_types[i]!=NIL) {
-
- if (p_type_from==invalid_types[i])
- return false;
- i++;
- }
}
return false;
diff --git a/core/variant.h b/core/variant.h
index b8b028a760..90be593bd9 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -426,7 +426,7 @@ public:
static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list);
static void get_numeric_constants_for_type(Variant::Type p_type, List<StringName> *p_constants);
static bool has_numeric_constant(Variant::Type p_type, const StringName& p_value);
- static int get_numeric_constant_value(Variant::Type p_type, const StringName& p_value);
+ static int get_numeric_constant_value(Variant::Type p_type, const StringName& p_value,bool *r_valid=NULL);
typedef String (*ObjectDeConstruct)(const Variant& p_object,void *ud);
typedef void (*ObjectConstruct)(const String& p_text,void *ud,Variant& r_value);
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 069c20bc6e..51cd4c2399 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -54,10 +54,10 @@ struct _VariantCall {
int arg_count;
Vector<Variant> default_args;
Vector<Variant::Type> arg_types;
-
-#ifdef DEBUG_ENABLED
Vector<StringName> arg_names;
Variant::Type return_type;
+
+#ifdef DEBUG_ENABLED
bool returns;
#endif
VariantFunc func;
@@ -346,6 +346,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM0R(Vector2,angle);
// VCALL_LOCALMEM1R(Vector2,cross);
VCALL_LOCALMEM0R(Vector2,abs);
+ VCALL_LOCALMEM1R(Vector2,clamped);
VCALL_LOCALMEM0R(Rect2,get_area);
VCALL_LOCALMEM1R(Rect2,intersects);
@@ -374,6 +375,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM0R(Vector3, ceil);
VCALL_LOCALMEM1R(Vector3, distance_to);
VCALL_LOCALMEM1R(Vector3, distance_squared_to);
+ VCALL_LOCALMEM1R(Vector3, angle_to);
VCALL_LOCALMEM1R(Vector3, slide);
VCALL_LOCALMEM1R(Vector3, reflect);
@@ -464,8 +466,8 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM0R(Array,hash);
VCALL_LOCALMEM1(Array,push_back);
VCALL_LOCALMEM1(Array,push_front);
- VCALL_LOCALMEM0(Array,pop_back);
- VCALL_LOCALMEM0(Array,pop_front);
+ VCALL_LOCALMEM0R(Array,pop_back);
+ VCALL_LOCALMEM0R(Array,pop_front);
VCALL_LOCALMEM1(Array,append);
VCALL_LOCALMEM1(Array,resize);
VCALL_LOCALMEM2(Array,insert);
@@ -518,6 +520,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM1(ByteArray,append);
VCALL_LOCALMEM1(ByteArray,append_array);
VCALL_LOCALMEM0(ByteArray,invert);
+ VCALL_LOCALMEM2R(ByteArray,subarray);
VCALL_LOCALMEM0R(IntArray,size);
VCALL_LOCALMEM2(IntArray,set);
@@ -1324,14 +1327,22 @@ bool Variant::has_numeric_constant(Variant::Type p_type, const StringName& p_val
return cd.value.has(p_value);
}
-int Variant::get_numeric_constant_value(Variant::Type p_type, const StringName& p_value) {
+int Variant::get_numeric_constant_value(Variant::Type p_type, const StringName& p_value, bool *r_valid) {
+
+ if (r_valid)
+ *r_valid=false;
ERR_FAIL_INDEX_V(p_type,Variant::VARIANT_MAX,0);
_VariantCall::ConstantData& cd = _VariantCall::constant_data[p_type];
Map<StringName,int>::Element *E = cd.value.find(p_value);
- ERR_FAIL_COND_V(!E,0);
+ if (!E) {
+ return -1;
+ }
+ if (r_valid)
+ *r_valid=true;
+
return E->get();
}
@@ -1448,6 +1459,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC1(VECTOR2,VECTOR2,Vector2,reflect,VECTOR2,"vec",varray());
//ADDFUNC1(VECTOR2,REAL,Vector2,cross,VECTOR2,"with",varray());
ADDFUNC0(VECTOR2,VECTOR2,Vector2,abs,varray());
+ ADDFUNC1(VECTOR2,VECTOR2,Vector2,clamped,REAL,"length",varray());
ADDFUNC0(RECT2,REAL,Rect2,get_area,varray());
ADDFUNC1(RECT2,BOOL,Rect2,intersects,RECT2,"b",varray());
@@ -1476,6 +1488,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC0(VECTOR3,VECTOR3,Vector3,ceil,varray());
ADDFUNC1(VECTOR3,REAL,Vector3,distance_to,VECTOR3,"b",varray());
ADDFUNC1(VECTOR3,REAL,Vector3,distance_squared_to,VECTOR3,"b",varray());
+ ADDFUNC1(VECTOR3,REAL,Vector3,angle_to,VECTOR3,"to",varray());
ADDFUNC1(VECTOR3,VECTOR3,Vector3,slide,VECTOR3,"by",varray());
ADDFUNC1(VECTOR3,VECTOR3,Vector3,reflect,VECTOR3,"by",varray());
@@ -1584,6 +1597,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC2(RAW_ARRAY,INT,ByteArray,insert,INT,"idx",INT,"byte",varray());
ADDFUNC1(RAW_ARRAY,NIL,ByteArray,resize,INT,"idx",varray());
ADDFUNC0(RAW_ARRAY,NIL,ByteArray,invert,varray());
+ ADDFUNC2(RAW_ARRAY,RAW_ARRAY,ByteArray,subarray,INT,"from",INT,"to",varray());
ADDFUNC0(RAW_ARRAY,STRING,ByteArray,get_string_from_ascii,varray());
ADDFUNC0(RAW_ARRAY,STRING,ByteArray,get_string_from_utf8,varray());
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index 023605a952..6b3828a572 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -986,7 +986,18 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
InputEvent ie;
- if (id=="KEY") {
+ if (id=="NONE") {
+
+ ie.type=InputEvent::NONE;
+
+ get_token(p_stream,token,line,r_err_str);
+
+ if (token.type!=TK_PARENTHESIS_CLOSE) {
+ r_err_str="Expected ')'";
+ return ERR_PARSE_ERROR;
+ }
+
+ } else if (id=="KEY") {
get_token(p_stream,token,line,r_err_str);
if (token.type!=TK_COMMA) {
@@ -2093,6 +2104,9 @@ Error VariantWriter::write(const Variant& p_variant, StoreStringFunc p_store_str
case InputEvent::JOYSTICK_MOTION: {
str+="JAXIS,"+itos(ev.joy_motion.axis)+","+itos(ev.joy_motion.axis_value);
} break;
+ case InputEvent::NONE: {
+ str+="NONE";
+ } break;
default: {}
}