This commit is contained in:
Juan Linietsky 2016-08-02 19:11:47 -03:00
commit 3d1d190dcd
79 changed files with 1339 additions and 1545 deletions

View file

@ -113,6 +113,7 @@ uint32_t ihash3( uint32_t a)
MainLoop* test() {
print_line(itos(Math::step_decimals( 0.0001 )));
return NULL;
{

View file

@ -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);

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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; }

View file

@ -206,25 +206,29 @@ double Math::ceil(double p_x) {
return ::ceil(p_x);
}
int Math::decimals(double p_step) {
int Math::step_decimals(double p_step) {
int max=4;
double llimit = Math::pow(0.1,max);
double ulimit = 1.0-llimit;
int i=0;
while( max) {
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
};
float d = absf(p_step) - Math::floor(absf(p_step));
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) {

View file

@ -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();

View file

@ -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) {

View file

@ -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);
}

View file

@ -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++) {

View file

@ -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();

View file

@ -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());

View file

@ -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: {}
}

View file

@ -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;
}

View file

@ -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>

View file

@ -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

View file

@ -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,",

View file

@ -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);

View file

@ -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);

View file

@ -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) {
return new GodotPaymentV3(p_activity);
}
*/
static public Godot.SingletonBase initialize(Activity 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(), "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, "no_validation_required", new Object[]{});
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 callbackFail(){
public void callbackSuccessNoUnconsumedPurchases() {
GodotLib.calldeferred(purchaseCallbackId, "consume_not_required", new Object[]{});
}
public void callbackFailConsume() {
GodotLib.calldeferred(purchaseCallbackId, "consume_fail", new Object[]{});
}
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});
}
}

View file

@ -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.IBinder;
import android.util.Log;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
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 onServiceConnected(ComponentName name, IBinder service) {
ServiceConnection mServiceConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
@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);
final ArrayList<String> myPurchases = bundle.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
final ArrayList<String> mySignatures = bundle.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
pc.setConsumableValue("ticket_signautre", sku, signature);
pc.setConsumableValue("ticket", sku, receipt);
pc.setConsumableFlag("block", sku, true);
pc.setConsumableValue("token", sku, token);
if (myPurchases == null || myPurchases.size() == 0) {
godotPaymentV3.callbackPurchased("", "", "");
return;
}
godotPaymentV3.callbackPurchased(receipt, signature, sku);
} catch (JSONException 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) {
}
}
}
}
}catch(Exception 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;
}
}

View file

@ -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"

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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();
};

View file

@ -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") );
}

View file

@ -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;

View file

@ -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++) {

View file

@ -92,6 +92,7 @@ private:
bool dragging;
bool just_selected;
Vector2 drag_accum;
Point2 drag_origin; // Workaround for GH-5907
float zoom;

View file

@ -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);

View file

@ -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++;

View file

@ -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) {

View file

@ -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!="")

View file

@ -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"));

View file

@ -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);

View file

@ -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 ) {

View file

@ -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;
err = _request();
if (use_threads) {
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;

View file

@ -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:

View file

@ -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") );

View file

@ -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) {

View file

@ -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(CacheID p_id){
Ref<DynamicFontAtSize> DynamicFontData::_get_dynamic_font_at_size(int p_size) {
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,31 +664,80 @@ 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;
}
return 0;
}
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();
}
int DynamicFont::get_size() const{
return size;
}
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() {

View file

@ -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);

View file

@ -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);

View file

@ -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
};

View file

@ -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;

View file

@ -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)) {

View file

@ -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;

View file

@ -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");

View file

@ -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;

View file

@ -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);

View file

@ -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->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) {

View file

@ -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) {

View file

@ -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(); }

View file

@ -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);

View file

@ -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);

View file

@ -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"));
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 B

After

Width:  |  Height:  |  Size: 425 B

View file

@ -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");

Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 B

After

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 B

After

Width:  |  Height:  |  Size: 301 B

View file

@ -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()

View file

@ -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>

Before

Width:  |  Height:  |  Size: 8 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -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>

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View file

@ -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];

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

View file

@ -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,23 +584,7 @@ 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();
}
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 (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==""));
_update_project_buttons();
if (p_ev.mouse_button.doubleclick)
_open_project(); //open if doubleclicked
@ -576,6 +592,138 @@ void ProjectManager::_panel_input(const InputEvent& p_ev,Node *p_hb) {
}
}
void ProjectManager::_unhandled_input(const InputEvent& p_ev) {
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();
}
}
}
}
void ProjectManager::_favorite_pressed(Node *p_hb) {
String clicked = p_hb->get_meta("name");
@ -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");
}

View file

@ -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:

View file

@ -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");

View file

@ -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);
}
};

View file

@ -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* parent,int p_pos) {
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::_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));

View file

@ -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);

View file

@ -2,4 +2,4 @@ short_name="godot"
name="Godot Engine"
major=2
minor=1
status="beta"
status="rc1"