summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2016-08-02 19:11:47 -0300
committerJuan Linietsky <reduzio@gmail.com>2016-08-02 19:11:47 -0300
commit3d1d190dcd2993f87d5804de8a60e8bf5fc2cf49 (patch)
treeaa2c814b744ab970ae79931b419908ff7ebc850e
parentad313097ebcb2a0c02c956fdf74a6610c3f7c9a8 (diff)
parentcea949180688add09eb9e69f5e405f361dc96d40 (diff)
Merge branch 'master' of https://github.com/godotengine/godot
-rw-r--r--bin/tests/test_math.cpp1
-rw-r--r--core/array.cpp4
-rw-r--r--core/array.h1
-rw-r--r--core/func_ref.cpp2
-rw-r--r--core/io/image_loader.cpp3
-rw-r--r--core/math/geometry.cpp14
-rw-r--r--core/math/math_2d.h8
-rw-r--r--core/math/math_funcs.cpp36
-rw-r--r--core/math/math_funcs.h2
-rw-r--r--core/math/quat.cpp2
-rw-r--r--core/object_type_db.cpp2
-rw-r--r--core/ustring.cpp2
-rw-r--r--core/variant.cpp40
-rw-r--r--core/variant_call.cpp2
-rw-r--r--core/variant_op.cpp10
-rw-r--r--core/variant_parser.cpp4
-rw-r--r--doc/base/classes.xml45
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp11
-rw-r--r--main/input_default.cpp1
-rw-r--r--modules/gdscript/gd_editor.cpp2
-rw-r--r--modules/gdscript/gd_functions.cpp2
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java172
-rw-r--r--platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java335
-rw-r--r--platform/windows/godot_res.rc16
-rw-r--r--platform/windows/os_windows.cpp3
-rw-r--r--scene/2d/parallax_layer.cpp19
-rw-r--r--scene/3d/baked_light_instance.cpp10
-rw-r--r--scene/3d/baked_light_instance.h2
-rw-r--r--scene/gui/file_dialog.cpp19
-rw-r--r--scene/gui/file_dialog.h2
-rw-r--r--scene/gui/graph_edit.cpp5
-rw-r--r--scene/gui/graph_edit.h1
-rw-r--r--scene/gui/graph_node.cpp5
-rw-r--r--scene/gui/label.cpp4
-rw-r--r--scene/gui/line_edit.cpp2
-rw-r--r--scene/gui/spin_box.cpp2
-rw-r--r--scene/gui/text_edit.cpp29
-rw-r--r--scene/gui/text_edit.h2
-rw-r--r--scene/gui/tree.cpp8
-rw-r--r--scene/main/http_request.cpp108
-rw-r--r--scene/main/http_request.h13
-rw-r--r--scene/main/viewport.cpp27
-rw-r--r--scene/resources/curve.cpp6
-rw-r--r--scene/resources/dynamic_font.cpp174
-rw-r--r--scene/resources/dynamic_font.h52
-rw-r--r--scene/resources/world_2d.cpp2
-rw-r--r--servers/audio/audio_mixer_sw.h3
-rw-r--r--servers/audio_server.h3
-rw-r--r--servers/physics/body_pair_sw.cpp8
-rw-r--r--tools/editor/asset_library_editor_plugin.cpp19
-rw-r--r--tools/editor/code_editor.cpp55
-rw-r--r--tools/editor/code_editor.h3
-rw-r--r--tools/editor/editor_file_system.cpp2
-rw-r--r--tools/editor/editor_help.cpp10
-rw-r--r--tools/editor/editor_node.cpp18
-rw-r--r--tools/editor/editor_node.h3
-rw-r--r--tools/editor/editor_plugin.cpp6
-rw-r--r--tools/editor/editor_plugin.h3
-rw-r--r--tools/editor/filesystem_dock.cpp10
-rw-r--r--tools/editor/icons/2x/icon_godot.pngbin1545 -> 1842 bytes
-rw-r--r--tools/editor/icons/2x/icon_h_t_t_p_request.pngbin180 -> 425 bytes
-rw-r--r--tools/editor/icons/SCsub5
-rw-r--r--tools/editor/icons/icon_godot.pngbin695 -> 769 bytes
-rw-r--r--tools/editor/icons/icon_h_t_t_p_request.pngbin154 -> 301 bytes
-rw-r--r--tools/editor/icons/make_icons.py48
-rw-r--r--tools/editor/icons/source/icon_godot.svg28
-rw-r--r--tools/editor/icons/source/icon_group.svg1005
-rw-r--r--tools/editor/icons/source/icon_h_t_t_p_request.svg78
-rw-r--r--tools/editor/io_plugins/editor_mesh_import_plugin.cpp1
-rw-r--r--tools/editor/plugins/baked_light_baker.cpp4
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.cpp6
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp1
-rw-r--r--tools/editor/project_manager.cpp259
-rw-r--r--tools/editor/project_manager.h8
-rw-r--r--tools/editor/project_settings.cpp33
-rw-r--r--tools/editor/property_editor.cpp4
-rw-r--r--tools/editor/scene_tree_dock.cpp39
-rw-r--r--tools/editor/scene_tree_dock.h4
-rw-r--r--version.py2
79 files changed, 1337 insertions, 1543 deletions
diff --git a/bin/tests/test_math.cpp b/bin/tests/test_math.cpp
index 8e08969fa4..4b686e8af8 100644
--- a/bin/tests/test_math.cpp
+++ b/bin/tests/test_math.cpp
@@ -113,6 +113,7 @@ uint32_t ihash3( uint32_t a)
MainLoop* test() {
+ print_line(itos(Math::step_decimals( 0.0001 )));
return NULL;
{
diff --git a/core/array.cpp b/core/array.cpp
index bb8e527304..23792f90fc 100644
--- a/core/array.cpp
+++ b/core/array.cpp
@@ -200,6 +200,10 @@ int Array::count(const Variant& p_value) const {
return amount;
}
+bool Array::has(const Variant& p_value) const {
+ return _p->array.find(p_value, 0) != -1;
+}
+
void Array::remove(int p_pos) {
_p->array.remove(p_pos);
diff --git a/core/array.h b/core/array.h
index 096660653e..dfc902525c 100644
--- a/core/array.h
+++ b/core/array.h
@@ -75,6 +75,7 @@ public:
int rfind(const Variant& p_value, int p_from=-1) const;
int find_last(const Variant& p_value) const;
int count(const Variant& p_value) const;
+ bool has(const Variant& p_value) const;
void erase(const Variant& p_value);
diff --git a/core/func_ref.cpp b/core/func_ref.cpp
index 29b06ae9a0..644d8b5b63 100644
--- a/core/func_ref.cpp
+++ b/core/func_ref.cpp
@@ -65,7 +65,7 @@ void FuncRef::_bind_methods() {
mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i)));
defargs.push_back(Variant());
}
- ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_func",&FuncRef::call_func,mi,defargs);
+ ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_func:Variant",&FuncRef::call_func,mi,defargs);
}
diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp
index 05bad97e90..ac6c00dc61 100644
--- a/core/io/image_loader.cpp
+++ b/core/io/image_loader.cpp
@@ -51,7 +51,7 @@ Error ImageLoader::load_image(String p_file,Image *p_image, FileAccess *p_custom
Error err;
f=FileAccess::open(p_file,FileAccess::READ,&err);
if (!f) {
- print_line("ERROR OPENING FILE: "+p_file);
+ ERR_PRINTS("Error opening file: "+p_file);
return err;
}
}
@@ -76,7 +76,6 @@ Error ImageLoader::load_image(String p_file,Image *p_image, FileAccess *p_custom
}
- print_line("NO LOADER?");
if (!p_custom)
memdelete(f);
diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp
index 5b767212f5..790903eff5 100644
--- a/core/math/geometry.cpp
+++ b/core/math/geometry.cpp
@@ -629,7 +629,7 @@ DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro
// create and initialize cells to zero
- print_line("Wrapper: Initializing Cells");
+ //print_line("Wrapper: Initializing Cells");
uint8_t ***cell_status=memnew_arr(uint8_t**,div_x);
for(int i=0;i<div_x;i++) {
@@ -648,7 +648,7 @@ DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro
}
// plot faces into cells
- print_line("Wrapper (1/6): Plotting Faces");
+ //print_line("Wrapper (1/6): Plotting Faces");
for (int i=0;i<face_count;i++) {
@@ -663,7 +663,7 @@ DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro
// determine which cells connect to the outside by traversing the outside and recursively flood-fill marking
- print_line("Wrapper (2/6) Flood Filling");
+ //print_line("Wrapper (2/6): Flood Filling");
for (int i=0;i<div_x;i++) {
@@ -694,7 +694,7 @@ DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro
// build faces for the inside-outside cell divisors
- print_line("Wrapper (3/6): Building Faces");
+ //print_line("Wrapper (3/6): Building Faces");
DVector<Face3> wrapped_faces;
@@ -709,7 +709,7 @@ DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro
}
}
- print_line("Wrapper (4/6): Transforming Back Vertices");
+ //print_line("Wrapper (4/6): Transforming Back Vertices");
// transform face vertices to global coords
@@ -728,7 +728,7 @@ DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro
}
// clean up grid
- print_line("Wrapper (5/6): Grid Cleanup");
+ //print_line("Wrapper (5/6): Grid Cleanup");
for(int i=0;i<div_x;i++) {
@@ -744,7 +744,7 @@ DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro
if (p_error)
*p_error=voxelsize.length();
- print_line("Wrapper (6/6): Finished.");
+ //print_line("Wrapper (6/6): Finished.");
return wrapped_faces;
}
diff --git a/core/math/math_2d.h b/core/math/math_2d.h
index ad4655b8f7..fbf700fb9c 100644
--- a/core/math/math_2d.h
+++ b/core/math/math_2d.h
@@ -157,7 +157,7 @@ struct Vector2 {
float get_aspect() const { return width/height; }
- operator String() const { return String::num(x)+","+String::num(y); }
+ operator String() const { return String::num(x)+", "+String::num(y); }
_FORCE_INLINE_ Vector2(float p_x,float p_y) { x=p_x; y=p_y; }
_FORCE_INLINE_ Vector2() { x=0; y=0; }
@@ -356,7 +356,7 @@ struct Rect2 {
}
- operator String() const { return String(pos)+","+String(size); }
+ operator String() const { return String(pos)+", "+String(size); }
Rect2() {}
Rect2( float p_x, float p_y, float p_width, float p_height) { pos=Point2(p_x,p_y); size=Size2( p_width, p_height ); }
@@ -409,7 +409,7 @@ struct Point2i {
float get_aspect() const { return width/(float)height; }
- operator String() const { return String::num(x)+","+String::num(y); }
+ operator String() const { return String::num(x)+", "+String::num(y); }
operator Vector2() const { return Vector2(x,y); }
inline Point2i(const Vector2& p_vec2) { x=(int)p_vec2.x; y=(int)p_vec2.y; }
@@ -540,7 +540,7 @@ struct Rect2i {
}
- operator String() const { return String(pos)+","+String(size); }
+ operator String() const { return String(pos)+", "+String(size); }
operator Rect2() const { return Rect2(pos,size); }
Rect2i(const Rect2& p_r2) { pos=p_r2.pos; size=p_r2.size; }
diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp
index 0fbd031214..64615fe6b4 100644
--- a/core/math/math_funcs.cpp
+++ b/core/math/math_funcs.cpp
@@ -206,25 +206,29 @@ double Math::ceil(double p_x) {
return ::ceil(p_x);
}
-int Math::decimals(double p_step) {
-
- int max=4;
- double llimit = Math::pow(0.1,max);
- double ulimit = 1.0-llimit;
- int i=0;
- while( max) {
-
- float d = absf(p_step) - Math::floor(absf(p_step));
+int Math::step_decimals(double p_step) {
+
+ static const int maxn=9;
+ static const double sd[maxn]={
+ 0.9999, // somehow compensate for floating point error
+ 0.09999,
+ 0.009999,
+ 0.0009999,
+ 0.00009999,
+ 0.000009999,
+ 0.0000009999,
+ 0.00000009999,
+ 0.000000009999
+ };
- if (d<llimit || d>ulimit)
- break;
- p_step*=10.0;
- max--;
- i++;
+ double as=absf(p_step);
+ for(int i=0;i<maxn;i++) {
+ if (as>=sd[i]) {
+ return i;
+ }
}
- return i;
-
+ return maxn;
}
double Math::ease(double p_x, double p_c) {
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 2e1b9c989e..fc76d96b2e 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -66,7 +66,7 @@ public:
static double floor(double p_x);
static double ceil(double p_x);
static double ease(double p_x, double p_c);
- static int decimals(double p_step);
+ static int step_decimals(double p_step);
static double stepify(double p_value,double p_step);
static void seed(uint32_t x=0);
static void randomize();
diff --git a/core/math/quat.cpp b/core/math/quat.cpp
index c6c12129b3..73124e5e8e 100644
--- a/core/math/quat.cpp
+++ b/core/math/quat.cpp
@@ -252,7 +252,7 @@ Quat Quat::cubic_slerp(const Quat& q, const Quat& prep, const Quat& postq,const
Quat::operator String() const {
- return String::num(x)+","+String::num(y)+","+ String::num(z)+","+ String::num(w);
+ return String::num(x)+", "+String::num(y)+", "+ String::num(z)+", "+ String::num(w);
}
Quat::Quat(const Vector3& axis, const real_t& angle) {
diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp
index 5f97df39a6..4998263961 100644
--- a/core/object_type_db.cpp
+++ b/core/object_type_db.cpp
@@ -828,7 +828,7 @@ MethodBind* ObjectTypeDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind , c
TypeInfo *type=types.getptr(instance_type);
if (!type) {
- print_line("couldn't bind method "+mdname+" for instance: "+instance_type);
+ ERR_PRINTS("Couldn't bind method '"+mdname+"' for instance: "+instance_type);
memdelete(p_bind);
ERR_FAIL_COND_V(!type,NULL);
}
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 6788ada1bb..0d887210c3 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -3491,7 +3491,7 @@ bool String::is_valid_integer() const {
return false;
int from=0;
- if (operator[](0)=='+' || operator[](0)=='-')
+ if (len!=1 && (operator[](0)=='+' || operator[](0)=='-'))
from++;
for(int i=from;i<len;i++) {
diff --git a/core/variant.cpp b/core/variant.cpp
index 31321dc0f3..a78c07d819 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -1515,15 +1515,43 @@ Variant::operator String() const {
case INT: return String::num(_data._int);
case REAL: return String::num(_data._real);
case STRING: return *reinterpret_cast<const String*>(_data._mem);
- case VECTOR2: return operator Vector2();
- case RECT2: return operator Rect2();
- case MATRIX32: return operator Matrix32();
- case VECTOR3: return operator Vector3();
+ case VECTOR2: return "("+operator Vector2()+")";
+ case RECT2: return "("+operator Rect2()+")";
+ case MATRIX32: {
+
+ Matrix32 mat32 = operator Matrix32();
+ return "("+Variant(mat32.elements[0]).operator String()+", "+Variant(mat32.elements[1]).operator String()+", "+Variant(mat32.elements[2]).operator String()+")";
+ } break;
+ case VECTOR3: return "("+operator Vector3()+")";
case PLANE: return operator Plane();
//case QUAT:
case _AABB: return operator AABB();
- case QUAT: return operator Quat();
- case MATRIX3: return operator Matrix3();
+ case QUAT: return "("+operator Quat()+")";
+ case MATRIX3: {
+
+ Matrix3 mat3 = operator Matrix3();
+
+ String mtx("(");
+ for (int i=0;i<3;i++) {
+
+ if (i!=0)
+ mtx+=", ";
+
+ mtx+="(";
+
+ for (int j=0;j<3;j++) {
+
+ if (j!=0)
+ mtx+=", ";
+
+ mtx+=Variant( mat3.elements[i][j] ).operator String();
+ }
+
+ mtx+=")";
+ }
+
+ return mtx+")";
+ } break;
case TRANSFORM: return operator Transform();
case NODE_PATH: return operator NodePath();
case INPUT_EVENT: return operator InputEvent();
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 7da4cef115..7956c14c2c 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -474,6 +474,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_LOCALMEM2R(Array,rfind);
VCALL_LOCALMEM1R(Array,find_last);
VCALL_LOCALMEM1R(Array,count);
+ VCALL_LOCALMEM1R(Array,has);
VCALL_LOCALMEM1(Array,erase);
VCALL_LOCALMEM0(Array,sort);
VCALL_LOCALMEM2(Array,sort_custom);
@@ -1516,6 +1517,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC2(ARRAY,INT,Array,rfind,NIL,"what",INT,"from",varray(-1));
ADDFUNC1(ARRAY,INT,Array,find_last,NIL,"value",varray());
ADDFUNC1(ARRAY,INT,Array,count,NIL,"value",varray());
+ ADDFUNC1(ARRAY,BOOL,Array,has,NIL,"value",varray());
ADDFUNC0(ARRAY,NIL,Array,pop_back,varray());
ADDFUNC0(ARRAY,NIL,Array,pop_front,varray());
ADDFUNC0(ARRAY,NIL,Array,sort,varray());
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 9182dcde1a..c537ed230f 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -600,6 +600,7 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
case REAL: {
_RETURN( *reinterpret_cast<const Quat*>(p_a._data._mem) * p_b._data._real);
} break;
+ default: {}
};
r_valid=false;
return;
@@ -618,6 +619,7 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
_RETURN( *p_a._data._matrix3 * *p_b._data._matrix3 );
};
+ default: {}
} ;
r_valid=false;
return;
@@ -635,6 +637,7 @@ void Variant::evaluate(const Operator& p_op, const Variant& p_a, const Variant&
_RETURN( *p_a._data._transform * *p_b._data._transform );
};
+ default: {}
} ;
r_valid=false;
return;
@@ -999,7 +1002,7 @@ Variant Variant::get_named(const StringName& p_index, bool *r_valid) const {
DEFAULT_OP_ARRAY_CMD(m_name, DVector<dv_type>, if(skip_cond) return;, arr->set(index, p_value);return)
#define DEFAULT_OP_DVECTOR_GET(m_name, dv_type)\
- DEFAULT_OP_ARRAY_CMD(m_name, const DVector<dv_type>, 0, return arr->get(index))
+ DEFAULT_OP_ARRAY_CMD(m_name, const DVector<dv_type>, ;, return arr->get(index))
void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid) {
@@ -2417,7 +2420,7 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const {
return *res;
}
} break; // 20
- DEFAULT_OP_ARRAY_CMD(ARRAY, const Array, 0, return (*arr)[index])
+ DEFAULT_OP_ARRAY_CMD(ARRAY, const Array, ;, return (*arr)[index])
DEFAULT_OP_DVECTOR_GET(RAW_ARRAY, uint8_t)
DEFAULT_OP_DVECTOR_GET(INT_ARRAY, int)
DEFAULT_OP_DVECTOR_GET(REAL_ARRAY, real_t)
@@ -2994,6 +2997,7 @@ bool Variant::iter_init(Variant& r_iter,bool &valid) const {
return true;
} break;
+ default: {}
}
@@ -3137,6 +3141,7 @@ bool Variant::iter_next(Variant& r_iter,bool &valid) const {
r_iter=idx;
return true;
} break;
+ default: {}
}
@@ -3279,6 +3284,7 @@ Variant Variant::iter_get(const Variant& r_iter,bool &r_valid) const {
#endif
return arr->get(idx);
} break;
+ default: {}
}
diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp
index dce873a306..023605a952 100644
--- a/core/variant_parser.cpp
+++ b/core/variant_parser.cpp
@@ -1233,7 +1233,9 @@ Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,in
}
get_token(p_stream,token,line,r_err_str);
- if (token.type!=TK_STRING) {
+ if (token.type==TK_PARENTHESIS_CLOSE) {
+ break;
+ } else if (token.type!=TK_STRING) {
r_err_str="Expected string";
return ERR_PARSE_ERROR;
}
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index 4c2a0fe7ba..b7b0502eaa 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -660,7 +660,7 @@
<argument index="1" name="signal" type="String">
</argument>
<description>
- Stop the function execution and return the current state. Call resume on the state to resume execution. This makes the state invalid.
+ Stop the function execution and return the current state. Call [method GDFunctionState.resume] on the state to resume execution. This invalidates the state.
Returns anything that was passed to the resume function call. If passed an object and a signal, the execution is resumed when the object's signal is emmited.
</description>
</method>
@@ -4546,6 +4546,15 @@
Searches the array in reverse order for a value and returns its index or -1 if not found.
</description>
</method>
+ <method name="has">
+ <return type="bool">
+ </return>
+ <argument index="0" name="value" type="var">
+ </argument>
+ <description>
+ Return true if the array contains given value. [code][ "inside", 7 ].has("inside") == true, [ "inside", 7 ].has("outside") == false, [ "inside", 7 ].has(7) == true, [ "inside", 7 ].has("7") == false[/code]
+ </description>
+ </method>
<method name="hash">
<return type="int">
</return>
@@ -11281,7 +11290,7 @@
<argument index="1" name="title" type="String">
</argument>
<description>
- Add a control to the bottom panel (together with Output, Debug, Animation, etc). If your plugin is being removed, also make sure to remove your control by calling [method remove_control_from_bottom_panel].
+ Add a control to the bottom panel (together with Output, Debug, Animation, etc). Returns a reference to the button added. It's up to you to hide/show the button when needed. If your plugin is being removed, also make sure to remove your control by calling [method remove_control_from_bottom_panel].
</description>
</method>
<method name="add_control_to_container">
@@ -12264,7 +12273,7 @@
file.open("user://save_game.dat", file.WRITE)
file.store_string(content)
file.close()
-
+
func load():
var file = File.new()
file.open("user://save_game.dat", file.READ)
@@ -13033,8 +13042,11 @@
</class>
<class name="FuncRef" inherits="Reference" category="Core">
<brief_description>
+ Reference to a function in an object.
</brief_description>
<description>
+ In GDScript, functions are not [i]first-class objects[/i]. This means it is impossible to store them directly as variables, return them from another function, or pass them as arguments.
+ However, by creating a [FuncRef] using the [method @GDScript.funcref] function, a reference to a function in a given object can be created, passed around and called.
</description>
<methods>
<method name="call_func">
@@ -13059,18 +13071,21 @@
<argument index="9" name="arg9" type="Variant" default="NULL">
</argument>
<description>
+ Call the referenced function with the given arguments. The argument count must correspond to the required number of arguments in the function. Returns the return value of the function call.
</description>
</method>
<method name="set_function">
<argument index="0" name="name" type="String">
</argument>
<description>
+ Set the name of the function to call on the object, without parentheses or any parameters.
</description>
</method>
<method name="set_instance">
<argument index="0" name="instance" type="Object">
</argument>
<description>
+ Set the object on which to call the referenced function. This object must be of a type actually inheriting from [Object], not a built-in type such as [int], [Vector2] or [Dictionary].
</description>
</method>
</methods>
@@ -13079,15 +13094,17 @@
</class>
<class name="GDFunctionState" inherits="Reference" category="Core">
<brief_description>
+ State of a function call after yielding.
</brief_description>
<description>
+ Calling [method @GDScript.yield] within a function will cause that function to yield and return its current state as an object of this type. The yielded function call can then be resumed later by calling [method resume] on this state object.
</description>
<methods>
<method name="is_valid" qualifiers="const">
<return type="bool">
</return>
<description>
- Should put children to the top left corner instead of center of the container.
+ Check whether the function call may be resumed. This is not the case if the function state was already resumed.
</description>
</method>
<method name="resume">
@@ -13096,6 +13113,9 @@
<argument index="0" name="arg" type="Variant" default="NULL">
</argument>
<description>
+ Resume execution of the yielded function call.
+ If handed an argument, return the argument from the [method @GDScript.yield] call in the yielded function call. You can pass e.g. an [Array] to hand multiple arguments.
+ This function returns what the resumed function call returns, possibly another function state if yielded again.
</description>
</method>
</methods>
@@ -15692,7 +15712,7 @@
</brief_description>
<description>
</description>
- ImmediateGeometry is a node used for displaying simple geometry created from code, very similar to how glBegin() and glEnd() worked in old versions of OpenGL (1.x).
+ ImmediateGeometry is a node used for displaying simple geometry created from code, very similar to how glBegin() and glEnd() worked in old versions of OpenGL (1.x).
Simply call [method begin()], and add vertices. For custom vertex colors, uvs, normal, etc. call one of the set_ functions below before adding each vertex. When done, call [method end]
Calls to begin/end are accumulative and all geometry is added together. To clear all the geometry, call [method clear].
If a material override is set, and this material contains a texture, it's possible to override the texture used in this material for every begin/end set of calls.
@@ -17226,20 +17246,25 @@
</class>
<class name="InstancePlaceholder" inherits="Node" category="Core">
<brief_description>
+ Placeholder for the root [Node] of a [PackedScene].
</brief_description>
<description>
+ Turning on the option [b]Load As Placeholder[/b] for an instanced scene in the editor causes it to be replaced by an InstacePlaceholder when running the game. This makes it possible to delay actually loading the scene until calling [method replace_by_instance]. This is useful to avoid loading large scenes all at once by loading parts of it selectively.
+ The InstancePlaceholder does not have a transform. This causes any child nodes to be positioned relatively to the Viewport from point (0,0), rather than their parent as displayed in the editor. Replacing the placeholder with a scene with a transform will transform children relatively to their parent again.
</description>
<methods>
<method name="get_instance_path" qualifiers="const">
<return type="String">
</return>
<description>
+ Retrieve the path to the [PackedScene] resource file that is loaded by default when calling [method replace_by_instance].
</description>
</method>
<method name="replace_by_instance">
<argument index="0" name="custom_scene" type="PackedScene" default="NULL">
</argument>
<description>
+ Replace this placeholder by the scene handed as an argument, or the original scene if no argument is given. As for all resources, the scene is loaded only if it's not loaded already. By manually loading the scene beforehand, delays caused by this function can be avoided.
</description>
</method>
</methods>
@@ -30271,8 +30296,10 @@
</class>
<class name="RID" category="Built-In Types">
<brief_description>
+ Handle for a [Resource]'s unique ID.
</brief_description>
<description>
+ The RID type is used to access the unique integer ID of a resource. They are opaque, so they do not grant access to the associated resource by themselves. They are used by and with the low-level Server classes such as [VisualServer].
</description>
<methods>
<method name="RID">
@@ -30281,12 +30308,14 @@
<argument index="0" name="from" type="Object">
</argument>
<description>
+ Create a new RID instance with the ID of a given resource. When not handed a valid resource, silently stores the unused ID 0.
</description>
</method>
<method name="get_id">
<return type="int">
</return>
<description>
+ Retrieve the ID of the referenced resource.
</description>
</method>
</methods>
@@ -42401,7 +42430,7 @@
Because it is easy to get it wrong, here is a quick usage example:
[codeblock]
var tween = get_node("Tween")
- tween.interpolate_property(get_node("Node2D_to_move"), "transform/pos", Vector2(0,0), Vector2(100,100), Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
+ tween.interpolate_property(get_node("Node2D_to_move"), "transform/pos", Vector2(0,0), Vector2(100,100), 1, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
tween.start()
[/codeblock]
Some of the methods of this class require a property name. You can get the property name by hovering over the property in the inspector of the editor.
@@ -46575,24 +46604,28 @@
<return type="RID">
</return>
<description>
+ Retrieve the [RID] of this world's canvas resource. Used by the [VisualServer] for 2D drawing.
</description>
</method>
<method name="get_direct_space_state">
<return type="Physics2DDirectSpaceState">
</return>
<description>
+ Retrieve the state of this world's physics space. This allows arbitrary querying for collision.
</description>
</method>
<method name="get_sound_space">
<return type="RID">
</return>
<description>
+ Retrieve the [RID] of this world's sound space resource. Used by the [SpatialSound2DServer] for 2D spatial audio.
</description>
</method>
<method name="get_space">
<return type="RID">
</return>
<description>
+ Retrieve the [RID] of this world's physics space resource. Used by the [Physics2DServer] for 2D physics, treating it as both a space and an area.
</description>
</method>
</methods>
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index 4cd97a7f6a..ba93a26a2d 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -10788,8 +10788,17 @@ void RasterizerGLES2::init() {
if (OS::get_singleton()->is_stdout_verbose()) {
print_line(String("GLES2: Using GLEW ") + (const char*) glewGetString(GLEW_VERSION));
}
-#endif
+ // Check for GL 2.1 compatibility, if not bail out
+ if (!glewIsSupported("GL_VERSION_2_1")) {
+ ERR_PRINT("Your system's graphic drivers seem not to support OpenGL 2.1 / GLES 2.0, sorry :(\n"
+ "Try a drivers update, buy a new GPU or try software rendering on Linux; Godot will now crash with a segmentation fault.");
+ OS::get_singleton()->alert("Your system's graphic drivers seem not to support OpenGL 2.1 / GLES 2.0, sorry :(\n"
+ "Godot Engine will self-destruct as soon as you acknowledge this error message.",
+ "Fatal error: Insufficient OpenGL / GLES drivers");
+ // TODO: If it's even possible, we should stop the execution without segfault and memory leaks :)
+ }
+#endif
diff --git a/main/input_default.cpp b/main/input_default.cpp
index 5e66a8b585..618d0d4f7d 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -588,6 +588,7 @@ static const char *s_ControllerMappings [] =
"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,",
"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,",
+ "030000005e0400008e02000001000000,Microsoft X-Box 360 pad,leftx:a0,lefty:a1,dpdown:h0.1,rightstick:b10,rightshoulder:b5,rightx:a3,start:b7,righty:a4,dpleft:h0.2,lefttrigger:a2,x:b2,dpup:h0.4,back:b6,leftshoulder:b4,y:b3,a:b0,dpright:h0.8,righttrigger:a5,b:b1,",
"030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,",
"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp
index 520a8b18d8..b02e55cf9d 100644
--- a/modules/gdscript/gd_editor.cpp
+++ b/modules/gdscript/gd_editor.cpp
@@ -297,7 +297,7 @@ void GDScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const
}
{
MethodInfo mi;
- mi.name="yield";
+ mi.name="yield:GDFunctionState";
mi.arguments.push_back(PropertyInfo(Variant::OBJECT,"object"));
mi.arguments.push_back(PropertyInfo(Variant::STRING,"signal"));
mi.default_arguments.push_back(Variant::NIL);
diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp
index b9815a5efd..a565e866d0 100644
--- a/modules/gdscript/gd_functions.cpp
+++ b/modules/gdscript/gd_functions.cpp
@@ -304,7 +304,7 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
case MATH_DECIMALS: {
VALIDATE_ARG_COUNT(1);
VALIDATE_ARG_NUM(0);
- r_ret=Math::decimals(*p_args[0]);
+ r_ret=Math::step_decimals(*p_args[0]);
} break;
case MATH_STEPIFY: {
VALIDATE_ARG_COUNT(2);
diff --git a/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java b/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java
index fde752acc9..b7de31ada3 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotPaymentV3.java
@@ -28,99 +28,94 @@
/*************************************************************************/
package org.godotengine.godot;
-import org.godotengine.godot.Dictionary;
import android.app.Activity;
import android.util.Log;
+import org.godotengine.godot.payments.PaymentsManager;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
public class GodotPaymentV3 extends Godot.SingletonBase {
private Godot activity;
-
private Integer purchaseCallbackId = 0;
-
private String accessToken;
-
private String purchaseValidationUrlPrefix;
-
private String transactionId;
+ private PaymentsManager mPaymentManager;
+ private Dictionary mSkuDetails = new Dictionary();
- public void purchase( String _sku, String _transactionId) {
- final String sku = _sku;
- final String transactionId = _transactionId;
- activity.getPaymentsManager().setBaseSingleton(this);
+ public void purchase(final String sku, final String transactionId) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- activity.getPaymentsManager().requestPurchase(sku, transactionId);
+ mPaymentManager.requestPurchase(sku, transactionId);
}
});
}
-
-/* public string requestPurchasedTicket(){
- activity.getPaymentsManager()
- }
-*/
- static public Godot.SingletonBase initialize(Activity p_activity) {
+ static public Godot.SingletonBase initialize(Activity p_activity) {
- return new GodotPaymentV3(p_activity);
- }
+ return new GodotPaymentV3(p_activity);
+ }
-
public GodotPaymentV3(Activity p_activity) {
- registerClass("GodotPayments", new String[] {"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature", "consumeUnconsumedPurchases", "requestPurchased", "setAutoConsume", "consume"});
- activity=(Godot) p_activity;
+ registerClass("GodotPayments", new String[]{"purchase", "setPurchaseCallbackId", "setPurchaseValidationUrlPrefix", "setTransactionId", "getSignature", "consumeUnconsumedPurchases", "requestPurchased", "setAutoConsume", "consume", "querySkuDetails"});
+ activity = (Godot) p_activity;
+ mPaymentManager = activity.getPaymentsManager();
+ mPaymentManager.setBaseSingleton(this);
}
- public void consumeUnconsumedPurchases(){
- activity.getPaymentsManager().setBaseSingleton(this);
+ public void consumeUnconsumedPurchases() {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- activity.getPaymentsManager().consumeUnconsumedPurchases();
+ mPaymentManager.consumeUnconsumedPurchases();
}
});
}
private String signature;
- public String getSignature(){
- return this.signature;
+
+ public String getSignature() {
+ return this.signature;
}
-
-
- public void callbackSuccess(String ticket, String signature, String sku){
-// Log.d(this.getClass().getName(), "PRE-Send callback to purchase success");
+
+ public void callbackSuccess(String ticket, String signature, String sku) {
GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{ticket, signature, sku});
-// Log.d(this.getClass().getName(), "POST-Send callback to purchase success");
-}
+ }
+
+ public void callbackSuccessProductMassConsumed(String ticket, String signature, String sku) {
+ Log.d(this.getClass().getName(), "callbackSuccessProductMassConsumed > " + ticket + "," + signature + "," + sku);
+ GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[]{ticket, signature, sku});
+ }
- public void callbackSuccessProductMassConsumed(String ticket, String signature, String sku){
-// Log.d(this.getClass().getName(), "PRE-Send callback to consume success");
- Log.d(this.getClass().getName(), "callbackSuccessProductMassConsumed > "+ticket+","+signature+","+sku);
- GodotLib.calldeferred(purchaseCallbackId, "consume_success", new Object[]{ticket, signature, sku});
-// Log.d(this.getClass().getName(), "POST-Send callback to consume success");
+ public void callbackSuccessNoUnconsumedPurchases() {
+ GodotLib.calldeferred(purchaseCallbackId, "consume_not_required", new Object[]{});
}
- public void callbackSuccessNoUnconsumedPurchases(){
- GodotLib.calldeferred(purchaseCallbackId, "no_validation_required", new Object[]{});
+ public void callbackFailConsume() {
+ GodotLib.calldeferred(purchaseCallbackId, "consume_fail", new Object[]{});
}
-
- public void callbackFail(){
+
+ public void callbackFail() {
GodotLib.calldeferred(purchaseCallbackId, "purchase_fail", new Object[]{});
-// GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{});
}
-
- public void callbackCancel(){
+
+ public void callbackCancel() {
GodotLib.calldeferred(purchaseCallbackId, "purchase_cancel", new Object[]{});
-// GodotLib.callobject(purchaseCallbackId, "purchase_cancel", new Object[]{});
}
-
- public void callbackAlreadyOwned(String sku){
+
+ public void callbackAlreadyOwned(String sku) {
GodotLib.calldeferred(purchaseCallbackId, "purchase_owned", new Object[]{sku});
}
-
+
public int getPurchaseCallbackId() {
return purchaseCallbackId;
}
@@ -129,11 +124,11 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
this.purchaseCallbackId = purchaseCallbackId;
}
- public String getPurchaseValidationUrlPrefix(){
- return this.purchaseValidationUrlPrefix ;
+ public String getPurchaseValidationUrlPrefix() {
+ return this.purchaseValidationUrlPrefix;
}
- public void setPurchaseValidationUrlPrefix(String url){
+ public void setPurchaseValidationUrlPrefix(String url) {
this.purchaseValidationUrlPrefix = url;
}
@@ -144,39 +139,80 @@ public class GodotPaymentV3 extends Godot.SingletonBase {
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
-
- public void setTransactionId(String transactionId){
+
+ public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
-
- public String getTransactionId(){
+
+ public String getTransactionId() {
return this.transactionId;
}
-
+
// request purchased items are not consumed
- public void requestPurchased(){
- activity.getPaymentsManager().setBaseSingleton(this);
+ public void requestPurchased() {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
- activity.getPaymentsManager().requestPurchased();
+ mPaymentManager.requestPurchased();
}
});
}
-
+
// callback for requestPurchased()
- public void callbackPurchased(String receipt, String signature, String sku){
+ public void callbackPurchased(String receipt, String signature, String sku) {
GodotLib.calldeferred(purchaseCallbackId, "has_purchased", new Object[]{receipt, signature, sku});
}
-
+
// consume item automatically after purchase. default is true.
- public void setAutoConsume(boolean autoConsume){
- activity.getPaymentsManager().setAutoConsume(autoConsume);
+ public void setAutoConsume(boolean autoConsume) {
+ mPaymentManager.setAutoConsume(autoConsume);
}
-
+
// consume a specific item
- public void consume(String sku){
- activity.getPaymentsManager().consume(sku);
+ public void consume(String sku) {
+ mPaymentManager.consume(sku);
+ }
+
+ // query in app item detail info
+ public void querySkuDetails(String[] list) {
+ List<String> nKeys = Arrays.asList(list);
+ List<String> cKeys = Arrays.asList(mSkuDetails.get_keys());
+ ArrayList<String> fKeys = new ArrayList<String>();
+ for (String key : nKeys) {
+ if (!cKeys.contains(key)) {
+ fKeys.add(key);
+ }
+ }
+ if (fKeys.size() > 0) {
+ mPaymentManager.querySkuDetails(fKeys.toArray(new String[0]));
+ } else {
+ completeSkuDetail();
+ }
+ }
+
+ public void addSkuDetail(String itemJson) {
+ JSONObject o = null;
+ try {
+ o = new JSONObject(itemJson);
+ Dictionary item = new Dictionary();
+ item.put("type", o.optString("type"));
+ item.put("product_id", o.optString("productId"));
+ item.put("title", o.optString("title"));
+ item.put("description", o.optString("description"));
+ item.put("price", o.optString("price"));
+ item.put("price_currency_code", o.optString("price_currency_code"));
+ item.put("price_amount", 0.000001d * o.optLong("price_amount_micros"));
+ mSkuDetails.put(item.get("product_id").toString(), item);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void completeSkuDetail() {
+ GodotLib.calldeferred(purchaseCallbackId, "sku_details_complete", new Object[]{mSkuDetails});
+ }
+
+ public void errorSkuDetail(String errorMessage) {
+ GodotLib.calldeferred(purchaseCallbackId, "sku_details_error", new Object[]{errorMessage});
}
}
-
diff --git a/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java
index eb33b37ecc..753c0a6f93 100644
--- a/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java
+++ b/platform/android/java/src/org/godotengine/godot/payments/PaymentsManager.java
@@ -28,283 +28,370 @@
/*************************************************************************/
package org.godotengine.godot.payments;
-import java.util.ArrayList;
-import java.util.List;
-
-import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.os.Bundle;
import android.os.IBinder;
+import android.os.RemoteException;
+import android.text.TextUtils;
import android.util.Log;
-import android.os.Bundle;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONStringer;
+import com.android.vending.billing.IInAppBillingService;
-import org.godotengine.godot.Dictionary;
import org.godotengine.godot.Godot;
import org.godotengine.godot.GodotPaymentV3;
-import com.android.vending.billing.IInAppBillingService;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.Arrays;
public class PaymentsManager {
public static final int BILLING_RESPONSE_RESULT_OK = 0;
public static final int REQUEST_CODE_FOR_PURCHASE = 0x1001;
private static boolean auto_consume = true;
-
+
private Activity activity;
IInAppBillingService mService;
- public void setActivity(Activity activity){
+ public void setActivity(Activity activity) {
this.activity = activity;
}
- public static PaymentsManager createManager(Activity activity){
+ public static PaymentsManager createManager(Activity activity) {
PaymentsManager manager = new PaymentsManager(activity);
return manager;
}
-
- private PaymentsManager(Activity activity){
+
+ private PaymentsManager(Activity activity) {
this.activity = activity;
}
-
- public PaymentsManager initService(){
+
+ public PaymentsManager initService() {
Intent intent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
intent.setPackage("com.android.vending");
activity.bindService(
- intent,
- mServiceConn,
+ intent,
+ mServiceConn,
Context.BIND_AUTO_CREATE);
return this;
}
- public void destroy(){
+ public void destroy() {
if (mService != null) {
- activity.unbindService(mServiceConn);
- }
+ activity.unbindService(mServiceConn);
+ }
}
-
+
ServiceConnection mServiceConn = new ServiceConnection() {
- @Override
- public void onServiceDisconnected(ComponentName name) {
- mService = null;
- }
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ mService = null;
+ }
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
mService = IInAppBillingService.Stub.asInterface(service);
- }
+ }
};
-
- public void requestPurchase(final String sku, String transactionId){
+
+ public void requestPurchase(final String sku, String transactionId) {
new PurchaseTask(mService, Godot.getInstance()) {
-
+
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
-
+
}
-
+
@Override
protected void canceled() {
godotPaymentV3.callbackCancel();
}
-
+
@Override
protected void alreadyOwned() {
godotPaymentV3.callbackAlreadyOwned(sku);
}
-
+
}.purchase(sku, transactionId);
}
- public void consumeUnconsumedPurchases(){
+ public void consumeUnconsumedPurchases() {
new ReleaseAllConsumablesTask(mService, activity) {
-
+
@Override
protected void success(String sku, String receipt, String signature, String token) {
godotPaymentV3.callbackSuccessProductMassConsumed(receipt, signature, sku);
}
-
+
@Override
protected void error(String message) {
- godotPaymentV3.callbackFail();
-
+ Log.d("godot", "consumeUnconsumedPurchases :" + message);
+ godotPaymentV3.callbackFailConsume();
+
}
@Override
protected void notRequired() {
+ Log.d("godot", "callbackSuccessNoUnconsumedPurchases :");
godotPaymentV3.callbackSuccessNoUnconsumedPurchases();
-
+
}
}.consumeItAll();
}
-
- public void requestPurchased(){
- try{
+
+ public void requestPurchased() {
+ try {
PaymentsCache pc = new PaymentsCache(Godot.getInstance());
-// Log.d("godot", "requestPurchased for " + activity.getPackageName());
- Bundle bundle = mService.getPurchases(3, activity.getPackageName(), "inapp",null);
+ String continueToken = null;
-/*
- for (String key : bundle.keySet()) {
- Object value = bundle.get(key);
- Log.d("godot", String.format("%s %s (%s)", key, value.toString(), value.getClass().getName()));
- }
-*/
-
- if (bundle.getInt("RESPONSE_CODE") == 0){
+ do {
+ Bundle bundle = mService.getPurchases(3, activity.getPackageName(), "inapp", continueToken);
- final ArrayList<String> myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
- final ArrayList<String> mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
-
+ if (bundle.getInt("RESPONSE_CODE") == 0) {
- if (myPurchases == null || myPurchases.size() == 0){
-// Log.d("godot", "No purchases!");
- godotPaymentV3.callbackPurchased("", "", "");
- return;
- }
-
-// Log.d("godot", "# products are purchased:" + myPurchases.size());
- for (int i=0;i<myPurchases.size();i++)
- {
-
- try{
- String receipt = myPurchases.get(i);
- JSONObject inappPurchaseData = new JSONObject(receipt);
- String sku = inappPurchaseData.getString("productId");
- String token = inappPurchaseData.getString("purchaseToken");
- String signature = mySignatures.get(i);
-// Log.d("godot", "purchased item:" + token + "\n" + receipt);
-
- pc.setConsumableValue("ticket_signautre", sku, signature);
- pc.setConsumableValue("ticket", sku, receipt);
- pc.setConsumableFlag("block", sku, true);
- pc.setConsumableValue("token", sku, token);
-
- godotPaymentV3.callbackPurchased(receipt, signature, sku);
- } catch (JSONException e) {
+ final ArrayList<String> myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
+ final ArrayList<String> mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
+
+ if (myPurchases == null || myPurchases.size() == 0) {
+ godotPaymentV3.callbackPurchased("", "", "");
+ return;
}
- }
- }
- }catch(Exception e){
+ for (int i = 0; i < myPurchases.size(); i++) {
+
+ try {
+ String receipt = myPurchases.get(i);
+ JSONObject inappPurchaseData = new JSONObject(receipt);
+ String sku = inappPurchaseData.getString("productId");
+ String token = inappPurchaseData.getString("purchaseToken");
+ String signature = mySignatures.get(i);
+
+ pc.setConsumableValue("ticket_signautre", sku, signature);
+ pc.setConsumableValue("ticket", sku, receipt);
+ pc.setConsumableFlag("block", sku, true);
+ pc.setConsumableValue("token", sku, token);
+
+ godotPaymentV3.callbackPurchased(receipt, signature, sku);
+ } catch (JSONException e) {
+ }
+ }
+ }
+ continueToken = bundle.getString("INAPP_CONTINUATION_TOKEN");
+ Log.d("godot", "continue token = " + continueToken);
+ } while (!TextUtils.isEmpty(continueToken));
+ } catch (Exception e) {
Log.d("godot", "Error requesting purchased products:" + e.getClass().getName() + ":" + e.getMessage());
}
}
-
+
public void processPurchaseResponse(int resultCode, Intent data) {
- new HandlePurchaseTask(activity){
+ new HandlePurchaseTask(activity) {
@Override
protected void success(final String sku, final String signature, final String ticket) {
godotPaymentV3.callbackSuccess(ticket, signature, sku);
- if (auto_consume){
+ if (auto_consume) {
new ConsumeTask(mService, activity) {
-
+
@Override
protected void success(String ticket) {
-// godotPaymentV3.callbackSuccess("");
}
-
+
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
-
+
}
}.consume(sku);
}
-
-// godotPaymentV3.callbackSuccess(new PaymentsCache(activity).getConsumableValue("ticket", sku),signature);
-// godotPaymentV3.callbackSuccess(ticket);
- //validatePurchase(purchaseToken, sku);
}
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
-
}
@Override
protected void canceled() {
godotPaymentV3.callbackCancel();
-
}
}.handlePurchaseRequest(resultCode, data);
}
-
- public void validatePurchase(String purchaseToken, final String sku){
-
- new ValidateTask(activity, godotPaymentV3){
+
+ public void validatePurchase(String purchaseToken, final String sku) {
+
+ new ValidateTask(activity, godotPaymentV3) {
@Override
protected void success() {
-
+
new ConsumeTask(mService, activity) {
-
+
@Override
protected void success(String ticket) {
godotPaymentV3.callbackSuccess(ticket, null, sku);
-
}
-
+
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
-
}
}.consume(sku);
-
+
}
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
-
}
@Override
protected void canceled() {
godotPaymentV3.callbackCancel();
-
}
}.validatePurchase(sku);
}
-
- public void setAutoConsume(boolean autoConsume){
+
+ public void setAutoConsume(boolean autoConsume) {
auto_consume = autoConsume;
}
-
- public void consume(final String sku){
+
+ public void consume(final String sku) {
new ConsumeTask(mService, activity) {
-
+
@Override
protected void success(String ticket) {
godotPaymentV3.callbackSuccessProductMassConsumed(ticket, "", sku);
-
}
-
+
@Override
protected void error(String message) {
- godotPaymentV3.callbackFail();
-
+ godotPaymentV3.callbackFailConsume();
}
}.consume(sku);
}
-
+
+ // Workaround to bug where sometimes response codes come as Long instead of Integer
+ int getResponseCodeFromBundle(Bundle b) {
+ Object o = b.get("RESPONSE_CODE");
+ if (o == null) {
+ //logDebug("Bundle with null response code, assuming OK (known issue)");
+ return BILLING_RESPONSE_RESULT_OK;
+ } else if (o instanceof Integer) return ((Integer) o).intValue();
+ else if (o instanceof Long) return (int) ((Long) o).longValue();
+ else {
+ //logError("Unexpected type for bundle response code.");
+ //logError(o.getClass().getName());
+ throw new RuntimeException("Unexpected type for bundle response code: " + o.getClass().getName());
+ }
+ }
+
+ /**
+ * Returns a human-readable description for the given response code.
+ *
+ * @param code The response code
+ * @return A human-readable string explaining the result code.
+ * It also includes the result code numerically.
+ */
+ public static String getResponseDesc(int code) {
+ String[] iab_msgs = ("0:OK/1:User Canceled/2:Unknown/" +
+ "3:Billing Unavailable/4:Item unavailable/" +
+ "5:Developer Error/6:Error/7:Item Already Owned/" +
+ "8:Item not owned").split("/");
+ String[] iabhelper_msgs = ("0:OK/-1001:Remote exception during initialization/" +
+ "-1002:Bad response received/" +
+ "-1003:Purchase signature verification failed/" +
+ "-1004:Send intent failed/" +
+ "-1005:User cancelled/" +
+ "-1006:Unknown purchase response/" +
+ "-1007:Missing token/" +
+ "-1008:Unknown error/" +
+ "-1009:Subscriptions not available/" +
+ "-1010:Invalid consumption attempt").split("/");
+
+ if (code <= -1000) {
+ int index = -1000 - code;
+ if (index >= 0 && index < iabhelper_msgs.length) return iabhelper_msgs[index];
+ else return String.valueOf(code) + ":Unknown IAB Helper Error";
+ } else if (code < 0 || code >= iab_msgs.length)
+ return String.valueOf(code) + ":Unknown";
+ else
+ return iab_msgs[code];
+ }
+
+ public void querySkuDetails(final String[] list) {
+ (new Thread(new Runnable() {
+ @Override
+ public void run() {
+ ArrayList<String> skuList = new ArrayList<String>(Arrays.asList(list));
+ if (skuList.size() == 0) {
+ return;
+ }
+ // Split the sku list in blocks of no more than 20 elements.
+ ArrayList<ArrayList<String>> packs = new ArrayList<ArrayList<String>>();
+ ArrayList<String> tempList;
+ int n = skuList.size() / 20;
+ int mod = skuList.size() % 20;
+ for (int i = 0; i < n; i++) {
+ tempList = new ArrayList<String>();
+ for (String s : skuList.subList(i * 20, i * 20 + 20)) {
+ tempList.add(s);
+ }
+ packs.add(tempList);
+ }
+ if (mod != 0) {
+ tempList = new ArrayList<String>();
+ for (String s : skuList.subList(n * 20, n * 20 + mod)) {
+ tempList.add(s);
+ }
+ packs.add(tempList);
+
+ for (ArrayList<String> skuPartList : packs) {
+ Bundle querySkus = new Bundle();
+ querySkus.putStringArrayList("ITEM_ID_LIST", skuPartList);
+ Bundle skuDetails = null;
+ try {
+ skuDetails = mService.getSkuDetails(3, activity.getPackageName(), "inapp", querySkus);
+ if (!skuDetails.containsKey("DETAILS_LIST")) {
+ int response = getResponseCodeFromBundle(skuDetails);
+ if (response != BILLING_RESPONSE_RESULT_OK) {
+ godotPaymentV3.errorSkuDetail(getResponseDesc(response));
+ } else {
+ godotPaymentV3.errorSkuDetail("No error but no detail list.");
+ }
+ return;
+ }
+
+ ArrayList<String> responseList = skuDetails.getStringArrayList("DETAILS_LIST");
+
+ for (String thisResponse : responseList) {
+ Log.d("godot", "response = "+thisResponse);
+ godotPaymentV3.addSkuDetail(thisResponse);
+ }
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ godotPaymentV3.errorSkuDetail("RemoteException error!");
+ }
+ }
+ godotPaymentV3.completeSkuDetail();
+ }
+ }
+ })).start();
+ }
+
private GodotPaymentV3 godotPaymentV3;
-
+
public void setBaseSingleton(GodotPaymentV3 godotPaymentV3) {
this.godotPaymentV3 = godotPaymentV3;
}
}
-
diff --git a/platform/windows/godot_res.rc b/platform/windows/godot_res.rc
index 5f1e951e0f..b86869d316 100644
--- a/platform/windows/godot_res.rc
+++ b/platform/windows/godot_res.rc
@@ -3,12 +3,18 @@
#define _STR(m_x) #m_x
#define _MKSTR(m_x) _STR(m_x)
#endif
+#ifndef VERSION_PATCH
+#define VERSION_PATCH 0
+#define PATCH_STRING
+#else
+#define PATCH_STRING "." _MKSTR(VERSION_PATCH)
+#endif
GODOT_ICON ICON platform/windows/godot.ico
1 VERSIONINFO
-FILEVERSION VERSION_MAJOR,VERSION_MINOR,0,0
-PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,0,0
+FILEVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,0
+PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,0
FILEOS 4
FILETYPE 1
BEGIN
@@ -17,13 +23,13 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Godot Engine"
- VALUE "FileDescription", _MKSTR(VERSION_NAME) " Editor (" _MKSTR(VERSION_STATUS) ")"
- VALUE "FileVersion", _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "."_MKSTR(VERSION_REVISION)
+ VALUE "FileDescription", _MKSTR(VERSION_NAME) " Editor"
+ VALUE "FileVersion", _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "." _MKSTR(VERSION_PATCH)
VALUE "ProductName", _MKSTR(VERSION_NAME)
VALUE "Licence", "MIT"
VALUE "LegalCopyright", "Copyright (c) 2007-" _MKSTR(VERSION_YEAR) " Juan Linietsky, Ariel Manzur"
VALUE "Info", "http://www.godotengine.org"
- VALUE "ProductVersion", _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) "."_MKSTR(VERSION_REVISION)
+ VALUE "ProductVersion", _MKSTR(VERSION_MAJOR) "." _MKSTR(VERSION_MINOR) PATCH_STRING "." _MKSTR(VERSION_REVISION)
END
END
BLOCK "VarFileInfo"
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 6aee0d2399..571277f91e 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -1343,7 +1343,7 @@ void OS_Windows::vprint(const char* p_format, va_list p_list, bool p_stderr) {
void OS_Windows::alert(const String& p_alert,const String& p_title) {
if (!is_no_window_mode_enabled())
- MessageBoxW(NULL,p_alert.c_str(),p_title.c_str(),MB_OK|MB_ICONEXCLAMATION);
+ MessageBoxW(NULL, p_alert.c_str(), p_title.c_str(), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
else
print_line("ALERT: "+p_alert);
}
@@ -1476,6 +1476,7 @@ Point2 OS_Windows::get_window_position() const{
}
void OS_Windows::set_window_position(const Point2& p_position){
+ if (video_mode.fullscreen) return;
RECT r;
GetWindowRect(hWnd,&r);
MoveWindow(hWnd,p_position.x,p_position.y,r.right-r.left,r.bottom-r.top,TRUE);
diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp
index e9378b1d02..05136de5d6 100644
--- a/scene/2d/parallax_layer.cpp
+++ b/scene/2d/parallax_layer.cpp
@@ -123,26 +123,15 @@ void ParallaxLayer::set_base_offset_and_scale(const Point2& p_offset,float p_sca
Point2 new_ofs = ((orig_offset+p_offset)*motion_scale)*p_scale+motion_offset;
if (mirroring.x) {
-
- while( new_ofs.x>=0) {
- new_ofs.x -= mirroring.x*p_scale;
- }
- while(new_ofs.x < -mirroring.x*p_scale) {
- new_ofs.x += mirroring.x*p_scale;
- }
+ double den = mirroring.x*p_scale;
+ new_ofs.x -= den*ceil(new_ofs.x/den);
}
if (mirroring.y) {
-
- while( new_ofs.y>=0) {
- new_ofs.y -= mirroring.y*p_scale;
- }
- while(new_ofs.y < -mirroring.y*p_scale) {
- new_ofs.y += mirroring.y*p_scale;
- }
+ double den = mirroring.y*p_scale;
+ new_ofs.y -= den*ceil(new_ofs.y/den);
}
-
set_pos(new_ofs);
set_scale(Vector2(1,1)*p_scale);
diff --git a/scene/3d/baked_light_instance.cpp b/scene/3d/baked_light_instance.cpp
index fafa62866f..ca3a309568 100644
--- a/scene/3d/baked_light_instance.cpp
+++ b/scene/3d/baked_light_instance.cpp
@@ -60,6 +60,8 @@ void BakedLightInstance::set_baked_light(const Ref<BakedLight>& p_baked_light) {
// VS::get_singleton()->instance_geometry_set_baked_light(E->get()->get_instance(),baked_light.is_valid()?get_instance():RID());
// }
}
+
+ update_configuration_warning();
}
Ref<BakedLight> BakedLightInstance::get_baked_light() const{
@@ -77,6 +79,14 @@ DVector<Face3> BakedLightInstance::get_faces(uint32_t p_usage_flags) const {
}
+String BakedLightInstance::get_configuration_warning() const {
+ if (get_baked_light().is_null()) {
+ return TTR("BakedLightInstance does not contain a BakedLight resource.");
+ }
+ return String();
+}
+
+
void BakedLightInstance::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_baked_light","baked_light"),&BakedLightInstance::set_baked_light);
diff --git a/scene/3d/baked_light_instance.h b/scene/3d/baked_light_instance.h
index 92c2d50986..002e55df1d 100644
--- a/scene/3d/baked_light_instance.h
+++ b/scene/3d/baked_light_instance.h
@@ -55,6 +55,8 @@ public:
virtual AABB get_aabb() const;
virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const;
+ String get_configuration_warning() const;
+
BakedLightInstance();
};
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index d335399caa..6b43425edc 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -475,7 +475,7 @@ void FileDialog::update_filters() {
String flt=filters[i].get_slice(";",0).strip_edges();
String desc=filters[i].get_slice(";",1).strip_edges();
if (desc.length())
- filter->add_item(desc+" ( "+flt+" )");
+ filter->add_item(String(XL_MESSAGE(desc))+" ( "+flt+" )");
else
filter->add_item("( "+flt+" )");
}
@@ -498,6 +498,16 @@ void FileDialog::add_filter(const String& p_filter) {
}
+void FileDialog::set_filters(const Vector<String>& p_filters){
+ filters=p_filters;
+ update_filters();
+ invalidate();
+}
+
+Vector<String> FileDialog::get_filters() const{
+ return filters;
+}
+
String FileDialog::get_current_dir() const {
return dir->get_text();
@@ -686,6 +696,8 @@ void FileDialog::_bind_methods() {
ObjectTypeDB::bind_method(_MD("clear_filters"),&FileDialog::clear_filters);
ObjectTypeDB::bind_method(_MD("add_filter","filter"),&FileDialog::add_filter);
+ ObjectTypeDB::bind_method(_MD("set_filters","filters"),&FileDialog::set_filters);
+ ObjectTypeDB::bind_method(_MD("get_filters"),&FileDialog::get_filters);
ObjectTypeDB::bind_method(_MD("get_current_dir"),&FileDialog::get_current_dir);
ObjectTypeDB::bind_method(_MD("get_current_file"),&FileDialog::get_current_file);
ObjectTypeDB::bind_method(_MD("get_current_path"),&FileDialog::get_current_path);
@@ -722,6 +734,11 @@ void FileDialog::_bind_methods() {
BIND_CONSTANT( ACCESS_USERDATA );
BIND_CONSTANT( ACCESS_FILESYSTEM );
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"),_SCS("set_mode"),_SCS("get_mode") );
+ ADD_PROPERTY( PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"),_SCS("set_access"),_SCS("get_access") );
+ ADD_PROPERTY( PropertyInfo(Variant::STRING_ARRAY, "filters"),_SCS("set_filters"),_SCS("get_filters") );
+ ADD_PROPERTY( PropertyInfo(Variant::BOOL, "show_hidden_files"),_SCS("set_show_hidden_files"),_SCS("is_showing_hidden_files") );
+
}
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 1fcf8387ce..150b24cb3f 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -131,6 +131,8 @@ public:
void clear_filters();
void add_filter(const String& p_filter);
+ void set_filters(const Vector<String>& p_filters);
+ Vector<String> get_filters() const;
void set_enable_multiple_selection(bool p_enable);
Vector<String> get_selected_files() const;
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index d24c59a21f..adda54ad70 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -592,7 +592,9 @@ void GraphEdit::_input_event(const InputEvent& p_ev) {
if (p_ev.type==InputEvent::MOUSE_MOTION && dragging) {
just_selected=true;
- drag_accum+=Vector2(p_ev.mouse_motion.relative_x,p_ev.mouse_motion.relative_y);
+ // TODO: Remove local mouse pos hack if/when InputEventMouseMotion is fixed to support floats
+ //drag_accum+=Vector2(p_ev.mouse_motion.relative_x,p_ev.mouse_motion.relative_y);
+ drag_accum = get_local_mouse_pos() - drag_origin;
for(int i=get_child_count()-1;i>=0;i--) {
GraphNode *gn=get_child(i)->cast_to<GraphNode>();
if (gn && gn->is_selected())
@@ -709,6 +711,7 @@ void GraphEdit::_input_event(const InputEvent& p_ev) {
dragging = true;
drag_accum = Vector2();
+ drag_origin = get_local_mouse_pos();
just_selected = !gn->is_selected();
if(!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
for (int i = 0; i < get_child_count(); i++) {
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index 100b6e94ab..e97d6bcb74 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -92,6 +92,7 @@ private:
bool dragging;
bool just_selected;
Vector2 drag_accum;
+ Point2 drag_origin; // Workaround for GH-5907
float zoom;
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 5914ea222d..1efc9a1ceb 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -571,7 +571,12 @@ Color GraphNode::get_connection_output_color(int p_idx) {
void GraphNode::_input_event(const InputEvent& p_ev) {
if (p_ev.type==InputEvent::MOUSE_BUTTON) {
+
+ ERR_EXPLAIN("GraphNode must be the child of a GraphEdit node.");
+ ERR_FAIL_COND(get_parent_control() == NULL);
+
get_parent_control()->grab_focus();
+
if(p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) {
Vector2 mpos = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y);
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index 4c025e92df..ec89b7b690 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -334,7 +334,7 @@ int Label::get_longest_line_width() const {
}
} else {
- int char_width=font->get_char_size(current).width;
+ int char_width=font->get_char_size(current,text[i+1]).width;
line_width+=char_width;
}
@@ -454,7 +454,7 @@ void Label::regenerate_word_cache() {
word_pos=i;
}
- char_width=font->get_char_size(current).width;
+ char_width=font->get_char_size(current,text[i+1]).width;
current_word_size+=char_width;
line_width+=char_width;
total_char_cache++;
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 89c235e101..fcea12fd6b 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -468,7 +468,7 @@ void LineEdit::_input_event(InputEvent p_event) {
if (handled) {
accept_event();
- } else {
+ } else if (!k.mod.alt && !k.mod.command) {
if (k.unicode>=32 && k.scancode!=KEY_DELETE) {
if (editable) {
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 2b64d36a81..98e1a32aef 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -39,7 +39,7 @@ Size2 SpinBox::get_minimum_size() const {
void SpinBox::_value_changed(double) {
- String value = String::num(get_val(),Math::decimals(get_step()));
+ String value = String::num(get_val(),Math::step_decimals(get_step()));
if (prefix!="")
value=prefix+" "+value;
if (suffix!="")
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 50b44c55a9..b265ef840a 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -2993,6 +2993,34 @@ void TextEdit::adjust_viewport_to_cursor() {
}
+void TextEdit::center_viewport_to_cursor() {
+
+ if (cursor.line_ofs>cursor.line)
+ cursor.line_ofs=cursor.line;
+
+ int visible_width=cache.size.width-cache.style_normal->get_minimum_size().width-cache.line_number_w-cache.breakpoint_gutter_width;
+ if (v_scroll->is_visible())
+ visible_width-=v_scroll->get_combined_minimum_size().width;
+ visible_width-=20; // give it a little more space
+
+ int visible_rows = get_visible_rows();
+ if (h_scroll->is_visible())
+ visible_rows-=((h_scroll->get_combined_minimum_size().height-1)/get_row_height());
+
+ int max_ofs = text.size()-(scroll_past_end_of_file_enabled?1:visible_rows);
+ cursor.line_ofs=CLAMP(cursor.line-(visible_rows/2),0,max_ofs);
+
+ int cursor_x = get_column_x_offset( cursor.column, text[cursor.line] );
+
+ if (cursor_x>(cursor.x_ofs+visible_width))
+ cursor.x_ofs=cursor_x-visible_width+1;
+
+ if (cursor_x < cursor.x_ofs)
+ cursor.x_ofs=cursor_x;
+
+ update();
+}
+
void TextEdit::cursor_set_column(int p_col, bool p_adjust_viewport) {
if (p_col<0)
@@ -4480,6 +4508,7 @@ void TextEdit::_bind_methods() {
ObjectTypeDB::bind_method(_MD("menu_option"),&TextEdit::menu_option);
ObjectTypeDB::bind_method(_MD("get_menu:PopupMenu"),&TextEdit::get_menu);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), _SCS("set_syntax_coloring"), _SCS("is_syntax_coloring_enabled"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), _SCS("set_show_line_numbers"), _SCS("is_show_line_numbers_enabled"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), _SCS("set_highlight_all_occurrences"), _SCS("is_highlight_all_occurrences_enabled"));
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 65e9615911..c3bdf7c856 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -396,6 +396,8 @@ public:
}
void set_auto_indent(bool p_auto_indent);
+ void center_viewport_to_cursor();
+
void cursor_set_column(int p_col, bool p_adjust_viewport=true);
void cursor_set_line(int p_row, bool p_adjust_viewport=true);
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 82459ba0ab..487f62ed44 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -1179,8 +1179,8 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2&
Ref<Texture> updown = cache.updown;
- //String valtext = String::num( p_item->cells[i].val, Math::decimals( p_item->cells[i].step ) );
- String valtext = rtos( p_item->cells[i].val );
+ String valtext = String::num( p_item->cells[i].val, Math::step_decimals( p_item->cells[i].step ) );
+ //String valtext = rtos( p_item->cells[i].val );
font->draw( ci, text_pos, valtext, col, item_rect.size.x-updown->get_width());
if (!p_item->cells[i].editable)
@@ -1746,7 +1746,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
} else {
- editor_text=String::num( p_item->cells[col].val, Math::decimals( p_item->cells[col].step ) );
+ editor_text=String::num( p_item->cells[col].val, Math::step_decimals( p_item->cells[col].step ) );
if (select_mode==SELECT_MULTI && get_tree()->get_last_event_id() == focus_in_id)
bring_up_editor=false;
@@ -2521,7 +2521,7 @@ bool Tree::edit_selected() {
text_editor->set_pos( textedpos );
text_editor->set_size( rect.size);
text_editor->clear();
- text_editor->set_text( c.mode==TreeItem::CELL_MODE_STRING?c.text:rtos(c.val) );
+ text_editor->set_text( c.mode==TreeItem::CELL_MODE_STRING?c.text:String::num( c.val, Math::step_decimals( c.step ) ) );
text_editor->select_all();
if (c.mode==TreeItem::CELL_MODE_RANGE || c.mode==TreeItem::CELL_MODE_RANGE_EXPRESSION ) {
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 040d509286..9b79af32bf 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -105,6 +105,9 @@ Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_h
}
Error err = _parse_url(p_url);
+ if (err)
+ return err;
+
validate_ssl=p_ssl_validate_domain;
bool has_user_agent=false;
@@ -127,19 +130,52 @@ Error HTTPRequest::request(const String& p_url, const Vector<String>& p_custom_h
headers.push_back("Accept: */*");
}
+ requesting=true;
+
+ if (use_threads) {
- err = _request();
+ thread_done=false;
+ thread_request_quit=false;
+ client->set_blocking_mode(true);
+ thread=Thread::create(_thread_func,this);
+ } else {
+ client->set_blocking_mode(false);
+ err = _request();
+ if (err!=OK) {
+ call_deferred("_request_done",RESULT_CANT_CONNECT,0,StringArray(),ByteArray());
+ return ERR_CANT_CONNECT;
+ }
- if (err==OK) {
set_process(true);
- requesting=true;
+
}
- return err;
+ return OK;
}
+void HTTPRequest::_thread_func(void *p_userdata) {
+
+ HTTPRequest *hr = (HTTPRequest*)p_userdata;
+
+ Error err = hr->_request();
+
+ if (err!=OK) {
+ hr->call_deferred("_request_done",RESULT_CANT_CONNECT,0,StringArray(),ByteArray());
+ } else {
+ while(!hr->thread_request_quit) {
+
+ bool exit = hr->_update_connection();
+ if (exit)
+ break;
+ OS::get_singleton()->delay_usec(1);
+ }
+ }
+
+ hr->thread_done=true;
+}
+
void HTTPRequest::cancel_request() {
if (!requesting)
@@ -147,6 +183,11 @@ void HTTPRequest::cancel_request() {
if (!use_threads) {
set_process(false);
+ } else {
+ thread_request_quit=true;
+ Thread::wait_to_finish(thread);
+ memdelete(thread);
+ thread=NULL;
}
if (file) {
@@ -167,7 +208,7 @@ void HTTPRequest::cancel_request() {
bool HTTPRequest::_handle_response(bool *ret_value) {
if (!client->has_response()) {
- call_deferred("emit_signal","request_completed",RESULT_NO_RESPONSE,0,StringArray(),ByteArray());
+ call_deferred("_request_done",RESULT_NO_RESPONSE,0,StringArray(),ByteArray());
*ret_value=true;
return true;
}
@@ -187,7 +228,7 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
//redirect
if (max_redirects>=0 && redirections>=max_redirects) {
- call_deferred("emit_signal","request_completed",RESULT_REDIRECT_LIMIT_REACHED,response_code,response_headers,ByteArray());
+ call_deferred("_request_done",RESULT_REDIRECT_LIMIT_REACHED,response_code,response_headers,ByteArray());
*ret_value=true;
return true;
}
@@ -239,7 +280,8 @@ bool HTTPRequest::_update_connection() {
switch( client->get_status() ) {
case HTTPClient::STATUS_DISCONNECTED: {
- return true; //end it, since it's doing something
+ call_deferred("_request_done",RESULT_CANT_CONNECT,0,StringArray(),ByteArray());
+ return true; //end it, since it's doing something
} break;
case HTTPClient::STATUS_RESOLVING: {
client->poll();
@@ -247,7 +289,7 @@ bool HTTPRequest::_update_connection() {
return false;
} break;
case HTTPClient::STATUS_CANT_RESOLVE: {
- call_deferred("emit_signal","request_completed",RESULT_CANT_RESOLVE,0,StringArray(),ByteArray());
+ call_deferred("_request_done",RESULT_CANT_RESOLVE,0,StringArray(),ByteArray());
return true;
} break;
@@ -258,7 +300,7 @@ bool HTTPRequest::_update_connection() {
} break; //connecting to ip
case HTTPClient::STATUS_CANT_CONNECT: {
- call_deferred("emit_signal","request_completed",RESULT_CANT_CONNECT,0,StringArray(),ByteArray());
+ call_deferred("_request_done",RESULT_CANT_CONNECT,0,StringArray(),ByteArray());
return true;
} break;
@@ -276,17 +318,17 @@ bool HTTPRequest::_update_connection() {
return ret_value;
- call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,ByteArray());
+ call_deferred("_request_done",RESULT_SUCCESS,response_code,response_headers,ByteArray());
return true;
}
if (got_response && body_len<0) {
//chunked transfer is done
- call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,body);
+ call_deferred("_request_done",RESULT_SUCCESS,response_code,response_headers,body);
return true;
}
- call_deferred("emit_signal","request_completed",RESULT_CHUNKED_BODY_SIZE_MISMATCH,response_code,response_headers,ByteArray());
+ call_deferred("_request_done",RESULT_CHUNKED_BODY_SIZE_MISMATCH,response_code,response_headers,ByteArray());
return true;
//request migh have been done
} else {
@@ -294,7 +336,7 @@ bool HTTPRequest::_update_connection() {
Error err = client->request(HTTPClient::METHOD_GET,request_string,headers);
if (err!=OK) {
- call_deferred("emit_signal","request_completed",RESULT_CONNECTION_ERROR,0,StringArray(),ByteArray());
+ call_deferred("_request_done",RESULT_CONNECTION_ERROR,0,StringArray(),ByteArray());
return true;
}
@@ -320,7 +362,7 @@ bool HTTPRequest::_update_connection() {
if (!client->is_response_chunked() && client->get_response_body_length()==0) {
- call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,ByteArray());
+ call_deferred("_request_done",RESULT_SUCCESS,response_code,response_headers,ByteArray());
return true;
}
@@ -331,7 +373,7 @@ bool HTTPRequest::_update_connection() {
body_len=client->get_response_body_length();
if (body_size_limit>=0 && body_len>body_size_limit) {
- call_deferred("emit_signal","request_completed",RESULT_BODY_SIZE_LIMIT_EXCEEDED,response_code,response_headers,ByteArray());
+ call_deferred("_request_done",RESULT_BODY_SIZE_LIMIT_EXCEEDED,response_code,response_headers,ByteArray());
return true;
}
}
@@ -340,7 +382,8 @@ bool HTTPRequest::_update_connection() {
file=FileAccess::open(download_to_file,FileAccess::WRITE);
if (!file) {
- call_deferred("emit_signal","request_completed",RESULT_DOWNLOAD_FILE_CANT_OPEN,response_code,response_headers,ByteArray());
+ call_deferred("_request_done",RESULT_DOWNLOAD_FILE_CANT_OPEN,response_code,response_headers,ByteArray());
+ return true;
}
}
}
@@ -356,7 +399,7 @@ bool HTTPRequest::_update_connection() {
ByteArray::Read r=chunk.read();
file->store_buffer(r.ptr(),chunk.size());
if (file->get_error()!=OK) {
- call_deferred("emit_signal","request_completed",RESULT_DOWNLOAD_FILE_WRITE_ERROR,response_code,response_headers,ByteArray());
+ call_deferred("_request_done",RESULT_DOWNLOAD_FILE_WRITE_ERROR,response_code,response_headers,ByteArray());
return true;
}
} else {
@@ -364,18 +407,18 @@ bool HTTPRequest::_update_connection() {
}
if (body_size_limit>=0 && downloaded>body_size_limit) {
- call_deferred("emit_signal","request_completed",RESULT_BODY_SIZE_LIMIT_EXCEEDED,response_code,response_headers,ByteArray());
+ call_deferred("_request_done",RESULT_BODY_SIZE_LIMIT_EXCEEDED,response_code,response_headers,ByteArray());
return true;
}
if (body_len>=0) {
if (downloaded==body_len) {
- call_deferred("emit_signal","request_completed",RESULT_SUCCESS,response_code,response_headers,body);
+ call_deferred("_request_done",RESULT_SUCCESS,response_code,response_headers,body);
return true;
}
/*if (body.size()>=body_len) {
- call_deferred("emit_signal","request_completed",RESULT_BODY_SIZE_MISMATCH,response_code,response_headers,ByteArray());
+ call_deferred("_request_done",RESULT_BODY_SIZE_MISMATCH,response_code,response_headers,ByteArray());
return true;
}*/
}
@@ -384,11 +427,11 @@ bool HTTPRequest::_update_connection() {
} break; // request resulted in body: { } break which must be read
case HTTPClient::STATUS_CONNECTION_ERROR: {
- call_deferred("emit_signal","request_completed",RESULT_CONNECTION_ERROR,0,StringArray(),ByteArray());
+ call_deferred("_request_done",RESULT_CONNECTION_ERROR,0,StringArray(),ByteArray());
return true;
} break;
case HTTPClient::STATUS_SSL_HANDSHAKE_ERROR: {
- call_deferred("emit_signal","request_completed",RESULT_SSL_HANDSHAKE_ERROR,0,StringArray(),ByteArray());
+ call_deferred("_request_done",RESULT_SSL_HANDSHAKE_ERROR,0,StringArray(),ByteArray());
return true;
} break;
@@ -397,17 +440,35 @@ bool HTTPRequest::_update_connection() {
ERR_FAIL_V(false);
}
+
+void HTTPRequest::_request_done(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data) {
+
+
+ cancel_request();
+ emit_signal("request_completed",p_status,p_code,headers,p_data);
+}
+
+
void HTTPRequest::_notification(int p_what) {
if (p_what==NOTIFICATION_PROCESS) {
+ if (use_threads)
+ return;
bool done = _update_connection();
if (done) {
set_process(false);
+ //cancel_request(); called from _request done now
+ }
+ }
+
+ if (p_what==NOTIFICATION_EXIT_TREE) {
+ if (requesting) {
cancel_request();
}
}
+
}
void HTTPRequest::set_use_threads(bool p_use) {
@@ -491,6 +552,7 @@ void HTTPRequest::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_body_size"),&HTTPRequest::get_body_size);
ObjectTypeDB::bind_method(_MD("_redirect_request"),&HTTPRequest::_redirect_request);
+ ObjectTypeDB::bind_method(_MD("_request_done"),&HTTPRequest::_request_done);
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"use_threads"),_SCS("set_use_threads"),_SCS("is_using_threads"));
ADD_PROPERTY(PropertyInfo(Variant::INT,"body_size_limit",PROPERTY_HINT_RANGE,"-1,2000000000"),_SCS("set_body_size_limit"),_SCS("get_body_size_limit"));
@@ -517,6 +579,7 @@ void HTTPRequest::_bind_methods() {
HTTPRequest::HTTPRequest()
{
+ thread=NULL;
port=80;
redirections=0;
@@ -530,6 +593,7 @@ HTTPRequest::HTTPRequest()
requesting=false;
client.instance();
use_threads=false;
+ thread_done=false;
body_size_limit=-1;
file=NULL;
status=HTTPClient::STATUS_DISCONNECTED;
diff --git a/scene/main/http_request.h b/scene/main/http_request.h
index 7c3ccb2eb9..8dd433982b 100644
--- a/scene/main/http_request.h
+++ b/scene/main/http_request.h
@@ -32,6 +32,7 @@
#include "node.h"
#include "io/http_client.h"
#include "os/file_access.h"
+#include "os/thread.h"
class HTTPRequest : public Node {
@@ -69,7 +70,7 @@ private:
bool request_sent;
Ref<HTTPClient> client;
ByteArray body;
- bool use_threads;
+ volatile bool use_threads;
bool got_response;
int response_code;
@@ -80,7 +81,7 @@ private:
FileAccess *file;
int body_len;
- int downloaded;
+ volatile int downloaded;
int body_size_limit;
int redirections;
@@ -93,11 +94,19 @@ private:
void _redirect_request(const String& p_new_url);
+
bool _handle_response(bool *ret_value);
Error _parse_url(const String& p_url);
Error _request();
+ volatile bool thread_done;
+ volatile bool thread_request_quit;
+
+ Thread *thread;
+
+ void _request_done(int p_status, int p_code, const StringArray& headers, const ByteArray& p_data);
+ static void _thread_func(void *p_userdata);
protected:
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index bdb2754e5e..7970229c06 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1782,7 +1782,6 @@ void Viewport::_gui_input_event(InputEvent p_event) {
if (top->data.modal_exclusive || top->data.modal_frame==OS::get_singleton()->get_frames_drawn()) {
//cancel event, sorry, modal exclusive EATS UP ALL
//alternative, you can't pop out a window the same frame it was made modal (fixes many issues)
- //get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
get_tree()->set_input_as_handled();
return; // no one gets the event if exclusive NO ONE
}
@@ -2034,8 +2033,22 @@ void Viewport::_gui_input_event(InputEvent p_event) {
}
+ bool is_tooltip_shown = false;
- if (can_tooltip) {
+ if (gui.tooltip_popup) {
+ if (can_tooltip) {
+ String tooltip = over->get_tooltip(gui.tooltip->get_global_transform().xform_inv(mpos));
+
+ if (tooltip.length() == 0)
+ _gui_cancel_tooltip();
+ else if (tooltip == gui.tooltip_label->get_text())
+ is_tooltip_shown = true;
+ }
+ else
+ _gui_cancel_tooltip();
+ }
+
+ if (can_tooltip && !is_tooltip_shown) {
gui.tooltip=over;
gui.tooltip_pos=mpos;//(parent_xform * get_transform()).affine_inverse().xform(pos);
@@ -2062,7 +2075,6 @@ void Viewport::_gui_input_event(InputEvent p_event) {
- //get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
get_tree()->set_input_as_handled();
@@ -2083,6 +2095,7 @@ void Viewport::_gui_input_event(InputEvent p_event) {
} break;
case InputEvent::ACTION:
case InputEvent::JOYSTICK_BUTTON:
+ case InputEvent::JOYSTICK_MOTION:
case InputEvent::KEY: {
@@ -2102,7 +2115,7 @@ void Viewport::_gui_input_event(InputEvent p_event) {
if (gui.key_event_accepted) {
- get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
+ get_tree()->set_input_as_handled();
break;
}
}
@@ -2162,7 +2175,7 @@ void Viewport::_gui_input_event(InputEvent p_event) {
if (next) {
next->grab_focus();
- get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_cancel_input_ID",p_event.ID);
+ get_tree()->set_input_as_handled();
}
}
@@ -2355,8 +2368,7 @@ void Viewport::_gui_control_grab_focus(Control* p_control) {
if (gui.key_focus && gui.key_focus==p_control)
return;
- _gui_remove_focus();
- get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"windows","_gui_remove_focus");
+ get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,"_viewports","_gui_remove_focus");
gui.key_focus=p_control;
p_control->notification(Control::NOTIFICATION_FOCUS_ENTER);
p_control->update();
@@ -2664,6 +2676,7 @@ void Viewport::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_input_disabled"), &Viewport::is_input_disabled);
ObjectTypeDB::bind_method(_MD("_gui_show_tooltip"), &Viewport::_gui_show_tooltip);
+ ObjectTypeDB::bind_method(_MD("_gui_remove_focus"), &Viewport::_gui_remove_focus);
ADD_PROPERTY( PropertyInfo(Variant::RECT2,"rect"), _SCS("set_rect"), _SCS("get_rect") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"own_world"), _SCS("set_use_own_world"), _SCS("is_using_own_world") );
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index 88ff09e961..29460790ff 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -644,7 +644,7 @@ Vector2 Curve2D::interpolate_baked(float p_offset,bool p_cubic) const{
if (p_offset>=baked_max_ofs)
return r[bpc-1];
- int idx = Math::floor(p_offset/bake_interval);
+ int idx = Math::floor((double)p_offset/(double)bake_interval);
float frac = Math::fmod(p_offset,bake_interval);
if (idx>=bpc-1) {
@@ -1117,7 +1117,7 @@ Vector3 Curve3D::interpolate_baked(float p_offset,bool p_cubic) const{
if (p_offset>=baked_max_ofs)
return r[bpc-1];
- int idx = Math::floor(p_offset/bake_interval);
+ int idx = Math::floor((double)p_offset/(double)bake_interval);
float frac = Math::fmod(p_offset,bake_interval);
if (idx>=bpc-1) {
@@ -1161,7 +1161,7 @@ float Curve3D::interpolate_baked_tilt(float p_offset) const{
if (p_offset>=baked_max_ofs)
return r[bpc-1];
- int idx = Math::floor(p_offset/bake_interval);
+ int idx = Math::floor((double)p_offset/(double)bake_interval);
float frac = Math::fmod(p_offset,bake_interval);
if (idx>=bpc-1) {
diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp
index 67587a8f8b..679c8a000c 100644
--- a/scene/resources/dynamic_font.cpp
+++ b/scene/resources/dynamic_font.cpp
@@ -30,13 +30,22 @@
#include "dynamic_font.h"
#include "os/file_access.h"
+bool DynamicFontData::CacheID::operator< (CacheID right) const{
+
+ if (size<right.size)
+ return true;
+ if (mipmaps != right.mipmaps)
+ return right.mipmaps;
+ if (filter != right.filter)
+ return right.filter;
+ return false;
+}
-
-Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(int p_size) {
+Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(CacheID p_id){
- if (size_cache.has(p_size)) {
- return Ref<DynamicFontAtSize>( size_cache[p_size] );
+ if (size_cache.has(p_id)) {
+ return Ref<DynamicFontAtSize>( size_cache[p_id] );
}
@@ -46,9 +55,8 @@ Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(int p_size) {
dfas->font=Ref<DynamicFontData>( this );
- size_cache[p_size]=dfas.ptr();
-
- dfas->size=p_size;
+ size_cache[p_id]=dfas.ptr();
+ dfas->id=p_id;
dfas->_load();
return dfas;
@@ -169,11 +177,16 @@ Error DynamicFontAtSize::_load() {
ERR_FAIL_COND_V( error, ERR_INVALID_PARAMETER );
}*/
- error = FT_Set_Pixel_Sizes(face,0,size);
+ error = FT_Set_Pixel_Sizes(face,0,id.size);
ascent=face->size->metrics.ascender>>6;
descent=-face->size->metrics.descender>>6;
linegap=0;
+ texture_flags=0;
+ if (id.mipmaps)
+ texture_flags|=Texture::FLAG_MIPMAPS;
+ if (id.filter)
+ texture_flags|=Texture::FLAG_FILTER;
//print_line("ASCENT: "+itos(ascent)+" descent "+itos(descent)+" hinted: "+itos(face->face_flags&FT_FACE_FLAG_HINTER));
@@ -270,6 +283,15 @@ Size2 DynamicFontAtSize::get_char_size(CharType p_char,CharType p_next,const Vec
return ret;
}
+void DynamicFontAtSize::set_texture_flags(uint32_t p_flags){
+
+ texture_flags=p_flags;
+ for(int i=0;i<textures.size();i++) {
+ Ref<ImageTexture> &tex = textures[i].texture;
+ if (!tex.is_null())
+ tex->set_flags(p_flags);
+ }
+}
float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2& p_pos, CharType p_char,CharType p_next,const Color& p_modulate,const Vector<Ref<DynamicFontAtSize> >& p_fallbacks) const {
@@ -496,7 +518,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
tex_x = 0;
tex_y = 0;
- int texsize = MAX(size*8,256);
+ int texsize = MAX(id.size*8,256);
if (mw>texsize)
texsize=mw; //special case, adapt to it?
if (mh>texsize)
@@ -555,7 +577,7 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
if (tex.texture.is_null()) {
tex.texture.instance();
- tex.texture->create_from_image(img,Texture::FLAG_VIDEO_SURFACE);
+ tex.texture->create_from_image(img,Texture::FLAG_VIDEO_SURFACE|texture_flags);
} else {
tex.texture->set_data(img); //update
}
@@ -595,25 +617,39 @@ DynamicFontAtSize::DynamicFontAtSize() {
ascent=1;
descent=1;
linegap=1;
+ texture_flags=0;
}
DynamicFontAtSize::~DynamicFontAtSize(){
if (valid) {
FT_Done_FreeType( library );
- font->size_cache.erase(size);
+ font->size_cache.erase(id);
}
}
/////////////////////////
+void DynamicFont::_reload_cache(){
+
+ ERR_FAIL_COND(cache_id.size<1);
+ if (!data.is_valid())
+ return;
+ data_at_size=data->_get_dynamic_font_at_size(cache_id);
+ for (int i=0;i<fallbacks.size();i++){
+ fallback_data_at_size[i]=fallbacks[i]->_get_dynamic_font_at_size(cache_id);
+ }
+
+ emit_changed();
+ _change_notify();
+}
void DynamicFont::set_font_data(const Ref<DynamicFontData>& p_data) {
data=p_data;
if (data.is_valid())
- data_at_size=data->_get_dynamic_font_at_size(size);
+ data_at_size=data->_get_dynamic_font_at_size(cache_id);
else
data_at_size=Ref<DynamicFontAtSize>();
@@ -628,23 +664,72 @@ Ref<DynamicFontData> DynamicFont::get_font_data() const{
void DynamicFont::set_size(int p_size){
- if (size==p_size)
+ if (cache_id.size==p_size)
return;
- size=p_size;
- ERR_FAIL_COND(p_size<1);
- if (!data.is_valid())
+ cache_id.size=p_size;
+ _reload_cache();
+}
+
+int DynamicFont::get_size() const{
+
+ return cache_id.size;
+}
+
+bool DynamicFont::get_use_mipmaps() const{
+
+ return cache_id.mipmaps;
+}
+
+void DynamicFont::set_use_mipmaps(bool p_enable){
+
+ if (cache_id.mipmaps==p_enable)
return;
- data_at_size=data->_get_dynamic_font_at_size(size);
- for(int i=0;i<fallbacks.size();i++) {
- fallback_data_at_size[i]=fallbacks[i]->_get_dynamic_font_at_size(size);
+ cache_id.mipmaps=p_enable;
+ _reload_cache();
+}
+
+bool DynamicFont::get_use_filter() const{
+
+ return cache_id.filter;
+}
+
+void DynamicFont::set_use_filter(bool p_enable){
+
+ if (cache_id.filter==p_enable)
+ return;
+ cache_id.filter=p_enable;
+ _reload_cache();
+}
+
+int DynamicFont::get_spacing(int p_type) const{
+
+ if (p_type == SPACING_TOP){
+ return spacing_top;
+ }else if (p_type == SPACING_BOTTOM){
+ return spacing_bottom;
+ }else if (p_type == SPACING_CHAR){
+ return spacing_char;
+ }else if (p_type == SPACING_SPACE){
+ return spacing_space;
}
- emit_changed();
- _change_notify();
+ return 0;
}
-int DynamicFont::get_size() const{
- return size;
+void DynamicFont::set_spacing(int p_type, int p_value){
+
+ if (p_type == SPACING_TOP){
+ spacing_top=p_value;
+ }else if (p_type == SPACING_BOTTOM){
+ spacing_bottom=p_value;
+ }else if (p_type == SPACING_CHAR){
+ spacing_char=p_value;
+ }else if (p_type == SPACING_SPACE){
+ spacing_space=p_value;
+ }
+
+ emit_changed();
+ _change_notify();
}
float DynamicFont::get_height() const{
@@ -652,7 +737,7 @@ float DynamicFont::get_height() const{
if (!data_at_size.is_valid())
return 1;
- return data_at_size->get_height();
+ return data_at_size->get_height()+spacing_top+spacing_bottom;
}
float DynamicFont::get_ascent() const{
@@ -660,7 +745,7 @@ float DynamicFont::get_ascent() const{
if (!data_at_size.is_valid())
return 1;
- return data_at_size->get_ascent();
+ return data_at_size->get_ascent()+spacing_top;
}
float DynamicFont::get_descent() const{
@@ -668,7 +753,7 @@ float DynamicFont::get_descent() const{
if (!data_at_size.is_valid())
return 1;
- return data_at_size->get_descent();
+ return data_at_size->get_descent()+spacing_bottom;
}
@@ -677,7 +762,13 @@ Size2 DynamicFont::get_char_size(CharType p_char,CharType p_next) const{
if (!data_at_size.is_valid())
return Size2(1,1);
- return data_at_size->get_char_size(p_char,p_next,fallback_data_at_size);
+ Size2 ret=data_at_size->get_char_size(p_char,p_next,fallback_data_at_size);
+ if (p_char==' ')
+ ret.width+=spacing_space+spacing_char;
+ else if (p_next)
+ ret.width+=spacing_char;
+
+ return ret;
}
@@ -691,7 +782,7 @@ float DynamicFont::draw_char(RID p_canvas_item, const Point2& p_pos, CharType p_
if (!data_at_size.is_valid())
return 0;
- return data_at_size->draw_char(p_canvas_item,p_pos,p_char,p_next,p_modulate,fallback_data_at_size);
+ return data_at_size->draw_char(p_canvas_item,p_pos,p_char,p_next,p_modulate,fallback_data_at_size)+spacing_char;
}
void DynamicFont::set_fallback(int p_idx,const Ref<DynamicFontData>& p_data) {
@@ -699,7 +790,7 @@ void DynamicFont::set_fallback(int p_idx,const Ref<DynamicFontData>& p_data) {
ERR_FAIL_COND(p_data.is_null());
ERR_FAIL_INDEX(p_idx,fallbacks.size());
fallbacks[p_idx]=p_data;
- fallback_data_at_size[p_idx]=fallbacks[p_idx]->_get_dynamic_font_at_size(size);
+ fallback_data_at_size[p_idx]=fallbacks[p_idx]->_get_dynamic_font_at_size(cache_id);
}
@@ -707,7 +798,7 @@ void DynamicFont::add_fallback(const Ref<DynamicFontData>& p_data) {
ERR_FAIL_COND(p_data.is_null());
fallbacks.push_back(p_data);
- fallback_data_at_size.push_back(fallbacks[fallbacks.size()-1]->_get_dynamic_font_at_size(size)); //const..
+ fallback_data_at_size.push_back(fallbacks[fallbacks.size()-1]->_get_dynamic_font_at_size(cache_id)); //const..
_change_notify();
emit_changed();
@@ -794,6 +885,13 @@ void DynamicFont::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_size","data"),&DynamicFont::set_size);
ObjectTypeDB::bind_method(_MD("get_size"),&DynamicFont::get_size);
+ ObjectTypeDB::bind_method(_MD("set_use_mipmaps","enable"),&DynamicFont::set_use_mipmaps);
+ ObjectTypeDB::bind_method(_MD("get_use_mipmaps"),&DynamicFont::get_use_mipmaps);
+ ObjectTypeDB::bind_method(_MD("set_use_filter","enable"),&DynamicFont::set_use_filter);
+ ObjectTypeDB::bind_method(_MD("get_use_filter"),&DynamicFont::get_use_filter);
+ ObjectTypeDB::bind_method(_MD("set_spacing","type","value"),&DynamicFont::set_spacing);
+ ObjectTypeDB::bind_method(_MD("get_spacing","type"),&DynamicFont::get_spacing);
+
ObjectTypeDB::bind_method(_MD("add_fallback","data:DynamicFontData"),&DynamicFont::add_fallback);
ObjectTypeDB::bind_method(_MD("set_fallback","idx","data:DynamicFontData"),&DynamicFont::set_fallback);
ObjectTypeDB::bind_method(_MD("get_fallback:DynamicFontData","idx"),&DynamicFont::get_fallback);
@@ -802,12 +900,26 @@ void DynamicFont::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT,"font/size"),_SCS("set_size"),_SCS("get_size"));
+ ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing/top"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_TOP);
+ ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing/bottom"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_BOTTOM);
+ ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing/char"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_CHAR);
+ ADD_PROPERTYINZ(PropertyInfo(Variant::INT,"extra_spacing/space"),_SCS("set_spacing"),_SCS("get_spacing"),SPACING_SPACE);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"font/use_mipmaps"),_SCS("set_use_mipmaps"),_SCS("get_use_mipmaps"));
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"font/use_filter"),_SCS("set_use_filter"),_SCS("get_use_filter"));
ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"font/font",PROPERTY_HINT_RESOURCE_TYPE,"DynamicFontData"),_SCS("set_font_data"),_SCS("get_font_data"));
+
+ BIND_CONSTANT( SPACING_TOP );
+ BIND_CONSTANT( SPACING_BOTTOM );
+ BIND_CONSTANT( SPACING_CHAR );
+ BIND_CONSTANT( SPACING_SPACE );
}
DynamicFont::DynamicFont() {
- size=16;
+ spacing_top=0;
+ spacing_bottom=0;
+ spacing_char=0;
+ spacing_space=0;
}
DynamicFont::~DynamicFont() {
diff --git a/scene/resources/dynamic_font.h b/scene/resources/dynamic_font.h
index 9ad1b4edbf..4ae58ab0dd 100644
--- a/scene/resources/dynamic_font.h
+++ b/scene/resources/dynamic_font.h
@@ -45,21 +45,32 @@ class DynamicFontData : public Resource {
OBJ_TYPE(DynamicFontData,Resource);
+public:
+
+ struct CacheID{
+
+ int size;
+ bool mipmaps;
+ bool filter;
+
+ bool operator< (CacheID right) const;
+ CacheID() { size=16; mipmaps=false; filter=false; }
+ };
+private:
const uint8_t *font_mem;
int font_mem_size;
bool force_autohinter;
String font_path;
- Map<int,DynamicFontAtSize*> size_cache;
+ Map<CacheID,DynamicFontAtSize*> size_cache;
friend class DynamicFontAtSize;
friend class DynamicFont;
-
- Ref<DynamicFontAtSize> _get_dynamic_font_at_size(int p_size);
+ Ref<DynamicFontAtSize> _get_dynamic_font_at_size(CacheID p_cache);
protected:
static void _bind_methods();
@@ -90,6 +101,8 @@ class DynamicFontAtSize : public Reference {
int linegap;
int rect_margin;
+ uint32_t texture_flags;
+
bool valid;
struct CharTexture {
@@ -124,7 +137,7 @@ class DynamicFontAtSize : public Reference {
friend class DynamicFontData;
Ref<DynamicFontData> font;
- int size;
+ DynamicFontData::CacheID id;
@@ -145,7 +158,7 @@ public:
float draw_char(RID p_canvas_item, const Point2& p_pos, CharType p_char,CharType p_next,const Color& p_modulate,const Vector<Ref<DynamicFontAtSize> >& p_fallbacks) const;
-
+ void set_texture_flags(uint32_t p_flags);
DynamicFontAtSize();
~DynamicFontAtSize();
@@ -157,18 +170,35 @@ class DynamicFont : public Font {
OBJ_TYPE( DynamicFont, Font );
- Ref<DynamicFontData> data;
+public:
+
+ enum SpacingType{
+ SPACING_TOP,
+ SPACING_BOTTOM,
+ SPACING_CHAR,
+ SPACING_SPACE
+ };
+
+private:
+
+ Ref<DynamicFontData> data;
Ref<DynamicFontAtSize> data_at_size;
Vector< Ref<DynamicFontData> > fallbacks;
Vector< Ref<DynamicFontAtSize> > fallback_data_at_size;
- int size;
+ DynamicFontData::CacheID cache_id;
bool valid;
+ int spacing_top;
+ int spacing_bottom;
+ int spacing_char;
+ int spacing_space;
protected:
+ void _reload_cache();
+
bool _set(const StringName& p_name, const Variant& p_value);
bool _get(const StringName& p_name,Variant &r_ret) const;
void _get_property_list( List<PropertyInfo> *p_list) const;
@@ -183,6 +213,14 @@ public:
void set_size(int p_size);
int get_size() const;
+ bool get_use_mipmaps() const;
+ void set_use_mipmaps(bool p_enable);
+
+ bool get_use_filter() const;
+ void set_use_filter(bool p_enable);
+
+ int get_spacing(int p_type) const;
+ void set_spacing(int p_type, int p_value);
void add_fallback(const Ref<DynamicFontData>& p_data);
void set_fallback(int p_idx,const Ref<DynamicFontData>& p_data);
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index 6b329a1a73..4c963da5b4 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -407,7 +407,7 @@ World2D::World2D() {
Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY,GLOBAL_DEF("physics_2d/default_gravity",98));
Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY_VECTOR,GLOBAL_DEF("physics_2d/default_gravity_vector",Vector2(0,1)));
// TODO: Remove this deprecation warning and compatibility code for 2.2 or 3.0
- if (Globals::get_singleton()->get("physics_2d/default_density") && !Globals::get_singleton()->get("physics_2d/default_linear_damp)")) {
+ if (Globals::get_singleton()->get("physics_2d/default_density") && !Globals::get_singleton()->get("physics_2d/default_linear_damp")) {
WARN_PRINT("Deprecated parameter 'physics_2d/default_density'. It was renamed to 'physics_2d/default_linear_damp', adjusting your project settings accordingly (make sure to adjust scripts that potentially rely on 'physics_2d/default_density'.");
Globals::get_singleton()->set("physics_2d/default_linear_damp", Globals::get_singleton()->get("physics_2d/default_density"));
Globals::get_singleton()->set_persisting("physics_2d/default_linear_damp", true);
diff --git a/servers/audio/audio_mixer_sw.h b/servers/audio/audio_mixer_sw.h
index 950ed19af6..e924b518cc 100644
--- a/servers/audio/audio_mixer_sw.h
+++ b/servers/audio/audio_mixer_sw.h
@@ -69,8 +69,7 @@ private:
MIX_VOLRAMP_FRAC_MASK=MIX_VOLRAMP_FRAC_LEN-1,
MIX_FILTER_FRAC_BITS=16,
MIX_FILTER_RAMP_FRAC_BITS=8,
- MIX_VOL_MOVE_TO_24=4,
- MAX_REVERBS=4
+ MIX_VOL_MOVE_TO_24=4
};
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 50194af4a5..9e21e6b183 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -65,7 +65,8 @@ public:
REVERB_SMALL,
REVERB_MEDIUM,
REVERB_LARGE,
- REVERB_HALL
+ REVERB_HALL,
+ MAX_REVERBS
};
virtual ChannelID channel_alloc(RID p_sample)=0;
diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp
index 3202e52abb..43e52f26e8 100644
--- a/servers/physics/body_pair_sw.cpp
+++ b/servers/physics/body_pair_sw.cpp
@@ -323,13 +323,13 @@ bool BodyPairSW::setup(float p_step) {
#endif
if (A->can_report_contacts()) {
- Vector3 crB = A->get_angular_velocity().cross( c.rA ) + A->get_linear_velocity();
- A->add_contact(global_A,-c.normal,depth,shape_A,global_B,shape_B,B->get_instance_id(),B->get_self(),crB);
+ Vector3 crA = A->get_angular_velocity().cross( c.rA ) + A->get_linear_velocity();
+ A->add_contact(global_A,-c.normal,depth,shape_A,global_B,shape_B,B->get_instance_id(),B->get_self(),crA);
}
if (B->can_report_contacts()) {
- Vector3 crA = A->get_angular_velocity().cross( c.rB ) + A->get_linear_velocity();
- B->add_contact(global_B,c.normal,depth,shape_B,global_A,shape_A,A->get_instance_id(),A->get_self(),crA);
+ Vector3 crB = B->get_angular_velocity().cross( c.rB ) + B->get_linear_velocity();
+ B->add_contact(global_B,c.normal,depth,shape_B,global_A,shape_A,A->get_instance_id(),A->get_self(),crB);
}
if (A->is_shape_set_as_trigger(shape_A) || B->is_shape_set_as_trigger(shape_B) || (A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC)) {
diff --git a/tools/editor/asset_library_editor_plugin.cpp b/tools/editor/asset_library_editor_plugin.cpp
index 4f685badfb..3fd5d2b5d1 100644
--- a/tools/editor/asset_library_editor_plugin.cpp
+++ b/tools/editor/asset_library_editor_plugin.cpp
@@ -134,13 +134,13 @@ EditorAssetLibraryItem::EditorAssetLibraryItem() {
category = memnew( LinkButton );
category->set_text("Editor Tools");
category->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- title->connect("pressed",this,"_category_clicked");
+ category->connect("pressed",this,"_category_clicked");
vb->add_child(category);
author = memnew( LinkButton );
author->set_text("Johny Tolengo");
author->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
- title->connect("pressed",this,"_author_clicked");
+ author->connect("pressed",this,"_author_clicked");
vb->add_child(author);
HBoxContainer *rating_hb = memnew( HBoxContainer );
@@ -325,6 +325,7 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int
String error_text;
+ print_line("COMPLETED: "+itos(p_status)+" code: "+itos(p_code)+" data size: "+itos(p_data.size()));
switch(p_status) {
@@ -383,7 +384,9 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int
print_line("max: "+itos(download->get_body_size())+" bytes: "+itos(download->get_downloaded_bytes()));
install->set_disabled(false);
- status->set_text("Success!");
+ progress->set_val(download->get_downloaded_bytes());
+
+ status->set_text("Success! ("+String::humanize_size(download->get_downloaded_bytes())+")");
set_process(false);
}
@@ -411,6 +414,10 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) {
progress->set_val(download->get_downloaded_bytes());
int cstatus = download->get_http_client_status();
+
+ if (cstatus==HTTPClient::STATUS_BODY)
+ status->set_text("Fetching: "+String::humanize_size(download->get_downloaded_bytes()));
+
if (cstatus!=prev_status) {
switch(cstatus) {
@@ -423,9 +430,6 @@ void EditorAssetLibraryItemDownload::_notification(int p_what) {
case HTTPClient::STATUS_REQUESTING: {
status->set_text("Requesting..");
} break;
- case HTTPClient::STATUS_BODY: {
- status->set_text("Downloading..");
- } break;
default: {}
}
prev_status=cstatus;
@@ -457,6 +461,7 @@ void EditorAssetLibraryItemDownload::_install() {
void EditorAssetLibraryItemDownload::_make_request() {
download->cancel_request();
download->set_download_file(EditorSettings::get_singleton()->get_settings_path().plus_file("tmp").plus_file("tmp_asset_"+itos(asset_id))+".zip");
+
Error err = download->request(host);
if(err!=OK) {
status->set_text("Error making request");
@@ -1007,6 +1012,7 @@ void EditorAssetLibrary::_api_request(const String& p_request, RequestType p_req
if (requesting!=REQUESTING_NONE) {
request->cancel_request();
}
+
requesting=p_request_type;
error_hb->hide();
@@ -1465,6 +1471,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
request = memnew( HTTPRequest );
add_child(request);
+ request->set_use_threads(EDITOR_DEF("asset_library/use_threads",true));
request->connect("request_completed",this,"_http_request_completed");
last_queue_id=0;
diff --git a/tools/editor/code_editor.cpp b/tools/editor/code_editor.cpp
index c6de541d02..2779275ea8 100644
--- a/tools/editor/code_editor.cpp
+++ b/tools/editor/code_editor.cpp
@@ -133,8 +133,9 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col)
if (found) {
if (!preserve_cursor) {
- text_edit->cursor_set_line(line);
- text_edit->cursor_set_column(col+text.length());
+ text_edit->cursor_set_line(line, false);
+ text_edit->cursor_set_column(col+text.length(), false);
+ text_edit->center_viewport_to_cursor();
}
text_edit->set_search_text(text);
@@ -187,7 +188,9 @@ void FindReplaceBar::_replace_all() {
text_edit->cursor_set_line(0);
text_edit->cursor_set_column(0);
+ String replace_text=get_replace_text();
int search_text_len=get_search_text().length();
+
int rc=0;
replace_all_mode = true;
@@ -203,7 +206,7 @@ void FindReplaceBar::_replace_all() {
if (match_from < prev_match)
break; // done
- prev_match=match_to;
+ prev_match=Point2i(result_line,result_col+replace_text.length());
text_edit->select(result_line,result_col,result_line,match_to.y);
@@ -213,12 +216,12 @@ void FindReplaceBar::_replace_all() {
continue;
// replace but adjust selection bounds
- text_edit->insert_text_at_cursor(get_replace_text());
+ text_edit->insert_text_at_cursor(replace_text);
if (match_to.x==selection_end.x)
- selection_end.y+=get_replace_text().length() - get_search_text().length();
+ selection_end.y+=replace_text.length()-search_text_len;
} else {
// just replace
- text_edit->insert_text_at_cursor(get_replace_text());
+ text_edit->insert_text_at_cursor(replace_text);
}
rc++;
@@ -1031,8 +1034,8 @@ void CodeTextEditor::_reset_zoom() {
void CodeTextEditor::_line_col_changed() {
- String text = String()+TTR("Line:")+" "+itos(text_editor->cursor_get_line()+1)+", "+TTR("Col:")+" "+itos(text_editor->cursor_get_column());
- line_col->set_text(text);
+ line_nb->set_text(itos(text_editor->cursor_get_line() + 1));
+ col_nb->set_text(itos(text_editor->cursor_get_column()));
}
void CodeTextEditor::_text_changed() {
@@ -1208,6 +1211,7 @@ CodeTextEditor::CodeTextEditor() {
HBoxContainer *status_bar = memnew( HBoxContainer );
status_mc->add_child(status_bar);
status_bar->set_h_size_flags(SIZE_EXPAND_FILL);
+ status_bar->add_child( memnew( Label ) ); //to keep the height if the other labels are not visible
idle = memnew( Timer );
add_child(idle);
@@ -1229,14 +1233,33 @@ CodeTextEditor::CodeTextEditor() {
status_bar->add_spacer();
- line_col = memnew( Label );
- status_bar->add_child(line_col);
- line_col->set_valign(Label::VALIGN_CENTER);
- line_col->set_autowrap(true);
- line_col->set_v_size_flags(SIZE_FILL);
- line_col->set_custom_minimum_size(Size2(100,1)*EDSCALE);
- status_bar->add_child( memnew( Label ) ); //to keep the height if the other labels are not visible
-
+ Label *line_txt = memnew( Label );
+ status_bar->add_child(line_txt);
+ line_txt->set_align(Label::ALIGN_RIGHT);
+ line_txt->set_valign(Label::VALIGN_CENTER);
+ line_txt->set_v_size_flags(SIZE_FILL);
+ line_txt->set_text(TTR("Line:"));
+
+ line_nb = memnew( Label );
+ status_bar->add_child(line_nb);
+ line_nb->set_valign(Label::VALIGN_CENTER);
+ line_nb->set_v_size_flags(SIZE_FILL);
+ line_nb->set_autowrap(true); // workaround to prevent resizing the label on each change
+ line_nb->set_custom_minimum_size(Size2(40,1)*EDSCALE);
+
+ Label *col_txt = memnew( Label );
+ status_bar->add_child(col_txt);
+ col_txt->set_align(Label::ALIGN_RIGHT);
+ col_txt->set_valign(Label::VALIGN_CENTER);
+ col_txt->set_v_size_flags(SIZE_FILL);
+ col_txt->set_text(TTR("Col:"));
+
+ col_nb = memnew( Label );
+ status_bar->add_child(col_nb);
+ col_nb->set_valign(Label::VALIGN_CENTER);
+ col_nb->set_v_size_flags(SIZE_FILL);
+ col_nb->set_autowrap(true); // workaround to prevent resizing the label on each change
+ col_nb->set_custom_minimum_size(Size2(40,1)*EDSCALE);
text_editor->connect("input_event", this,"_text_editor_input_event");
text_editor->connect("cursor_changed", this,"_line_col_changed");
diff --git a/tools/editor/code_editor.h b/tools/editor/code_editor.h
index f6c3ac7564..2affa31482 100644
--- a/tools/editor/code_editor.h
+++ b/tools/editor/code_editor.h
@@ -198,7 +198,8 @@ class CodeTextEditor : public VBoxContainer {
TextEdit *text_editor;
FindReplaceBar *find_replace_bar;
- Label *line_col;
+ Label *line_nb;
+ Label *col_nb;
Label *info;
Timer *idle;
Timer *code_complete_timer;
diff --git a/tools/editor/editor_file_system.cpp b/tools/editor/editor_file_system.cpp
index cb7cefea26..582b9e2490 100644
--- a/tools/editor/editor_file_system.cpp
+++ b/tools/editor/editor_file_system.cpp
@@ -657,7 +657,7 @@ void EditorFileSystem::_scan_new_dir(EditorFileSystemDirectory *p_dir,DirAccess
da->change_dir("..");
}
} else {
- ERR_PRINTS(TTR("Cannot go into subdir:")+" "+E->get());
+ ERR_PRINTS("Cannot go into subdir: "+E->get());
}
p_progress.update(idx,total);
diff --git a/tools/editor/editor_help.cpp b/tools/editor/editor_help.cpp
index 1fc157098c..4ab86ad512 100644
--- a/tools/editor/editor_help.cpp
+++ b/tools/editor/editor_help.cpp
@@ -943,10 +943,9 @@ Error EditorHelp::_goto_desc(const String& p_class,int p_vscr) {
class_desc->add_newline();
}
- class_desc->add_newline();
- class_desc->pop();
-
+ class_desc->pop();
+ class_desc->add_newline();
}
if (cd.theme_properties.size()) {
@@ -987,11 +986,10 @@ Error EditorHelp::_goto_desc(const String& p_class,int p_vscr) {
class_desc->add_newline();
}
- class_desc->add_newline();
class_desc->pop();
-
-
+ class_desc->add_newline();
}
+
if (cd.signals.size()) {
if (sort_methods) {
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp
index f7189f022a..6f70eedcb3 100644
--- a/tools/editor/editor_node.cpp
+++ b/tools/editor/editor_node.cpp
@@ -1214,7 +1214,7 @@ void EditorNode::_dialog_action(String p_file) {
case FILE_SAVE_SCENE:
case FILE_SAVE_AS_SCENE: {
- if (file->get_mode()==FileDialog::MODE_SAVE_FILE) {
+ if (file->get_mode()==EditorFileDialog::MODE_SAVE_FILE) {
//_save_scene(p_file);
_save_scene_with_preview(p_file);
@@ -1224,7 +1224,7 @@ void EditorNode::_dialog_action(String p_file) {
} break;
case FILE_SAVE_AND_RUN: {
- if (file->get_mode()==FileDialog::MODE_SAVE_FILE) {
+ if (file->get_mode()==EditorFileDialog::MODE_SAVE_FILE) {
//_save_scene(p_file);
_save_scene_with_preview(p_file);
@@ -1449,7 +1449,7 @@ void EditorNode::_dialog_action(String p_file) {
} break;
default: { //save scene?
- if (file->get_mode()==FileDialog::MODE_SAVE_FILE) {
+ if (file->get_mode()==EditorFileDialog::MODE_SAVE_FILE) {
//_save_scene(p_file);
_save_scene_with_preview(p_file);
@@ -2843,7 +2843,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
} break;
case SETTINGS_ABOUT: {
- about->popup_centered(Size2(500,130)*EDSCALE);
+ about->popup_centered_minsize(Size2(500,130)*EDSCALE);
} break;
case SOURCES_REIMPORT: {
@@ -3823,6 +3823,11 @@ void EditorNode::request_instance_scene(const String &p_path) {
}
+void EditorNode::request_instance_scenes(const Vector<String>& p_files) {
+
+ scene_tree_dock->instance_scenes(p_files);
+}
+
FileSystemDock *EditorNode::get_scenes_dock() {
return scenes_dock;
@@ -3832,10 +3837,9 @@ SceneTreeDock *EditorNode::get_scene_tree_dock() {
return scene_tree_dock;
}
-void EditorNode::_instance_request(const String& p_path){
-
+void EditorNode::_instance_request(const Vector<String>& p_files) {
- request_instance_scene(p_path);
+ request_instance_scenes(p_files);
}
void EditorNode::_property_keyed(const String& p_keyed,const Variant& p_value,bool p_advance) {
diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h
index 9a227d3644..793c148671 100644
--- a/tools/editor/editor_node.h
+++ b/tools/editor/editor_node.h
@@ -452,7 +452,7 @@ private:
void _save_scene(String p_file, int idx = -1);
- void _instance_request(const String& p_path);
+ void _instance_request(const Vector<String>& p_files);
void _property_keyed(const String& p_keyed, const Variant& p_value, bool p_advance);
void _transform_keyed(Object *sp,const String& p_sub,const Transform& p_key);
@@ -666,6 +666,7 @@ public:
static VSplitContainer *get_top_split() { return singleton->top_split; }
void request_instance_scene(const String &p_path);
+ void request_instance_scenes(const Vector<String>& p_files);
FileSystemDock *get_scenes_dock();
SceneTreeDock *get_scene_tree_dock();
static UndoRedo* get_undo_redo() { return &singleton->editor_data.get_undo_redo(); }
diff --git a/tools/editor/editor_plugin.cpp b/tools/editor/editor_plugin.cpp
index 01e6b613c0..0d162cbe56 100644
--- a/tools/editor/editor_plugin.cpp
+++ b/tools/editor/editor_plugin.cpp
@@ -44,9 +44,9 @@ void EditorPlugin::remove_custom_type(const String& p_type){
}
-void EditorPlugin::add_control_to_bottom_panel(Control *p_control, const String &p_title) {
+ToolButton * EditorPlugin::add_control_to_bottom_panel(Control *p_control, const String &p_title) {
- EditorNode::get_singleton()->add_bottom_panel_item(p_title,p_control);
+ return EditorNode::get_singleton()->add_bottom_panel_item(p_title,p_control);
}
void EditorPlugin::add_control_to_dock(DockSlot p_slot,Control *p_control) {
@@ -284,7 +284,7 @@ Control *EditorPlugin::get_base_control() {
void EditorPlugin::_bind_methods() {
ObjectTypeDB::bind_method(_MD("add_control_to_container","container","control:Control"),&EditorPlugin::add_control_to_container);
- ObjectTypeDB::bind_method(_MD("add_control_to_bottom_panel","control:Control","title"),&EditorPlugin::add_control_to_bottom_panel);
+ ObjectTypeDB::bind_method(_MD("add_control_to_bottom_panel:ToolButton","control:Control","title"),&EditorPlugin::add_control_to_bottom_panel);
ObjectTypeDB::bind_method(_MD("add_control_to_dock","slot","control:Control"),&EditorPlugin::add_control_to_dock);
ObjectTypeDB::bind_method(_MD("remove_control_from_docks","control:Control"),&EditorPlugin::remove_control_from_docks);
ObjectTypeDB::bind_method(_MD("remove_control_from_bottom_panel","control:Control"),&EditorPlugin::remove_control_from_bottom_panel);
diff --git a/tools/editor/editor_plugin.h b/tools/editor/editor_plugin.h
index b93b6624d0..b960a7d5af 100644
--- a/tools/editor/editor_plugin.h
+++ b/tools/editor/editor_plugin.h
@@ -29,6 +29,7 @@
#ifndef EDITOR_PLUGIN_H
#define EDITOR_PLUGIN_H
+#include "scene/gui/tool_button.h"
#include "scene/main/node.h"
#include "scene/resources/texture.h"
#include "undo_redo.h"
@@ -92,7 +93,7 @@ public:
//TODO: send a resoucre for editing to the editor node?
void add_control_to_container(CustomControlContainer p_location, Control *p_control);
- void add_control_to_bottom_panel(Control *p_control, const String &p_title);
+ ToolButton *add_control_to_bottom_panel(Control *p_control, const String &p_title);
void add_control_to_dock(DockSlot p_slot,Control *p_control);
void remove_control_from_docks(Control *p_control);
void remove_control_from_bottom_panel(Control *p_control);
diff --git a/tools/editor/filesystem_dock.cpp b/tools/editor/filesystem_dock.cpp
index 3be122cc7d..378edd6667 100644
--- a/tools/editor/filesystem_dock.cpp
+++ b/tools/editor/filesystem_dock.cpp
@@ -950,14 +950,20 @@ void FileSystemDock::_file_option(int p_option) {
} break;
case FILE_INSTANCE: {
+ Vector<String> paths;
+
for (int i = 0; i<files->get_item_count(); i++) {
if (!files->is_selected(i))
continue;
String path =files->get_item_metadata(i);
if (EditorFileSystem::get_singleton()->get_file_type(path)=="PackedScene") {
- emit_signal("instance",path);
+ paths.push_back(path);
}
}
+
+ if (!paths.empty()) {
+ emit_signal("instance", paths);
+ }
} break;
case FILE_DEPENDENCIES: {
@@ -1596,7 +1602,7 @@ void FileSystemDock::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_preview_invalidated"),&FileSystemDock::_preview_invalidated);
- ADD_SIGNAL(MethodInfo("instance"));
+ ADD_SIGNAL(MethodInfo("instance", PropertyInfo(Variant::STRING_ARRAY, "files")));
ADD_SIGNAL(MethodInfo("open"));
}
diff --git a/tools/editor/icons/2x/icon_godot.png b/tools/editor/icons/2x/icon_godot.png
index f789c791bd..94d87e23cc 100644
--- a/tools/editor/icons/2x/icon_godot.png
+++ b/tools/editor/icons/2x/icon_godot.png
Binary files differ
diff --git a/tools/editor/icons/2x/icon_h_t_t_p_request.png b/tools/editor/icons/2x/icon_h_t_t_p_request.png
index e3f7568ea1..a334dea4e2 100644
--- a/tools/editor/icons/2x/icon_h_t_t_p_request.png
+++ b/tools/editor/icons/2x/icon_h_t_t_p_request.png
Binary files differ
diff --git a/tools/editor/icons/SCsub b/tools/editor/icons/SCsub
index f2f5dcca48..bc104294cb 100644
--- a/tools/editor/icons/SCsub
+++ b/tools/editor/icons/SCsub
@@ -37,12 +37,9 @@ def make_editor_icons_action(target, source, env):
pngf.close();
var_str=os.path.basename(x)[:-4]+"_hidpi_png";
-#print("TRY OPEN: "+os.path.dirname(x)+"/2x/"+os.path.basename(x)+"\n")
try:
- pngf = open(os.path.dirname(x)+"/2x/"+os.path.basename(x))
-
- #print(var_str)
+ pngf = open(os.path.dirname(x)+"/2x/"+os.path.basename(x), "rb")
s.write("static const unsigned char "+ var_str +"[]={\n");
diff --git a/tools/editor/icons/icon_godot.png b/tools/editor/icons/icon_godot.png
index a033ab48a8..0b72e6ecc7 100644
--- a/tools/editor/icons/icon_godot.png
+++ b/tools/editor/icons/icon_godot.png
Binary files differ
diff --git a/tools/editor/icons/icon_h_t_t_p_request.png b/tools/editor/icons/icon_h_t_t_p_request.png
index c00854a414..60c6845b33 100644
--- a/tools/editor/icons/icon_h_t_t_p_request.png
+++ b/tools/editor/icons/icon_h_t_t_p_request.png
Binary files differ
diff --git a/tools/editor/icons/make_icons.py b/tools/editor/icons/make_icons.py
deleted file mode 100644
index e06cbac720..0000000000
--- a/tools/editor/icons/make_icons.py
+++ /dev/null
@@ -1,48 +0,0 @@
-
-import glob
-
-pixmaps = glob.glob("*.png")
-
-f = open("../editor_icons.cpp","wb")
-
-
-f.write("#include \"editor_icons.h\"\n\n")
-f.write("#include \"scene/resources/theme.h\"\n\n")
-
-for x in pixmaps:
-
- var_str=x[:-4]+"_png";
-
- f.write("static const unsigned char "+ var_str +"[]={\n");
-
- pngf=open(x,"rb");
-
- b=pngf.read(1);
- while(len(b)==1):
- f.write(hex(ord(b)))
- b=pngf.read(1);
- if (len(b)==1):
- f.write(",")
-
- f.write("\n};\n\n\n");
- pngf.close();
-
-f.write("static Ref<ImageTexture> make_icon(const uint8_t* p_png) {\n")
-f.write("\tRef<ImageTexture> texture( memnew( ImageTexture ) );\n")
-f.write("\ttexture->create_from_image( Image(p_png),ImageTexture::FLAG_FILTER );\n")
-f.write("\treturn texture;\n")
-f.write("}\n\n")
-
-f.write("void editor_register_icons(Ref<Theme> p_theme) {\n\n")
-
-
-for x in pixmaps:
-
- type=x[5:-4].title().replace("_","");
- var_str=x[:-4]+"_png";
- f.write("\tp_theme->set_icon(\""+type+"\",\"EditorIcons\",make_icon("+var_str+"));\n");
-
-f.write("\n\n}\n\n");
-f.close()
-
-
diff --git a/tools/editor/icons/source/icon_godot.svg b/tools/editor/icons/source/icon_godot.svg
index 927c3ee053..419f23125b 100644
--- a/tools/editor/icons/source/icon_godot.svg
+++ b/tools/editor/icons/source/icon_godot.svg
@@ -28,12 +28,12 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="22.627417"
- inkscape:cx="4.9021021"
- inkscape:cy="11.249083"
+ inkscape:zoom="32"
+ inkscape:cx="9.8470361"
+ inkscape:cy="9.8599985"
inkscape:document-units="px"
inkscape:current-layer="layer1"
- showgrid="true"
+ showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
@@ -59,7 +59,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -146,5 +146,23 @@
</g>
</g>
</g>
+ <path
+ style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.44162436"
+ d="m 4,1041.3622 a 3,3 0 0 0 -3,3 3,3 0 0 0 3,3 3,3 0 0 0 3,-3 3,3 0 0 0 -3,-3 z m 0,1 a 2.0000174,2.0000174 0 0 1 2,2 2.0000174,2.0000174 0 0 1 -2,2 2.0000174,2.0000174 0 0 1 -2,-2 2.0000174,2.0000174 0 0 1 2,-2 z"
+ id="path4151"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4156"
+ d="m 12,1041.3622 a 3,3 0 0 0 -3,3 3,3 0 0 0 3,3 3,3 0 0 0 3,-3 3,3 0 0 0 -3,-3 z m 0,1 a 2.0000174,2.0000174 0 0 1 2,2 2.0000174,2.0000174 0 0 1 -2,2 2.0000174,2.0000174 0 0 1 -2,-2 2.0000174,2.0000174 0 0 1 2,-2 z"
+ style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.44162436" />
+ <rect
+ style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.44162436"
+ id="rect4160"
+ width="4"
+ height="1"
+ x="6"
+ y="1043.3622"
+ ry="0" />
</g>
</svg>
diff --git a/tools/editor/icons/source/icon_group.svg b/tools/editor/icons/source/icon_group.svg
index c8d20af9dd..a0a2f02af5 100644
--- a/tools/editor/icons/source/icon_group.svg
+++ b/tools/editor/icons/source/icon_group.svg
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="22.627417"
- inkscape:cx="10.459761"
- inkscape:cy="9.5219725"
+ inkscape:zoom="5.6568543"
+ inkscape:cx="14.789684"
+ inkscape:cy="26.718572"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -79,1005 +79,6 @@
id="rect4697"
transform="translate(0,1036.3622)" />
<rect
- ry="4.3456585e-05"
- rx="4.5000234"
- y="996.36218"
- x="-20.000004"
- height="15.999995"
- width="36.000008"
- id="rect4379"
- style="opacity:1;fill:#4b4b4b;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- ry="8.6913296e-06"
- rx="24"
- y="17.999989"
- x="998.36218"
- height="1"
- width="12"
- id="rect4153"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="matrix(0,1,-1,0,0,0)"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4151"
- width="12"
- height="1"
- x="-17.999989"
- y="997.36218"
- rx="24"
- ry="8.6913296e-06"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4155"
- width="12"
- height="1"
- x="998.36218"
- y="4.99999"
- rx="24"
- ry="8.6913296e-06"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- ry="8.6913296e-06"
- rx="24"
- y="1010.3622"
- x="-17.999989"
- height="1"
- width="12"
- id="rect4157"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4159"
- width="4.9999809"
- height="1.0000036"
- x="1003.3622"
- y="15.999995"
- rx="9.9999619"
- ry="8.6913606e-06"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- ry="4.3456628e-05"
- rx="2.0000134"
- y="11.000003"
- x="1002.3622"
- height="4.9999976"
- width="1.0000067"
- id="rect4161"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="matrix(0,1,-1,0,0,0)"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- ry="8.6913606e-06"
- rx="9.9999619"
- y="9.9999886"
- x="1003.3622"
- height="1.0000036"
- width="4.9999809"
- id="rect4163"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="matrix(0,1,-1,0,0,0)"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4165"
- width="1.0000067"
- height="4.9999976"
- x="1008.3622"
- y="11.000002"
- rx="2.0000134"
- ry="4.3456628e-05"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4167"
- sodipodi:type="arc"
- sodipodi:cx="-17.999989"
- sodipodi:cy="998.36218"
- sodipodi:rx="1"
- sodipodi:ry="1"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m -17.999989,999.36218 a 1,1 0 0 1 -0.866025,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866025,-0.5 l 0,1 z"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- d="m 5.9999948,999.36218 a 1,1 0 0 1 -0.8660254,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.8660254,-0.5 l 0,1 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="998.36218"
- sodipodi:cx="5.9999948"
- sodipodi:type="arc"
- id="path4169"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="scale(-1,1)"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- transform="scale(-1,1)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4171"
- sodipodi:type="arc"
- sodipodi:cx="5.9999948"
- sodipodi:cy="1010.3622"
- sodipodi:rx="1"
- sodipodi:ry="1"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m 5.9999948,1011.3622 a 1,1 0 0 1 -0.8660254,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.8660254,-0.5 l 0,1 z"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- d="m -17.999994,1011.3622 a 1,1 0 0 1 -0.866026,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866026,-0.5 l 0,1 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="1010.3622"
- sodipodi:cx="-17.999994"
- sodipodi:type="arc"
- id="path4173"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4175"
- sodipodi:type="arc"
- sodipodi:cx="-15.999995"
- sodipodi:cy="1008.3622"
- sodipodi:rx="1"
- sodipodi:ry="1"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m -15.999995,1009.3622 a 1,1 0 0 1 -0.866026,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866026,-0.5 l 0,1 z"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- d="m -15.999995,1004.3622 a 1,1 0 0 1 -0.866026,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866026,-0.5 l 0,1 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="1003.3622"
- sodipodi:cx="-15.999995"
- sodipodi:type="arc"
- id="path4177-3"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- d="m 10.999986,1009.3622 a 1,1 0 0 1 -0.866026,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866026,-0.5 l 0,1 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="1008.3622"
- sodipodi:cx="10.999986"
- sodipodi:type="arc"
- id="path4179-6"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="scale(-1,1)"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4181"
- sodipodi:type="arc"
- sodipodi:cx="10.999986"
- sodipodi:cy="1003.3622"
- sodipodi:rx="1"
- sodipodi:ry="1"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m 10.999986,1004.3622 a 1,1 0 0 1 -0.866026,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866026,-0.5 l 0,1 z"
- transform="scale(-1,1)"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- inkscape:connector-curvature="0"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m -12.99999,999.36232 a 1,1 0 0 0 -0.865235,0.5 1,1 0 0 0 -0.134765,0.52348 l 0,0.9765 c 0.361502,0 0.445997,0 1,0 l 0,-1 5,0 0,1 0,1.5 0,2.5 -1,0 0,1 1,0 a 1,1 0 0 0 0.865234,-0.5 1,1 0 0 0 0.134766,-0.5 l 0,-2.5 0,-2.4765 a 1,1 0 0 0 0,-0.024 1,1 0 0 0 -0.134766,-0.49998 1,1 0 0 0 -0.865234,-0.5 l -5,-10e-5 z"
- id="rect4183"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- ry="8.6913606e-06"
- rx="9.9999619"
- y="-4.0000043"
- x="1003.3622"
- height="1.0000036"
- width="4.9999809"
- id="rect4389"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="matrix(0,1,-1,0,0,0)"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4391"
- width="1.0000067"
- height="4.9999976"
- x="1002.3622"
- y="-8.9999962"
- rx="2.0000134"
- ry="4.3456628e-05"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4393"
- width="4.9999809"
- height="1.0000036"
- x="1003.3622"
- y="-10.00001"
- rx="9.9999619"
- ry="8.6913606e-06"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- ry="4.3456628e-05"
- rx="2.0000134"
- y="-8.9999971"
- x="1008.3622"
- height="4.9999976"
- width="1.0000067"
- id="rect4395"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="matrix(0,1,-1,0,0,0)"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- d="m 4.0000043,1009.3622 a 1,1 0 0 1 -0.8660254,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.8660254,-0.5 l 0,1 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="1008.3622"
- sodipodi:cx="4.0000043"
- sodipodi:type="arc"
- id="path4405"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4407"
- sodipodi:type="arc"
- sodipodi:cx="4.0000043"
- sodipodi:cy="1003.3622"
- sodipodi:rx="1"
- sodipodi:ry="1"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m 4.0000043,1004.3622 a 1,1 0 0 1 -0.8660254,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.8660254,-0.5 l 0,1 z"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- transform="scale(-1,1)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4409"
- sodipodi:type="arc"
- sodipodi:cx="-9.0000134"
- sodipodi:cy="1008.3622"
- sodipodi:rx="1"
- sodipodi:ry="1"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m -9.0000133,1009.3622 a 1,1 0 0 1 -0.8660254,-0.5 1,1 0 0 1 -10e-8,-1 1,1 0 0 1 0.8660255,-0.5 l -10e-8,1 z"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- transform="scale(-1,1)"
- d="m -9.0000133,1004.3622 a 1,1 0 0 1 -0.8660254,-0.5 1,1 0 0 1 -10e-8,-1 1,1 0 0 1 0.8660255,-0.5 l -10e-8,1 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="1003.3622"
- sodipodi:cx="-9.0000134"
- sodipodi:type="arc"
- id="path4411"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- id="path4413"
- d="m 7.0000094,999.36232 a 1,1 0 0 0 -0.865235,0.5 1,1 0 0 0 -0.134765,0.52348 l 0,0.9765 c 0.361502,0 0.445997,0 1,0 l 0,-1 5.0000006,0 0,1 0,1.5 0,2.5 -1,0 0,1 1,0 a 1,1 0 0 0 0.865234,-0.5 1,1 0 0 0 0.134766,-0.5 l 0,-2.5 0,-2.4765 a 1,1 0 0 0 0,-0.024 1,1 0 0 0 -0.134766,-0.49998 1,1 0 0 0 -0.865234,-0.5 l -5.0000006,-10e-5 z"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:connector-curvature="0"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- style="opacity:1;fill:#4b4b4b;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4415"
- width="36.000008"
- height="15.999995"
- x="-19.999994"
- y="1012.3622"
- rx="4.5000234"
- ry="4.3456585e-05"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- d="m -16.000053,1020.3622 a 1,1 0 0 1 -0.866026,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866026,-0.5 l 0,1 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="1019.3622"
- sodipodi:cx="-16.000053"
- sodipodi:type="arc"
- id="path4417"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- d="m 11.000043,1025.3622 a 1,1 0 0 1 -0.866025,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866025,-0.5 l 0,1 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="1024.3622"
- sodipodi:cx="11.000043"
- sodipodi:type="arc"
- id="path4419"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="scale(-1,1)"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4421"
- width="2"
- height="5"
- x="-19.000053"
- y="1020.3622"
- rx="2.00001"
- ry="4.3456599e-05"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- ry="1.7382426e-05"
- rx="5.000021"
- y="1018.3622"
- x="-17.00005"
- height="1.9999754"
- width="4.9999962"
- id="rect4423"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- ry="4.3456599e-05"
- rx="2.00001"
- y="1020.3622"
- x="-12.000043"
- height="5"
- width="2"
- id="rect4425"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4427"
- width="2"
- height="5"
- x="1025.3622"
- y="12.000043"
- rx="2.00001"
- ry="4.3456599e-05"
- transform="matrix(0,1,-1,0,0,0)"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4429"
- sodipodi:type="arc"
- sodipodi:cx="-17.000048"
- sodipodi:cy="1020.3622"
- sodipodi:rx="2"
- sodipodi:ry="2"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m -17.000048,1022.3622 a 2,2 0 0 1 -1.73205,-1 2,2 0 0 1 0,-2 2,2 0 0 1 1.73205,-1 l 0,2 z"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- d="m -17.000048,1027.3622 a 2,2 0 0 1 -1.73205,-1 2,2 0 0 1 0,-2 2,2 0 0 1 1.73205,-1 l 0,2 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="2"
- sodipodi:rx="2"
- sodipodi:cy="1025.3622"
- sodipodi:cx="-17.000048"
- sodipodi:type="arc"
- id="path4431"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- d="m 12.000043,1022.3622 a 2,2 0 0 1 -1.732051,-1 2,2 0 0 1 0,-2 2,2 0 0 1 1.732051,-1 l 0,2 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="2"
- sodipodi:rx="2"
- sodipodi:cy="1020.3622"
- sodipodi:cx="12.000043"
- sodipodi:type="arc"
- id="path4433"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="scale(-1,1)"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4435"
- sodipodi:type="arc"
- sodipodi:cx="12.000043"
- sodipodi:cy="1025.3622"
- sodipodi:rx="2"
- sodipodi:ry="2"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m 12.000043,1027.3622 a 2,2 0 0 1 -1.732051,-1 2,2 0 0 1 0,-2 2,2 0 0 1 1.732051,-1 l 0,2 z"
- transform="scale(-1,1)"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- inkscape:connector-curvature="0"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m -12.000048,1013.3622 a 2,2 0 0 0 -1.732422,1 2,2 0 0 0 -0.265625,1 l -0.0019,0 0,1 2,0 0,-1 2.5000001,0 2.5,0 0,3 0,2 -1,0 0,2 1,0 a 2,2 0 0 0 1.732422,-1 2,2 0 0 0 0.265625,-1 l 0.002,0 0,-5 -0.002,0 a 2,2 0 0 0 -0.265625,-1 2,2 0 0 0 -1.732422,-1 l -2.5,0 -2.5000001,0 z"
- id="path4437"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- inkscape:connector-curvature="0"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m -17.000048,1013.3622 a 2,2 0 0 0 -1.732422,1 2,2 0 0 0 -0.265625,1 c 0,0 -0.0019,0 -0.0019,0 l 0,7 c 0,0 0.446,0 1,0 0.554,0 1,0 1,0 l 0,-5 0,-2 5,0 5.0000001,0 0,-2 -5.0000001,0 -5,0 z m 10.0000001,5 0,7 -4.5000001,0 -4.5,0 0,2 4.5,0 4.5000001,0 a 2,2 0 0 0 1.732422,-1 2,2 0 0 0 0.265625,-1 c 0,0 0.002,0 0.002,0 l 0,-7 c 0,0 -0.446,0 -1,0 -0.554,0 -1,0 -1,0 z"
- id="path4439"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4441"
- width="2"
- height="2"
- x="-14.000048"
- y="1016.3622"
- rx="2.00001"
- ry="3.3799501e-05"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- ry="3.3799501e-05"
- rx="2.00001"
- y="1020.3622"
- x="-10.000052"
- height="2"
- width="2"
- id="rect4443"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4445"
- sodipodi:type="arc"
- sodipodi:cx="3.9999421"
- sodipodi:cy="1019.3622"
- sodipodi:rx="1"
- sodipodi:ry="1"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m 3.9999421,1020.3622 a 1,1 0 0 1 -0.8660254,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.8660254,-0.5 l 0,1 z"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- transform="scale(-1,1)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4447"
- sodipodi:type="arc"
- sodipodi:cx="-8.9999523"
- sodipodi:cy="1024.3622"
- sodipodi:rx="1"
- sodipodi:ry="1"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m -8.9999523,1025.3622 a 1,1 0 0 1 -0.8660254,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.8660254,-0.5 l 0,1 z"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- ry="4.3456599e-05"
- rx="2.00001"
- y="1020.3622"
- x="0.99994206"
- height="5"
- width="2"
- id="rect4449"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4451"
- width="4.9999962"
- height="1.9999754"
- x="2.9999459"
- y="1018.3622"
- rx="5.000021"
- ry="1.7382426e-05"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4453"
- width="2"
- height="5"
- x="7.9999528"
- y="1020.3622"
- rx="2.00001"
- ry="4.3456599e-05"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- ry="4.3456599e-05"
- rx="2.00001"
- y="-7.9999528"
- x="1025.3622"
- height="5"
- width="2"
- id="rect4455"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- d="m 2.9999478,1022.3622 a 2,2 0 0 1 -1.7320508,-1 2,2 0 0 1 0,-2 2,2 0 0 1 1.7320508,-1 l 0,2 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="2"
- sodipodi:rx="2"
- sodipodi:cy="1020.3622"
- sodipodi:cx="2.9999478"
- sodipodi:type="arc"
- id="path4457"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4459"
- sodipodi:type="arc"
- sodipodi:cx="2.9999478"
- sodipodi:cy="1025.3622"
- sodipodi:rx="2"
- sodipodi:ry="2"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m 2.9999478,1027.3622 a 2,2 0 0 1 -1.7320508,-1 2,2 0 0 1 0,-2 2,2 0 0 1 1.7320508,-1 l 0,2 z"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- transform="scale(-1,1)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4461"
- sodipodi:type="arc"
- sodipodi:cx="-7.9999528"
- sodipodi:cy="1020.3622"
- sodipodi:rx="2"
- sodipodi:ry="2"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m -7.9999527,1022.3622 a 2,2 0 0 1 -1.7320509,-1 2,2 0 0 1 0,-2 2,2 0 0 1 1.7320508,-1 l 0,2 z"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- transform="scale(-1,1)"
- d="m -7.9999527,1027.3622 a 2,2 0 0 1 -1.7320509,-1 2,2 0 0 1 0,-2 2,2 0 0 1 1.7320508,-1 l 0,2 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="2"
- sodipodi:rx="2"
- sodipodi:cy="1025.3622"
- sodipodi:cx="-7.9999528"
- sodipodi:type="arc"
- id="path4463"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <path
- id="path4465"
- d="m 7.9999475,1013.3622 a 2,2 0 0 0 -1.732422,1 2,2 0 0 0 -0.265625,1 l -0.0019,0 0,1 2,0 0,-1 2.5000005,0 2.5,0 0,3 0,2 -1,0 0,2 1,0 a 2,2 0 0 0 1.732422,-1 2,2 0 0 0 0.265625,-1 l 0.002,0 0,-5 -0.002,0 a 2,2 0 0 0 -0.265625,-1 2,2 0 0 0 -1.732422,-1 l -2.5,0 -2.5000005,0 z"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:connector-curvature="0"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- ry="3.3799501e-05"
- rx="2.00001"
- y="1016.3622"
- x="5.999948"
- height="2"
- width="2"
- id="rect4469"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4471"
- width="2"
- height="2"
- x="9.9999428"
- y="1020.3622"
- rx="2.00001"
- ry="3.3799501e-05"
- inkscape:export-filename="/home/djrm/rect4471.png"
- inkscape:export-xdpi="180"
- inkscape:export-ydpi="180" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4473"
- width="12"
- height="1"
- x="1038.3622"
- y="-35.500008"
- rx="24"
- ry="8.6913296e-06" />
- <rect
- ry="8.6913296e-06"
- rx="24"
- y="1037.3622"
- x="35.500008"
- height="1"
- width="12"
- id="rect4475"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <rect
- ry="8.6913296e-06"
- rx="24"
- y="-48.500004"
- x="1038.3622"
- height="1"
- width="12"
- id="rect4477"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="matrix(0,1,-1,0,0,0)" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4479"
- width="12"
- height="1"
- x="35.500008"
- y="1050.3622"
- rx="24"
- ry="8.6913296e-06" />
- <rect
- ry="8.6913606e-06"
- rx="9.9999619"
- y="-37.5"
- x="1043.3622"
- height="1.0000036"
- width="4.9999809"
- id="rect4481"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="matrix(0,1,-1,0,0,0)" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4483"
- width="1.0000067"
- height="4.9999976"
- x="1042.3622"
- y="-42.499992"
- rx="2.0000134"
- ry="4.3456628e-05" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4485"
- width="4.9999809"
- height="1.0000036"
- x="1043.3622"
- y="-43.500008"
- rx="9.9999619"
- ry="8.6913606e-06" />
- <rect
- ry="4.3456628e-05"
- rx="2.0000134"
- y="-42.499992"
- x="1048.3622"
- height="4.9999976"
- width="1.0000067"
- id="rect4487"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="matrix(0,1,-1,0,0,0)" />
- <path
- d="m 35.500008,1039.3622 a 1,1 0 0 1 -0.866026,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866026,-0.5 l 0,1 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="1038.3622"
- sodipodi:cx="35.500008"
- sodipodi:type="arc"
- id="path4489"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <path
- transform="scale(-1,1)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4491"
- sodipodi:type="arc"
- sodipodi:cx="-47.5"
- sodipodi:cy="1038.3622"
- sodipodi:rx="1"
- sodipodi:ry="1"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m -47.5,1039.3622 a 1,1 0 0 1 -0.866025,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866025,-0.5 l 0,1 z" />
- <path
- d="m -47.5,1051.3622 a 1,1 0 0 1 -0.866025,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866025,-0.5 l 0,1 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="1050.3622"
- sodipodi:cx="-47.5"
- sodipodi:type="arc"
- id="path4493"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- transform="scale(-1,1)" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4495"
- sodipodi:type="arc"
- sodipodi:cx="35.5"
- sodipodi:cy="1050.3622"
- sodipodi:rx="1"
- sodipodi:ry="1"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m 35.5,1051.3622 a 1,1 0 0 1 -0.866025,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866025,-0.5 l 0,1 z" />
- <path
- d="m 37.5,1049.3622 a 1,1 0 0 1 -0.866025,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866025,-0.5 l 0,1 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="1048.3622"
- sodipodi:cx="37.5"
- sodipodi:type="arc"
- id="path4497"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4499"
- sodipodi:type="arc"
- sodipodi:cx="37.5"
- sodipodi:cy="1043.3622"
- sodipodi:rx="1"
- sodipodi:ry="1"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m 37.5,1044.3622 a 1,1 0 0 1 -0.866025,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866025,-0.5 l 0,1 z" />
- <path
- transform="scale(-1,1)"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4501"
- sodipodi:type="arc"
- sodipodi:cx="-42.500011"
- sodipodi:cy="1048.3622"
- sodipodi:rx="1"
- sodipodi:ry="1"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m -42.500011,1049.3622 a 1,1 0 0 1 -0.866026,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866026,-0.5 l 0,1 z" />
- <path
- transform="scale(-1,1)"
- d="m -42.500011,1044.3622 a 1,1 0 0 1 -0.866026,-0.5 1,1 0 0 1 0,-1 1,1 0 0 1 0.866026,-0.5 l 0,1 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="1"
- sodipodi:rx="1"
- sodipodi:cy="1043.3622"
- sodipodi:cx="-42.500011"
- sodipodi:type="arc"
- id="path4503"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <path
- id="path4505"
- d="m 40.500005,1039.3623 a 1,1 0 0 0 -0.865235,0.5 1,1 0 0 0 -0.134765,0.5235 l 0,0.9765 c 0.361502,0 0.445997,0 1,0 l 0,-1 5,0 0,1 0,1.5 0,2.5 -1,0 0,1 1,0 a 1,1 0 0 0 0.865234,-0.5 1,1 0 0 0 0.134766,-0.5 l 0,-2.5 0,-2.4765 a 1,1 0 0 0 0,-0.024 1,1 0 0 0 -0.134766,-0.5 1,1 0 0 0 -0.865234,-0.5 l -5,-10e-5 z"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:connector-curvature="0" />
- <rect
- inkscape:export-ydpi="180"
- inkscape:export-xdpi="180"
- inkscape:export-filename="/home/djrm/rect4471.png"
- ry="4.3456599e-05"
- rx="2.00001"
- y="1044.3622"
- x="-18.000057"
- height="5"
- width="2"
- id="rect4536"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <rect
- inkscape:export-ydpi="180"
- inkscape:export-xdpi="180"
- inkscape:export-filename="/home/djrm/rect4471.png"
- transform="matrix(0,1,-1,0,0,0)"
- ry="4.3456599e-05"
- rx="2.00001"
- y="11.000047"
- x="1049.3622"
- height="5"
- width="2"
- id="rect4542"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <path
- inkscape:export-ydpi="180"
- inkscape:export-xdpi="180"
- inkscape:export-filename="/home/djrm/rect4471.png"
- d="m -16.00005,1046.3622 a 2,2 0 0 1 -1.73205,-1 2,2 0 0 1 0,-2 2,2 0 0 1 1.73205,-1 l 0,2 z"
- sodipodi:end="4.712389"
- sodipodi:start="1.5707963"
- sodipodi:ry="2"
- sodipodi:rx="2"
- sodipodi:cy="1044.3622"
- sodipodi:cx="-16.00005"
- sodipodi:type="arc"
- id="path4544"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
- <path
- inkscape:export-ydpi="180"
- inkscape:export-xdpi="180"
- inkscape:export-filename="/home/djrm/rect4471.png"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="path4546"
- sodipodi:type="arc"
- sodipodi:cx="-16.00005"
- sodipodi:cy="1049.3622"
- sodipodi:rx="2"
- sodipodi:ry="2"
- sodipodi:start="1.5707963"
- sodipodi:end="4.712389"
- d="m -16.00005,1051.3622 a 2,2 0 0 1 -1.73205,-1 2,2 0 0 1 0,-2 2,2 0 0 1 1.73205,-1 l 0,2 z" />
- <path
- inkscape:export-ydpi="180"
- inkscape:export-xdpi="180"
- inkscape:export-filename="/home/djrm/rect4471.png"
- id="path4554"
- d="m -16.000053,1037.3622 a 2,2 0 0 0 -1.732422,1 2,2 0 0 0 -0.265625,1 c 0,0 -0.0019,0 -0.0019,0 l 0,7 c 0,0 0.446,0 1,0 0.554,0 1,0 1,0 l 0,-5 0,-2 5.000001,0 5,0 0,-2 -5,0 -5.000001,0 z m 10.000001,5 0,7 -4.5,0 -4.500001,0 0,2 4.500001,0 4.5,0 a 2,2 0 0 0 1.732422,-1 2,2 0 0 0 0.265625,-1 c 0,0 0.002,0 0.002,0 l 0,-7 c 0,0 -0.446,0 -1,0 -0.554,0 -1,0 -1,0 z"
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- inkscape:connector-curvature="0" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4560"
- width="4"
- height="4"
- x="-14"
- y="1041.3622"
- rx="2.00001"
- ry="3.3799501e-05" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m 33.000005,1021.3622 c 1.107999,0 2,0.892 2,2 l 0,5 c 0,1.108 -0.892001,2 -2,2 l -1,0 0,-3 a 2.9999926,2.9999926 0 0 0 -3,-3 l -3,0 0,-1 c 0,-1.108 0.892001,-2 2,-2 l 5,0 z m -7,6 a 2.9999926,2.9999926 0 0 0 3,3 l -1,0 c -1.107999,0 -2,-0.892 -2,-2 l 0,-1 z"
- id="rect4562"
- inkscape:connector-curvature="0" />
- <rect
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4566"
- width="8.9999924"
- height="9.0000114"
- x="-30.000002"
- y="1026.3622"
- rx="1.9999952"
- ry="2.0000174"
- transform="scale(-1,1)" />
- <rect
- inkscape:export-ydpi="180"
- inkscape:export-xdpi="180"
- inkscape:export-filename="/home/djrm/rect4471.png"
- style="opacity:1;fill:#4b4b4b;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- id="rect4579"
- width="36.000008"
- height="15.999995"
- x="-20.000004"
- y="980.36218"
- rx="4.5000234"
- ry="4.3456585e-05" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m -32.000005,1037.3622 c -1.10801,0 -2,0.892 -2,2 l 0,10 c 0,1.108 0.89199,2 2,2 l 10,0 c 1.10801,0 2,-0.892 2,-2 l 0,-10 c 0,-1.108 -0.89199,-2 -2,-2 l -10,0 z m 0,2 10,0 0,10 -10,0 0,-10 z"
- id="rect4601"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m 21,1044.3622 a 3.4999881,3.4999881 0 0 0 -3.5,3.5 3.4999881,3.4999881 0 0 0 3.5,3.5 3.4999881,3.4999881 0 0 0 3.5,-3.5 3.4999881,3.4999881 0 0 0 -3.5,-3.5 z m 0,2 a 1.5000153,1.5000153 0 0 1 1.5,1.5 1.5000153,1.5000153 0 0 1 -1.5,1.5 1.5000153,1.5000153 0 0 1 -1.5,-1.5 1.5000153,1.5000153 0 0 1 1.5,-1.5 z"
- id="path4644"
- inkscape:connector-curvature="0" />
- <path
- style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
- d="m 28,1037.3622 a 3.4999881,3.4999881 0 0 0 -3.5,3.5 3.4999881,3.4999881 0 0 0 3.5,3.5 3.4999881,3.4999881 0 0 0 3.5,-3.5 3.4999881,3.4999881 0 0 0 -3.5,-3.5 z m 0,2 a 1.5000153,1.5000153 0 0 1 1.5,1.5 1.5000153,1.5000153 0 0 1 -1.5,1.5 1.5000153,1.5000153 0 0 1 -1.5,-1.5 1.5000153,1.5000153 0 0 1 1.5,-1.5 z"
- id="circle4646"
- inkscape:connector-curvature="0" />
- <rect
style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4679"
width="2"
diff --git a/tools/editor/icons/source/icon_h_t_t_p_request.svg b/tools/editor/icons/source/icon_h_t_t_p_request.svg
index 2aee12b2af..f43141dd7c 100644
--- a/tools/editor/icons/source/icon_h_t_t_p_request.svg
+++ b/tools/editor/icons/source/icon_h_t_t_p_request.svg
@@ -15,7 +15,7 @@
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
- inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_key.png"
+ inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_h_t_t_p_request.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
sodipodi:docname="icon_h_t_t_p_request.svg">
@@ -28,9 +28,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="45.254836"
- inkscape:cx="10.430372"
- inkscape:cy="8.7048298"
+ inkscape:zoom="32.000001"
+ inkscape:cx="14.357316"
+ inkscape:cy="9.4289864"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
@@ -59,7 +59,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -73,18 +73,18 @@
id="rect4200"
width="1"
height="5"
- x="0"
- y="1042.3622" />
+ x="1"
+ y="1046.3622" />
<rect
- y="1044.3622"
- x="0"
+ y="1048.3622"
+ x="1"
height="0.9999826"
width="2"
id="rect4202"
style="opacity:1;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
<rect
- y="1042.3622"
- x="2"
+ y="1046.3622"
+ x="3"
height="5"
width="1"
id="rect4204"
@@ -94,18 +94,18 @@
id="rect4206"
width="1"
height="5"
- x="5"
- y="1042.3622" />
+ x="6"
+ y="1046.3622" />
<rect
- y="1042.3622"
- x="4"
+ y="1046.3622"
+ x="5"
height="1.0000174"
width="3"
id="rect4208"
style="opacity:1;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843" />
<rect
- y="1042.3622"
- x="9"
+ y="1046.3622"
+ x="10"
height="5"
width="1"
id="rect4210"
@@ -115,18 +115,18 @@
id="rect4212"
width="3"
height="1.0000174"
- x="8"
- y="1042.3622" />
+ x="9"
+ y="1046.3622" />
<rect
style="opacity:1;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
id="rect4214"
width="1"
height="5"
- x="12"
- y="1042.3622" />
+ x="13"
+ y="1046.3622" />
<rect
- y="1042.3622"
- x="12"
+ y="1046.3622"
+ x="13"
height="1.0000174"
width="3"
id="rect4216"
@@ -136,14 +136,38 @@
id="rect4218"
width="1"
height="3.0000174"
- x="14"
- y="1042.3622" />
+ x="15"
+ y="1046.3622" />
<rect
style="opacity:1;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.99607843"
id="rect4220"
width="3"
height="1.0000174"
- x="12"
- y="1044.3622" />
+ x="13"
+ y="1048.3622" />
+ <path
+ style="fill:#e0e0e0;fill-opacity:0.99607843;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 1,1041.3622 6,0 -3,-4 z"
+ id="path4279"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4281"
+ d="m 9,1040.3622 6,0 -3,4 z"
+ style="fill:#e0e0e0;fill-opacity:0.99607843;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <rect
+ style="opacity:1;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect4283"
+ width="2"
+ height="3"
+ x="3"
+ y="1041.3622" />
+ <rect
+ y="1037.3622"
+ x="11"
+ height="3"
+ width="2"
+ id="rect4285"
+ style="opacity:1;fill:#e0e0e0;fill-opacity:0.99607843;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</svg>
diff --git a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp
index 2c3ed2afd6..da608292c1 100644
--- a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp
@@ -496,7 +496,6 @@ Error EditorMeshImportPlugin::import(const String& p_path, const Ref<ResourceImp
}
int vtx = face[idx][0].to_int()-1;
- print_line("vtx: "+itos(vtx)+"/"+itos(vertices.size()));
ERR_FAIL_INDEX_V(vtx,vertices.size(),ERR_PARSE_ERROR);
Vector3 vertex = vertices[vtx];
diff --git a/tools/editor/plugins/baked_light_baker.cpp b/tools/editor/plugins/baked_light_baker.cpp
index 6a88ba4cbe..a2e94e8855 100644
--- a/tools/editor/plugins/baked_light_baker.cpp
+++ b/tools/editor/plugins/baked_light_baker.cpp
@@ -1772,6 +1772,10 @@ void BakedLightBaker::bake(const Ref<BakedLight> &p_light, Node* p_node) {
mat_map.clear();
tex_map.clear();
print_line("\ttotal triangles: "+itos(triangles.size()));
+ // no geometry
+ if (triangles.size() == 0) {
+ return;
+ }
ep.step(TTR("Fixing Lights"),1);
_fix_lights();
ep.step(TTR("Making BVH"),2);
diff --git a/tools/editor/plugins/baked_light_editor_plugin.cpp b/tools/editor/plugins/baked_light_editor_plugin.cpp
index df76f28ae0..a58a0c25e2 100644
--- a/tools/editor/plugins/baked_light_editor_plugin.cpp
+++ b/tools/editor/plugins/baked_light_editor_plugin.cpp
@@ -206,8 +206,9 @@ void BakedLightEditor::_menu_option(int p_option) {
void BakedLightEditor::_bake_pressed() {
ERR_FAIL_COND(!node);
- if (node->get_baked_light().is_null()) {
- err_dialog->set_text(TTR("BakedLightInstance does not contain a BakedLight resource."));
+ const String conf_warning = node->get_configuration_warning();
+ if (!conf_warning.empty()) {
+ err_dialog->set_text(conf_warning);
err_dialog->popup_centered_minsize();
button_bake->set_pressed(false);
return;
@@ -236,6 +237,7 @@ void BakedLightEditor::_bake_pressed() {
update_timeout=0;
last_rays_time=0;
+ button_bake->set_pressed(false);
set_process(true);
}
diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp
index 1b739e62f6..376c0daa68 100644
--- a/tools/editor/plugins/script_editor_plugin.cpp
+++ b/tools/editor/plugins/script_editor_plugin.cpp
@@ -1954,6 +1954,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
completion_cache = memnew( EditorScriptCodeCompletionCache );
restoring_layout=false;
waiting_update_names=false;
+ pending_auto_reload=false;
auto_reload_running_scripts=false;
editor=p_editor;
diff --git a/tools/editor/project_manager.cpp b/tools/editor/project_manager.cpp
index b7d3abfd5b..62b15d344d 100644
--- a/tools/editor/project_manager.cpp
+++ b/tools/editor/project_manager.cpp
@@ -31,6 +31,7 @@
#include "os/os.h"
#include "os/dir_access.h"
#include "os/file_access.h"
+#include "os/keyboard.h"
#include "editor_settings.h"
#include "scene/gui/separator.h"
#include "scene/gui/tool_button.h"
@@ -363,6 +364,12 @@ public:
mode=p_mode;
}
+ void import_from_file(const String& p_file) {
+ mode=MODE_IMPORT;
+ _file_selected(p_file);
+ ok_pressed();
+ }
+
void show_dialog() {
@@ -491,6 +498,10 @@ void ProjectManager::_notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_TREE) {
get_tree()->set_editor_hint(true);
+
+ } else if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+
+ set_process_unhandled_input(is_visible());
}
}
@@ -505,6 +516,27 @@ void ProjectManager::_panel_draw(Node *p_hb) {
}
}
+void ProjectManager::_update_project_buttons()
+{
+ for(int i=0;i<scroll_childs->get_child_count();i++) {
+
+ CanvasItem *item = scroll_childs->get_child(i)->cast_to<CanvasItem>();
+ item->update();
+ }
+
+ bool has_runnable_scene = false;
+ for (Map<String,String>::Element *E=selected_list.front(); E; E=E->next()) {
+ const String &selected_main = E->get();
+ if (selected_main == "") continue;
+ has_runnable_scene = true;
+ break;
+ }
+
+ erase_btn->set_disabled(selected_list.size()<1);
+ open_btn->set_disabled(selected_list.size()<1);
+ run_btn->set_disabled(!has_runnable_scene);
+}
+
void ProjectManager::_panel_input(const InputEvent& p_ev,Node *p_hb) {
if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) {
@@ -552,27 +584,143 @@ void ProjectManager::_panel_input(const InputEvent& p_ev,Node *p_hb) {
}
}
- String single_selected = "";
- if (selected_list.size() == 1) {
- single_selected = selected_list.front()->key();
- }
+ _update_project_buttons();
- single_selected_main = "";
- for(int i=0;i<scroll_childs->get_child_count();i++) {
- CanvasItem *item = scroll_childs->get_child(i)->cast_to<CanvasItem>();
- item->update();
+ if (p_ev.mouse_button.doubleclick)
+ _open_project(); //open if doubleclicked
- if (single_selected!="" && single_selected == item->get_meta("name"))
- single_selected_main = item->get_meta("main_scene");
- }
+ }
+}
- erase_btn->set_disabled(selected_list.size()<1);
- open_btn->set_disabled(selected_list.size()<1);
- run_btn->set_disabled(selected_list.size()<1 || (selected_list.size()==1 && single_selected_main==""));
+void ProjectManager::_unhandled_input(const InputEvent& p_ev) {
- if (p_ev.mouse_button.doubleclick)
- _open_project(); //open if doubleclicked
+ if (p_ev.type==InputEvent::KEY) {
+
+ const InputEventKey &k = p_ev.key;
+
+ if (!k.pressed)
+ return;
+
+ bool scancode_handled = true;
+
+ switch (k.scancode) {
+
+ case KEY_HOME: {
+
+ for (int i=0; i<scroll_childs->get_child_count(); i++) {
+
+ HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ if (hb) {
+ selected_list.clear();
+ selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
+ scroll->set_v_scroll(0);
+ break;
+ }
+ }
+
+ } break;
+ case KEY_END: {
+
+ for (int i=scroll_childs->get_child_count()-1; i>=0; i--) {
+
+ HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ if (hb) {
+ selected_list.clear();
+ selected_list.insert(hb->get_meta("name"), hb->get_meta("main_scene"));
+ scroll->set_v_scroll(scroll_childs->get_size().y);
+ break;
+ }
+ }
+
+ } break;
+ case KEY_UP: {
+
+ if (k.mod.shift)
+ break;
+
+ if (selected_list.size()) {
+
+ bool found = false;
+
+ for (int i=scroll_childs->get_child_count()-1; i>=0; i--) {
+
+ HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ if (!hb) continue;
+
+ String current = hb->get_meta("name");
+
+ if (found) {
+ selected_list.clear();
+ selected_list.insert(current, hb->get_meta("main_scene"));
+
+ int offset_diff = scroll->get_v_scroll() - hb->get_pos().y;
+
+ if (offset_diff > 0)
+ scroll->set_v_scroll(scroll->get_v_scroll() - offset_diff);
+
+ break;
+
+ } else if (current==selected_list.back()->key()) {
+ found = true;
+ }
+ }
+
+ break;
+ }
+ // else fallthrough to key_down
+ }
+ case KEY_DOWN: {
+
+ if (k.mod.shift)
+ break;
+
+ bool found = selected_list.empty();
+
+ for (int i=0; i<scroll_childs->get_child_count(); i++) {
+
+ HBoxContainer *hb = scroll_childs->get_child(i)->cast_to<HBoxContainer>();
+ if (!hb) continue;
+
+ String current = hb->get_meta("name");
+
+ if (found) {
+ selected_list.clear();
+ selected_list.insert(current, hb->get_meta("main_scene"));
+
+ int last_y_visible = scroll->get_v_scroll() + scroll->get_size().y;
+ int offset_diff = (hb->get_pos().y + hb->get_size().y) - last_y_visible;
+
+ if (offset_diff > 0)
+ scroll->set_v_scroll(scroll->get_v_scroll() + offset_diff);
+
+ break;
+
+ } else if (current==selected_list.back()->key()) {
+
+ found = true;
+ }
+ }
+
+ } break;
+ case KEY_F: {
+ if (k.mod.command) this->project_filter->search_box->grab_focus();
+ else scancode_handled = false;
+ } break;
+ default: {
+ scancode_handled = false;
+ } break;
+ }
+
+ if (scancode_handled) {
+ accept_event();
+
+ for(int i=0;i<scroll_childs->get_child_count();i++) {
+ CanvasItem *item = scroll_childs->get_child(i)->cast_to<CanvasItem>();
+ if (item)
+ item->update();
+ }
+ }
}
}
@@ -602,6 +750,8 @@ void ProjectManager::_load_recent_projects() {
memdelete( scroll_childs->get_child(0));
}
+ Map<String, String> selected_list_copy = selected_list;
+
List<PropertyInfo> properties;
EditorSettings::get_singleton()->get_property_list(&properties);
@@ -708,6 +858,8 @@ void ProjectManager::_load_recent_projects() {
main_scene = cf->get_value("application","main_scene");
}
+ selected_list_copy.erase(project);
+
HBoxContainer *hb = memnew( HBoxContainer );
hb->set_meta("name",project);
hb->set_meta("main_scene",main_scene);
@@ -745,12 +897,15 @@ void ProjectManager::_load_recent_projects() {
scroll_childs->add_child(hb);
}
-
+
+ for (Map<String,String>::Element *E = selected_list_copy.front();E;E = E->next()) {
+ String key = E->key();
+ selected_list.erase(key);
+ }
+
scroll->set_v_scroll(0);
-
- erase_btn->set_disabled(selected_list.size()<1);
- open_btn->set_disabled(selected_list.size()<1);
- run_btn->set_disabled(selected_list.size()<1 || (selected_list.size()==1 && single_selected_main==""));
+
+ _update_project_buttons();
EditorSettings::get_singleton()->save();
@@ -917,7 +1072,6 @@ void ProjectManager::_erase_project_confirm() {
EditorSettings::get_singleton()->save();
selected_list.clear();
last_clicked = "";
- single_selected_main="";
_load_recent_projects();
}
@@ -948,6 +1102,54 @@ void ProjectManager::_install_project(const String& p_zip_path,const String& p_t
npdialog->show_dialog();
}
+void ProjectManager::_files_dropped(StringArray p_files, int p_screen) {
+ Set<String> folders_set;
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ for (int i = 0; i < p_files.size(); i++) {
+ String file = p_files[i];
+ folders_set.insert(da->dir_exists(file) ? file : file.get_base_dir());
+ }
+ memdelete(da);
+ if (folders_set.size()>0) {
+ StringArray folders;
+ for (Set<String>::Element *E=folders_set.front();E;E=E->next()) {
+ folders.append(E->get());
+ }
+
+ bool confirm = true;
+ if (folders.size()==1) {
+ DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (dir->change_dir(folders[0])==OK) {
+ dir->list_dir_begin();
+ String file = dir->get_next();
+ while(confirm && file!=String()) {
+ if (!da->current_is_dir() && file.ends_with("engine.cfg")) {
+ confirm = false;
+ }
+ file = dir->get_next();
+ }
+ dir->list_dir_end();
+ }
+ memdelete(dir);
+ }
+ if (confirm) {
+ multi_scan_ask->get_ok()->disconnect("pressed", this, "_scan_multiple_folders");
+ multi_scan_ask->get_ok()->connect("pressed", this, "_scan_multiple_folders", varray(folders));
+ multi_scan_ask->set_text(vformat(TTR("You are about the scan %s folders for existing Godot projects. Do you confirm?"), folders.size()));
+ multi_scan_ask->popup_centered_minsize();
+ } else {
+ _scan_multiple_folders(folders);
+ }
+ }
+}
+
+void ProjectManager::_scan_multiple_folders(StringArray p_files)
+{
+ for (int i = 0; i < p_files.size(); i++) {
+ _scan_begin(p_files.get(i));
+ }
+}
+
void ProjectManager::_bind_methods() {
ObjectTypeDB::bind_method("_open_project",&ProjectManager::_open_project);
@@ -964,8 +1166,11 @@ void ProjectManager::_bind_methods() {
ObjectTypeDB::bind_method("_load_recent_projects",&ProjectManager::_load_recent_projects);
ObjectTypeDB::bind_method("_panel_draw",&ProjectManager::_panel_draw);
ObjectTypeDB::bind_method("_panel_input",&ProjectManager::_panel_input);
+ ObjectTypeDB::bind_method("_unhandled_input",&ProjectManager::_unhandled_input);
ObjectTypeDB::bind_method("_favorite_pressed",&ProjectManager::_favorite_pressed);
ObjectTypeDB::bind_method("_install_project",&ProjectManager::_install_project);
+ ObjectTypeDB::bind_method("_files_dropped",&ProjectManager::_files_dropped);
+ ObjectTypeDB::bind_method(_MD("_scan_multiple_folders", "files"),&ProjectManager::_scan_multiple_folders);
}
@@ -1100,6 +1305,7 @@ ProjectManager::ProjectManager() {
scan_dir = memnew( FileDialog );
scan_dir->set_access(FileDialog::ACCESS_FILESYSTEM);
scan_dir->set_mode(FileDialog::MODE_OPEN_DIR);
+ scan_dir->set_title(TTR("Select a Folder to Scan")); // must be after mode or it's overridden
scan_dir->set_current_dir( EditorSettings::get_singleton()->get("global/default_project_path") );
gui_base->add_child(scan_dir);
scan_dir->connect("dir_selected",this,"_scan_begin");
@@ -1161,8 +1367,13 @@ ProjectManager::ProjectManager() {
multi_run_ask = memnew( ConfirmationDialog );
multi_run_ask->get_ok()->set_text(TTR("Run"));
multi_run_ask->get_ok()->connect("pressed", this, "_run_project_confirm");
-
+
gui_base->add_child(multi_run_ask);
+
+ multi_scan_ask = memnew( ConfirmationDialog );
+ multi_scan_ask->get_ok()->set_text(TTR("Scan"));
+
+ gui_base->add_child(multi_scan_ask);
OS::get_singleton()->set_low_processor_usage_mode(true);
@@ -1180,6 +1391,8 @@ ProjectManager::ProjectManager() {
//get_ok()->set_text("Exit");
last_clicked = "";
+
+ SceneTree::get_singleton()->connect("files_dropped", this, "_files_dropped");
}
diff --git a/tools/editor/project_manager.h b/tools/editor/project_manager.h
index 69467f50e7..46f7aea3a5 100644
--- a/tools/editor/project_manager.h
+++ b/tools/editor/project_manager.h
@@ -55,12 +55,12 @@ class ProjectManager : public Control {
ConfirmationDialog *erase_ask;
ConfirmationDialog *multi_open_ask;
ConfirmationDialog *multi_run_ask;
+ ConfirmationDialog *multi_scan_ask;
NewProjectDialog *npdialog;
ScrollContainer *scroll;
VBoxContainer *scroll_childs;
Map<String, String> selected_list; // name -> main_scene
String last_clicked;
- String single_selected_main;
bool importing;
HBoxContainer *projects_hb;
@@ -69,8 +69,6 @@ class ProjectManager : public Control {
Control *gui_base;
- void _item_doubleclicked();
-
void _scan_projects();
@@ -82,6 +80,7 @@ class ProjectManager : public Control {
void _new_project();
void _erase_project();
void _erase_project_confirm();
+ void _update_project_buttons();
void _exit_dialog();
void _scan_begin(const String& p_base);
@@ -92,7 +91,10 @@ class ProjectManager : public Control {
void _panel_draw(Node *p_hb);
void _panel_input(const InputEvent& p_ev,Node *p_hb);
+ void _unhandled_input(const InputEvent& p_ev);
void _favorite_pressed(Node *p_hb);
+ void _files_dropped(StringArray p_files, int p_screen);
+ void _scan_multiple_folders(StringArray p_files);
protected:
diff --git a/tools/editor/project_settings.cpp b/tools/editor/project_settings.cpp
index 6be1abf52f..e8d22143ee 100644
--- a/tools/editor/project_settings.cpp
+++ b/tools/editor/project_settings.cpp
@@ -1375,34 +1375,35 @@ ProjectSettings::ProjectSettings(EditorData *p_data) {
input_base->set_area_as_parent_rect();;
tab_container->add_child(input_base);
+ VBoxContainer *vbc = memnew( VBoxContainer );
+ input_base->add_child(vbc);
+ vbc->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN, 5 );
+ vbc->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 5 );
+ vbc->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN, 5 );
+ vbc->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END, 5 );
+
l = memnew( Label );
- input_base->add_child(l);
+ vbc->add_child(l);
l->set_pos(Point2(6,5));
l->set_text(TTR("Action:"));
+ hbc = memnew( HBoxContainer );
+ vbc->add_child(hbc);
+
action_name = memnew( LineEdit );
- action_name->set_anchor(MARGIN_RIGHT,ANCHOR_RATIO);
- action_name->set_begin( Point2(5,25) );
- action_name->set_end( Point2(0.85,26) );
- input_base->add_child(action_name);
+ action_name->set_h_size_flags(SIZE_EXPAND_FILL);
+ hbc->add_child(action_name);
action_name->connect("text_entered",this,"_action_adds");
add = memnew( Button );
- input_base->add_child(add);
- add->set_anchor(MARGIN_LEFT,ANCHOR_RATIO);
- add->set_begin( Point2(0.86,25) );
- add->set_anchor(MARGIN_RIGHT,ANCHOR_END);
- add->set_end( Point2(5,26) );
+ hbc->add_child(add);
+ add->set_custom_minimum_size(Size2(150, 0));
add->set_text(TTR("Add"));
add->connect("pressed",this,"_action_add");
input_editor = memnew( Tree );
- input_base->add_child(input_editor);
- input_editor->set_area_as_parent_rect();
- input_editor->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN, 55 );
- input_editor->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END, 35 );
- input_editor->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN, 5 );
- input_editor->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END, 5 );
+ vbc->add_child(input_editor);
+ input_editor->set_v_size_flags(SIZE_EXPAND_FILL);
input_editor->connect("item_edited",this,"_action_edited");
input_editor->connect("cell_selected",this,"_action_selected");
input_editor->connect("button_pressed",this,"_action_button_pressed");
diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp
index bc879a9cf9..ccce92523f 100644
--- a/tools/editor/property_editor.cpp
+++ b/tools/editor/property_editor.cpp
@@ -3051,10 +3051,10 @@ void PropertyEditor::update_tree() {
} else {
if (p.type == Variant::REAL) {
- item->set_range_config(1, -65536, 65535, 0.001);
+ item->set_range_config(1, -16777216, 16777216, 0.001);
} else {
- item->set_range_config(1, -65536, 65535, 1);
+ item->set_range_config(1, -2147483647, 2147483647, 1);
}
};
diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp
index a240b575aa..9e2b2266a5 100644
--- a/tools/editor/scene_tree_dock.cpp
+++ b/tools/editor/scene_tree_dock.cpp
@@ -48,11 +48,9 @@ void SceneTreeDock::_unhandled_key_input(InputEvent p_event) {
if (get_viewport()->get_modal_stack_top())
return; //ignore because of modal window
- uint32_t sc = p_event.key.get_scancode_with_modifiers();
if (!p_event.key.pressed || p_event.key.echo)
return;
-
if (ED_IS_SHORTCUT("scene_tree/add_child_node", p_event)) {
_tool_selected(TOOL_NEW);
}
@@ -83,9 +81,11 @@ void SceneTreeDock::_unhandled_key_input(InputEvent p_event) {
else if (ED_IS_SHORTCUT("scene_tree/save_branch_as_scene", p_event)) {
_tool_selected(TOOL_NEW_SCENE_FROM);
}
- switch(sc) {
- case KEY_MASK_SHIFT|KEY_DELETE: { _tool_selected(TOOL_ERASE, true); } break;
- case KEY_DELETE: { _tool_selected(TOOL_ERASE); } break;
+ else if (ED_IS_SHORTCUT("scene_tree/delete_no_confirm", p_event)) {
+ _tool_selected(TOOL_ERASE, true);
+ }
+ else if (ED_IS_SHORTCUT("scene_tree/delete", p_event)) {
+ _tool_selected(TOOL_ERASE);
}
}
@@ -106,11 +106,30 @@ void SceneTreeDock::instance(const String& p_file) {
Vector<String> scenes;
scenes.push_back(p_file);
- instance_scenes(scenes,parent,-1);
+ _perform_instance_scenes(scenes,parent,-1);
+
+}
+
+void SceneTreeDock::instance_scenes(const Vector<String>& p_files, Node *p_parent) {
+
+ Node *parent = p_parent;
+
+ if (!parent) {
+ parent = scene_tree->get_selected();
+ }
+
+ if (!parent || !edited_scene) {
+
+ accept->get_ok()->set_text(TTR("OK"));
+ accept->set_text(TTR("No parent to instance the scenes at."));
+ accept->popup_centered_minsize();
+ return;
+ };
+ _perform_instance_scenes(p_files, parent, -1);
}
-void SceneTreeDock::instance_scenes(const Vector<String>& p_files,Node* parent,int p_pos) {
+void SceneTreeDock::_perform_instance_scenes(const Vector<String>& p_files,Node* parent,int p_pos) {
@@ -1677,7 +1696,7 @@ void SceneTreeDock::_files_dropped(Vector<String> p_files,NodePath p_to,int p_ty
int to_pos=-1;
_normalize_drop(node,to_pos,p_type);
- instance_scenes(p_files,node,to_pos);
+ _perform_instance_scenes(p_files,node,to_pos);
}
void SceneTreeDock::_nodes_dragged(Array p_nodes,NodePath p_to,int p_type) {
@@ -1750,7 +1769,7 @@ void SceneTreeDock::_tree_rmb(const Vector2& p_menu_pos) {
}
menu->add_separator();
- menu->add_icon_item(get_icon("Remove","EditorIcons"),TTR("Delete Node(s)"), TOOL_ERASE, KEY_DELETE);
+ menu->add_icon_shortcut(get_icon("Remove","EditorIcons"), ED_SHORTCUT("scene_tree/delete", TTR("Delete Node(s)"), KEY_DELETE), TOOL_ERASE);
menu->set_size(Size2(1,1));
menu->set_pos(p_menu_pos);
@@ -1827,6 +1846,8 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor,Node *p_scene_root,EditorSelec
ED_SHORTCUT("scene_tree/reparent", TTR("Reparent"));
ED_SHORTCUT("scene_tree/merge_from_scene", TTR("Merge From Scene"));
ED_SHORTCUT("scene_tree/save_branch_as_scene", TTR("Save Branch as Scene"));
+ ED_SHORTCUT("scene_tree/delete_no_confirm", TTR("Delete (No Confirm)"), KEY_MASK_SHIFT|KEY_DELETE);
+ ED_SHORTCUT("scene_tree/delete", TTR("Delete"), KEY_DELETE);
tb = memnew( ToolButton );
tb->connect("pressed",this,"_tool_selected",make_binds(TOOL_NEW, false));
diff --git a/tools/editor/scene_tree_dock.h b/tools/editor/scene_tree_dock.h
index 51041a235b..04ed16967f 100644
--- a/tools/editor/scene_tree_dock.h
+++ b/tools/editor/scene_tree_dock.h
@@ -148,6 +148,8 @@ class SceneTreeDock : public VBoxContainer {
void _filter_changed(const String& p_filter);
+ void _perform_instance_scenes(const Vector<String>& p_files,Node* parent,int p_pos);
+
protected:
void _notification(int p_what);
@@ -160,7 +162,7 @@ public:
void import_subscene();
void set_edited_scene(Node* p_scene);
void instance(const String& p_path);
- void instance_scenes(const Vector<String>& p_files,Node* parent,int p_pos);
+ void instance_scenes(const Vector<String>& p_files, Node *p_parent=NULL);
void set_selected(Node *p_node, bool p_emit_selected=false);
void fill_path_renames(Node* p_node, Node *p_new_parent, List<Pair<NodePath,NodePath> > *p_renames);
void perform_node_renames(Node* p_base,List<Pair<NodePath,NodePath> > *p_renames, Map<Ref<Animation>, Set<int> > *r_rem_anims=NULL);
diff --git a/version.py b/version.py
index dd80ca1b19..19ff05f715 100644
--- a/version.py
+++ b/version.py
@@ -2,4 +2,4 @@ short_name="godot"
name="Godot Engine"
major=2
minor=1
-status="beta"
+status="rc1"