-Support for changing fonts

-Detect when free() might crash the project and throw error
-fixed 2D Bounce in physics (3d still broken)
-renamed “on_top” property to “behind_parent”, which makes more sense, old on_top remains there for compatibility but is invisible.
-large amount of fixes
This commit is contained in:
Juan Linietsky 2014-04-05 12:39:30 -03:00
parent 35b84d2c85
commit 9f33134c93
47 changed files with 1599 additions and 268 deletions

View File

@ -246,6 +246,12 @@ Error _OS::kill(int p_pid) {
return OS::get_singleton()->kill(p_pid); return OS::get_singleton()->kill(p_pid);
} }
int _OS::get_process_ID() const {
return OS::get_singleton()->get_process_ID();
};
bool _OS::has_environment(const String& p_var) const { bool _OS::has_environment(const String& p_var) const {
return OS::get_singleton()->has_environment(p_var); return OS::get_singleton()->has_environment(p_var);
@ -561,6 +567,7 @@ void _OS::_bind_methods() {
ObjectTypeDB::bind_method(_MD("execute","path","arguments","blocking"),&_OS::execute); ObjectTypeDB::bind_method(_MD("execute","path","arguments","blocking"),&_OS::execute);
ObjectTypeDB::bind_method(_MD("kill","pid"),&_OS::kill); ObjectTypeDB::bind_method(_MD("kill","pid"),&_OS::kill);
ObjectTypeDB::bind_method(_MD("shell_open","uri"),&_OS::shell_open); ObjectTypeDB::bind_method(_MD("shell_open","uri"),&_OS::shell_open);
ObjectTypeDB::bind_method(_MD("get_process_ID"),&_OS::get_process_ID);
ObjectTypeDB::bind_method(_MD("get_environment","environment"),&_OS::get_environment); ObjectTypeDB::bind_method(_MD("get_environment","environment"),&_OS::get_environment);
ObjectTypeDB::bind_method(_MD("has_environment","environment"),&_OS::has_environment); ObjectTypeDB::bind_method(_MD("has_environment","environment"),&_OS::has_environment);

View File

@ -117,6 +117,8 @@ public:
Error kill(int p_pid); Error kill(int p_pid);
Error shell_open(String p_uri); Error shell_open(String p_uri);
int get_process_ID() const;
bool has_environment(const String& p_var) const; bool has_environment(const String& p_var) const;
String get_environment(const String& p_var) const; String get_environment(const String& p_var) const;

View File

@ -949,6 +949,7 @@ String ResourceInteractiveLoaderBinary::recognize(FileAccess *p_f) {
} else if (header[0]!='R' || header[1]!='S' || header[2]!='R' || header[3]!='C') { } else if (header[0]!='R' || header[1]!='S' || header[2]!='R' || header[3]!='C') {
//not normal //not normal
error=ERR_FILE_UNRECOGNIZED;
return ""; return "";
} }

View File

@ -378,11 +378,12 @@ void MessageQueue::flush() {
} }
} }
message->~Message();
read_pos+=sizeof(Message); read_pos+=sizeof(Message);
if (message->type!=TYPE_NOTIFICATION) if (message->type!=TYPE_NOTIFICATION)
read_pos+=sizeof(Variant)*message->args; read_pos+=sizeof(Variant)*message->args;
message->~Message();
_THREAD_SAFE_UNLOCK_ _THREAD_SAFE_UNLOCK_
} }

View File

@ -33,6 +33,30 @@
#include "message_queue.h" #include "message_queue.h"
#include "core_string_names.h" #include "core_string_names.h"
#include "translation.h" #include "translation.h"
#ifdef DEBUG_ENABLED
struct _ObjectDebugLock {
Object *obj;
_ObjectDebugLock(Object *p_obj) {
obj=p_obj;
obj->_lock_index.ref();
}
~_ObjectDebugLock() {
obj->_lock_index.unref();
}
};
#define OBJ_DEBUG_LOCK _ObjectDebugLock _debug_lock(this);
#else
#define OBJ_DEBUG_LOCK
#endif
Array convert_property_list(const List<PropertyInfo> * p_list) { Array convert_property_list(const List<PropertyInfo> * p_list) {
Array va; Array va;
@ -562,13 +586,22 @@ void Object::call_multilevel(const StringName& p_method,const Variant** p_args,i
ERR_FAIL(); ERR_FAIL();
return; return;
} }
if (_lock_index.get()>1) {
ERR_EXPLAIN("Object is locked and can't be freed.");
ERR_FAIL();
return;
}
#endif #endif
//must be here, must be before everything, //must be here, must be before everything,
memdelete(this); memdelete(this);
return; return;
} }
//Variant ret; //Variant ret;
OBJ_DEBUG_LOCK
Variant::CallError error; Variant::CallError error;
@ -594,6 +627,7 @@ void Object::call_multilevel_reversed(const StringName& p_method,const Variant**
MethodBind *method=ObjectTypeDB::get_method(get_type_name(),p_method); MethodBind *method=ObjectTypeDB::get_method(get_type_name(),p_method);
Variant::CallError error; Variant::CallError error;
OBJ_DEBUG_LOCK
if (method) { if (method) {
@ -813,6 +847,15 @@ Variant Object::call(const StringName& p_method,const Variant** p_args,int p_arg
ERR_EXPLAIN("Can't 'free' a reference."); ERR_EXPLAIN("Can't 'free' a reference.");
ERR_FAIL_V(Variant()); ERR_FAIL_V(Variant());
} }
if (_lock_index.get()>1) {
r_error.argument=0;
r_error.error=Variant::CallError::CALL_ERROR_INVALID_METHOD;
ERR_EXPLAIN("Object is locked and can't be freed.");
ERR_FAIL_V(Variant());
}
#endif #endif
//must be here, must be before everything, //must be here, must be before everything,
memdelete(this); memdelete(this);
@ -821,7 +864,7 @@ Variant Object::call(const StringName& p_method,const Variant** p_args,int p_arg
} }
Variant ret; Variant ret;
OBJ_DEBUG_LOCK
if (script_instance) { if (script_instance) {
ret = script_instance->call(p_method,p_args,p_argcount,r_error); ret = script_instance->call(p_method,p_args,p_argcount,r_error);
//force jumptable //force jumptable
@ -902,7 +945,7 @@ void Object::set_script(const RefPtr& p_script) {
Ref<Script> s(script); Ref<Script> s(script);
if (!s.is_null() && s->can_instance() ) { if (!s.is_null() && s->can_instance() ) {
OBJ_DEBUG_LOCK
script_instance = s->instance_create(this); script_instance = s->instance_create(this);
} }
@ -1066,6 +1109,8 @@ void Object::emit_signal(const StringName& p_name,VARIANT_ARG_DECLARE) {
int ssize = slot_map.size(); int ssize = slot_map.size();
OBJ_DEBUG_LOCK
for(int i=0;i<ssize;i++) { for(int i=0;i<ssize;i++) {
const Connection &c = slot_map.getv(i).conn; const Connection &c = slot_map.getv(i).conn;
@ -1536,6 +1581,11 @@ Object::Object() {
_edited=false; _edited=false;
#endif #endif
#ifdef DEBUG_ENABLED
_lock_index.init(1);
#endif
} }

View File

@ -331,7 +331,9 @@ public:
Connection(const Variant& p_variant); Connection(const Variant& p_variant);
}; };
private: private:
#ifdef DEBUG_ENABLED
friend class _ObjectDebugLock;
#endif
friend bool predelete_handler(Object*); friend bool predelete_handler(Object*);
friend void postinitialize_handler(Object*); friend void postinitialize_handler(Object*);
@ -365,7 +367,9 @@ friend void postinitialize_handler(Object*);
HashMap< StringName, Signal, StringNameHasher> signal_map; HashMap< StringName, Signal, StringNameHasher> signal_map;
List<Connection> connections; List<Connection> connections;
#ifdef DEBUG_ENABLED
SafeRefCount _lock_index;
#endif
bool _block_signals; bool _block_signals;
int _predelete_ok; int _predelete_ok;
Set<Object*> change_receptors; Set<Object*> change_receptors;

View File

@ -124,6 +124,11 @@ String OS::get_executable_path() const {
return _execpath; return _execpath;
} }
int OS::get_process_ID() const {
return -1;
};
uint64_t OS::get_frames_drawn() { uint64_t OS::get_frames_drawn() {
return frames_drawn; return frames_drawn;

View File

@ -162,6 +162,7 @@ public:
virtual String get_executable_path() const; virtual String get_executable_path() const;
virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL)=0; virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL)=0;
virtual Error kill(const ProcessID& p_pid)=0; virtual Error kill(const ProcessID& p_pid)=0;
virtual int get_process_ID() const;
virtual Error shell_open(String p_uri); virtual Error shell_open(String p_uri);
virtual Error set_cwd(const String& p_cwd); virtual Error set_cwd(const String& p_cwd);

View File

@ -1,15 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<resource_file type="PackedScene" subresource_count="24" version="1.0" version_name="Godot Engine v1.0.3917-beta1"> <resource_file type="PackedScene" subresource_count="24" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
<ext_resource path="res://robot_demo.*" type="Texture"></ext_resource> <ext_resource path="res://osb_jump.png" type="Texture"></ext_resource>
<ext_resource path="res://osb_jump.*" type="Texture"></ext_resource> <ext_resource path="res://bullet.png" type="Texture"></ext_resource>
<ext_resource path="res://player.*" type="Script"></ext_resource> <ext_resource path="res://osb_right.png" type="Texture"></ext_resource>
<ext_resource path="res://osb_right.*" type="Texture"></ext_resource> <ext_resource path="res://sound_coin.wav" type="Sample"></ext_resource>
<ext_resource path="res://sound_coin.*" type="Sample"></ext_resource> <ext_resource path="res://sound_shoot.wav" type="Sample"></ext_resource>
<ext_resource path="res://sound_jump.*" type="Sample"></ext_resource> <ext_resource path="res://osb_fire.png" type="Texture"></ext_resource>
<ext_resource path="res://sound_shoot.*" type="Sample"></ext_resource> <ext_resource path="res://robot_demo.png" type="Texture"></ext_resource>
<ext_resource path="res://bullet.*" type="Texture"></ext_resource> <ext_resource path="res://osb_left.png" type="Texture"></ext_resource>
<ext_resource path="res://osb_fire.*" type="Texture"></ext_resource> <ext_resource path="res://player.gd" type="Script"></ext_resource>
<ext_resource path="res://osb_left.*" type="Texture"></ext_resource> <ext_resource path="res://sound_jump.wav" type="Sample"></ext_resource>
<resource type="RayShape2D" path="local://1"> <resource type="RayShape2D" path="local://1">
<real name="custom_solver_bias"> 0.5 </real> <real name="custom_solver_bias"> 0.5 </real>
<real name="length"> 20 </real> <real name="length"> 20 </real>
@ -50,30 +50,6 @@
</resource> </resource>
<resource type="Animation" path="local://4"> <resource type="Animation" path="local://4">
<string name="resource/name"> "jumping" </string>
<real name="length"> 0.5 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="3"> 1, 1, 1 </real_array>
<string> "values" </string>
<array len="3" shared="false">
<int> 23 </int>
<int> 24 </int>
<int> 23 </int>
</array>
<string> "times" </string>
<real_array len="3"> 0, 0.25, 0.5 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://5">
<string name="resource/name"> "run" </string> <string name="resource/name"> "run" </string>
<real name="length"> 1.25 </real> <real name="length"> 1.25 </real>
<bool name="loop"> True </bool> <bool name="loop"> True </bool>
@ -100,144 +76,7 @@
</dictionary> </dictionary>
</resource> </resource>
<resource type="Animation" path="local://6"> <resource type="Animation" path="local://5">
<string name="resource/name"> "run_weapon" </string>
<real name="length"> 1.25 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
<string> "values" </string>
<array len="6" shared="false">
<int> 5 </int>
<int> 6 </int>
<int> 7 </int>
<int> 8 </int>
<int> 9 </int>
<int> 5 </int>
</array>
<string> "times" </string>
<real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://7">
<string name="resource/name"> "falling" </string>
<real name="length"> 0.01 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 21 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://8">
<string name="resource/name"> "falling_weapon" </string>
<real name="length"> 0.5 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 26 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://9">
<string name="resource/name"> "idle_weapon" </string>
<real name="length"> 0.5 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 25 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://10">
<string name="resource/name"> "jumping_weapon" </string>
<real name="length"> 0.5 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 26 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://11">
<string name="resource/name"> "crouch" </string>
<real name="length"> 0.01 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 22 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://12">
<string name="resource/name"> "run_gun_fire" </string> <string name="resource/name"> "run_gun_fire" </string>
<real name="length"> 1.25 </real> <real name="length"> 1.25 </real>
<bool name="loop"> True </bool> <bool name="loop"> True </bool>
@ -263,6 +102,167 @@
<real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array> <real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
</dictionary> </dictionary>
</resource>
<resource type="Animation" path="local://6">
<string name="resource/name"> "jumping_weapon" </string>
<real name="length"> 0.5 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 26 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://7">
<string name="resource/name"> "crouch" </string>
<real name="length"> 0.01 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 22 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://8">
<string name="resource/name"> "jumping" </string>
<real name="length"> 0.5 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="3"> 1, 1, 1 </real_array>
<string> "values" </string>
<array len="3" shared="false">
<int> 23 </int>
<int> 24 </int>
<int> 23 </int>
</array>
<string> "times" </string>
<real_array len="3"> 0, 0.25, 0.5 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://9">
<string name="resource/name"> "run_weapon" </string>
<real name="length"> 1.25 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
<string> "values" </string>
<array len="6" shared="false">
<int> 5 </int>
<int> 6 </int>
<int> 7 </int>
<int> 8 </int>
<int> 9 </int>
<int> 5 </int>
</array>
<string> "times" </string>
<real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://10">
<string name="resource/name"> "idle_weapon" </string>
<real name="length"> 0.5 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 25 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://11">
<string name="resource/name"> "falling_weapon" </string>
<real name="length"> 0.5 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 26 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://12">
<string name="resource/name"> "falling" </string>
<real name="length"> 0.01 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 21 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource> </resource>
<resource type="SampleLibrary" path="local://13"> <resource type="SampleLibrary" path="local://13">
<dictionary name="samples/jump" shared="false"> <dictionary name="samples/jump" shared="false">
@ -271,7 +271,7 @@
<string> "pitch" </string> <string> "pitch" </string>
<real> 1 </real> <real> 1 </real>
<string> "sample" </string> <string> "sample" </string>
<resource resource_type="Sample" path="res://sound_jump.*"> </resource> <resource resource_type="Sample" path="res://sound_jump.wav"> </resource>
</dictionary> </dictionary>
<dictionary name="samples/shoot" shared="false"> <dictionary name="samples/shoot" shared="false">
<string> "db" </string> <string> "db" </string>
@ -279,7 +279,7 @@
<string> "pitch" </string> <string> "pitch" </string>
<real> 1 </real> <real> 1 </real>
<string> "sample" </string> <string> "sample" </string>
<resource resource_type="Sample" path="res://sound_shoot.*"> </resource> <resource resource_type="Sample" path="res://sound_shoot.wav"> </resource>
</dictionary> </dictionary>
<dictionary name="samples/coin" shared="false"> <dictionary name="samples/coin" shared="false">
<string> "db" </string> <string> "db" </string>
@ -287,7 +287,7 @@
<string> "pitch" </string> <string> "pitch" </string>
<real> 1 </real> <real> 1 </real>
<string> "sample" </string> <string> "sample" </string>
<resource resource_type="Sample" path="res://sound_coin.*"> </resource> <resource resource_type="Sample" path="res://sound_coin.wav"> </resource>
</dictionary> </dictionary>
</resource> </resource>
@ -300,7 +300,7 @@
<string> "visibility/visible" </string> <string> "visibility/visible" </string>
<string> "visibility/opacity" </string> <string> "visibility/opacity" </string>
<string> "visibility/self_opacity" </string> <string> "visibility/self_opacity" </string>
<string> "visibility/on_top" </string> <string> "visibility/behind_parent" </string>
<string> "transform/pos" </string> <string> "transform/pos" </string>
<string> "transform/rot" </string> <string> "transform/rot" </string>
<string> "transform/scale" </string> <string> "transform/scale" </string>
@ -396,15 +396,15 @@
<string> "playback/default_blend_time" </string> <string> "playback/default_blend_time" </string>
<string> "root/root" </string> <string> "root/root" </string>
<string> "anims/idle" </string> <string> "anims/idle" </string>
<string> "anims/jumping" </string>
<string> "anims/run" </string> <string> "anims/run" </string>
<string> "anims/run_weapon" </string> <string> "anims/standing_weapon_ready" </string>
<string> "anims/falling" </string>
<string> "anims/falling_weapon" </string>
<string> "anims/idle_weapon" </string>
<string> "anims/jumping_weapon" </string> <string> "anims/jumping_weapon" </string>
<string> "anims/crouch" </string> <string> "anims/crouch" </string>
<string> "anims/standing_weapon_ready" </string> <string> "anims/jumping" </string>
<string> "anims/run_weapon" </string>
<string> "anims/idle_weapon" </string>
<string> "anims/falling_weapon" </string>
<string> "anims/falling" </string>
<string> "playback/active" </string> <string> "playback/active" </string>
<string> "playback/speed" </string> <string> "playback/speed" </string>
<string> "blend_times" </string> <string> "blend_times" </string>
@ -476,18 +476,19 @@
<array len="71" shared="false"> <array len="71" shared="false">
<bool> True </bool> <bool> True </bool>
<real> 1 </real> <real> 1 </real>
<bool> False </bool>
<vector2> 0, 0 </vector2> <vector2> 0, 0 </vector2>
<real> 0 </real> <real> 0 </real>
<vector2> 1, 1 </vector2> <vector2> 1, 1 </vector2>
<int> 2 </int> <int> 2 </int>
<resource resource_type="Shape2D" path="local://1"> </resource> <resource resource_type="Shape2D" path="local://1"> </resource>
<matrix32> 1, -0, 0, 1.76469, 0.291992, -12.1587 </matrix32> <matrix32> 1, -0, 0, 1.76469, 0.291992, -12.1587 </matrix32>
<bool> False </bool>
<resource resource_type="Shape2D" path="local://2"> </resource> <resource resource_type="Shape2D" path="local://2"> </resource>
<matrix32> 1, -0, 0, 1, 0, 0 </matrix32> <matrix32> 1, -0, 0, 1, 0, 0 </matrix32>
<real> 3 </real> <real> 3 </real>
<int> 0 </int>
<int> 3 </int> <int> 3 </int>
<resource resource_type="Script" path="res://player.*"> </resource> <resource resource_type="Script" path="res://player.gd"> </resource>
<dictionary shared="false"> <dictionary shared="false">
<string> "__editor_plugin_states__" </string> <string> "__editor_plugin_states__" </string>
<dictionary shared="false"> <dictionary shared="false">
@ -507,7 +508,7 @@
<string> "zoom" </string> <string> "zoom" </string>
<real> 2.272073 </real> <real> 2.272073 </real>
<string> "ofs" </string> <string> "ofs" </string>
<vector2> -125.17, -137.776 </vector2> <vector2> -181.946, -86.2812 </vector2>
</dictionary> </dictionary>
<string> "3D" </string> <string> "3D" </string>
<dictionary shared="false"> <dictionary shared="false">
@ -594,20 +595,20 @@
<int> 0 </int> <int> 0 </int>
</dictionary> </dictionary>
<string> "__editor_plugin_screen__" </string> <string> "__editor_plugin_screen__" </string>
<string> "2D" </string> <string> "3D" </string>
</dictionary> </dictionary>
<resource resource_type="Texture" path="res://robot_demo.*"> </resource> <resource resource_type="Texture" path="res://robot_demo.png"> </resource>
<int> 16 </int> <int> 16 </int>
<int> 1 </int>
<color> 1, 1, 1, 1 </color> <color> 1, 1, 1, 1 </color>
<rect2> 0, 0, 0, 0 </rect2> <rect2> 0, 0, 0, 0 </rect2>
<real> 0.363636 </real> <real> 0.363636 </real>
<int> 1 </int>
<vector2> 20.7312, 3.21187 </vector2> <vector2> 20.7312, 3.21187 </vector2>
<real> 83.450417 </real> <real> 83.450417 </real>
<int> 4 </int> <int> 4 </int>
<real> 0.3 </real> <real> 0.3 </real>
<real> 0.1 </real> <real> 0.1 </real>
<resource resource_type="Texture" path="res://bullet.*"> </resource> <resource resource_type="Texture" path="res://bullet.png"> </resource>
<real> 180 </real> <real> 180 </real>
<real> 20 </real> <real> 20 </real>
<real> 9.8 </real> <real> 9.8 </real>
@ -630,7 +631,6 @@
<array len="0" shared="false"> <array len="0" shared="false">
</array> </array>
<string> "" </string> <string> "" </string>
<int> 0 </int>
<int> 10000000 </int> <int> 10000000 </int>
<real> 0.2 </real> <real> 0.2 </real>
<vector2> 31.2428, 4.08784 </vector2> <vector2> 31.2428, 4.08784 </vector2>
@ -641,20 +641,20 @@
<vector2_array len="3"> -0.138023, 16.5036, -19.902, -24.8691, 19.3625, -24.6056 </vector2_array> <vector2_array len="3"> -0.138023, 16.5036, -19.902, -24.8691, 19.3625, -24.6056 </vector2_array>
<vector2> 27.7593, 360.87 </vector2> <vector2> 27.7593, 360.87 </vector2>
<vector2> 1.49157, 1.46265 </vector2> <vector2> 1.49157, 1.46265 </vector2>
<resource resource_type="Texture" path="res://osb_left.*"> </resource> <resource resource_type="Texture" path="res://osb_left.png"> </resource>
<resource name=""></resource> <string> "move_left" </string> <resource name=""></resource> <string> "move_left" </string>
<vector2> 121.542, 361.415 </vector2> <vector2> 121.542, 361.415 </vector2>
<resource resource_type="Texture" path="res://osb_right.*"> </resource> <resource resource_type="Texture" path="res://osb_right.png"> </resource>
<string> "move_right" </string> <string> "move_right" </string>
<vector2> 666.224, 359.02 </vector2> <vector2> 666.224, 359.02 </vector2>
<resource resource_type="Texture" path="res://osb_jump.*"> </resource> <resource resource_type="Texture" path="res://osb_jump.png"> </resource>
<string> "jump" </string> <string> "jump" </string>
<vector2> 668.073, 262.788 </vector2> <vector2> 668.073, 262.788 </vector2>
<resource resource_type="Texture" path="res://osb_fire.*"> </resource> <resource resource_type="Texture" path="res://osb_fire.png"> </resource>
<string> "shoot" </string> <string> "shoot" </string>
</array> </array>
<string> "nodes" </string> <string> "nodes" </string>
<int_array len="572"> -1, -1, 1, 0, -1, 28, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, 8, 13, 9, 14, 10, 15, 8, 16, 5, 17, 11, 18, 3, 19, 3, 20, 0, 21, 8, 22, 12, 23, 8, 24, 0, 25, 0, 26, 2, 27, 3, 28, 13, 29, 14, 0, 0, 0, 31, 30, -1, 18, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 32, 15, 33, 0, 34, 2, 35, 8, 36, 8, 37, 5, 38, 16, 39, 17, 40, 18, 41, 8, 42, 19, 0, 1, 0, 44, 43, -1, 57, 2, 0, 3, 1, 4, 20, 5, 0, 45, 17, 6, 21, 7, 22, 8, 4, 46, 23, 47, 24, 48, 1, 49, 3, 50, 24, 51, 8, 52, 2, 53, 2, 54, 8, 55, 25, 56, 8, 57, 8, 58, 26, 59, 3, 60, 27, 61, 28, 62, 1, 63, 3, 64, 3, 65, 29, 66, 3, 67, 3, 68, 3, 69, 30, 70, 30, 71, 3, 72, 3, 73, 3, 74, 3, 75, 30, 76, 3, 77, 3, 78, 3, 79, 3, 80, 3, 81, 3, 82, 3, 83, 3, 84, 3, 85, 5, 86, 3, 87, 18, 88, 1, 89, 31, 90, 1, 91, 32, 92, 1, 93, 33, 94, 34, 0, 0, 0, 96, 95, -1, 17, 97, 17, 98, 3, 99, 35, 100, 36, 101, 37, 102, 38, 103, 39, 104, 40, 105, 41, 106, 42, 107, 43, 108, 44, 109, 45, 110, 0, 111, 30, 112, 46, 113, 47, 0, 0, 0, 115, 114, -1, 22, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 33, 0, 116, 8, 117, 0, 118, 3, 119, 4, 120, 48, 121, 48, 122, 49, 123, 49, 124, 0, 125, 0, 126, 50, 127, 50, 128, 50, 129, 50, 0, 0, 0, 131, 130, -1, 7, 2, 0, 3, 1, 4, 1, 5, 0, 6, 51, 7, 3, 8, 4, 0, 0, 0, 132, 132, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 52, 7, 3, 8, 53, 133, 6, 134, 8, 0, 0, 0, 136, 135, -1, 14, 137, 12, 138, 54, 139, 3, 140, 1, 141, 3, 142, 3, 143, 3, 144, 55, 145, 55, 146, 55, 147, 55, 148, 5, 149, 3, 150, 3, 0, 0, 0, 151, 151, -1, 9, 2, 0, 3, 1, 4, 1, 5, 0, 6, 2, 7, 3, 8, 4, 152, 48, 153, 56, 0, 0, 0, 155, 154, -1, 4, 156, 48, 34, 2, 157, 3, 158, 4, 0, 9, 0, 160, 159, -1, 13, 2, 0, 3, 1, 4, 1, 5, 0, 6, 57, 7, 3, 8, 58, 161, 59, 162, 60, 163, 60, 164, 0, 165, 61, 166, 17, 0, 9, 0, 160, 167, -1, 13, 2, 0, 3, 1, 4, 1, 5, 0, 6, 62, 7, 3, 8, 58, 161, 63, 162, 60, 163, 60, 164, 0, 165, 64, 166, 17, 0, 9, 0, 160, 168, -1, 13, 2, 0, 3, 1, 4, 1, 5, 0, 6, 65, 7, 3, 8, 58, 161, 66, 162, 60, 163, 60, 164, 8, 165, 67, 166, 17, 0, 9, 0, 160, 169, -1, 13, 2, 0, 3, 1, 4, 1, 5, 0, 6, 68, 7, 3, 8, 58, 161, 69, 162, 60, 163, 60, 164, 8, 165, 70, 166, 17, 0 </int_array> <int_array len="572"> -1, -1, 1, 0, -1, 28, 2, 0, 3, 1, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 8, 12, 2, 13, 9, 14, 10, 15, 2, 16, 6, 17, 11, 18, 4, 19, 4, 20, 0, 21, 12, 22, 13, 23, 2, 24, 0, 25, 0, 26, 3, 27, 4, 28, 14, 29, 15, 0, 0, 0, 31, 30, -1, 18, 2, 0, 3, 1, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 32, 16, 33, 0, 34, 3, 35, 2, 36, 2, 37, 6, 38, 17, 39, 12, 40, 18, 41, 2, 42, 19, 0, 1, 0, 44, 43, -1, 57, 2, 0, 3, 1, 4, 20, 5, 2, 45, 21, 6, 22, 7, 23, 8, 5, 46, 24, 47, 25, 48, 1, 49, 4, 50, 25, 51, 2, 52, 3, 53, 3, 54, 2, 55, 26, 56, 2, 57, 2, 58, 27, 59, 4, 60, 28, 61, 29, 62, 1, 63, 4, 64, 4, 65, 30, 66, 4, 67, 4, 68, 4, 69, 31, 70, 31, 71, 4, 72, 4, 73, 4, 74, 4, 75, 31, 76, 4, 77, 4, 78, 4, 79, 4, 80, 4, 81, 4, 82, 4, 83, 4, 84, 4, 85, 6, 86, 4, 87, 18, 88, 1, 89, 32, 90, 1, 91, 33, 92, 1, 93, 34, 94, 35, 0, 0, 0, 96, 95, -1, 17, 97, 21, 98, 4, 99, 36, 100, 37, 101, 38, 102, 39, 103, 40, 104, 41, 105, 42, 106, 43, 107, 44, 108, 45, 109, 46, 110, 0, 111, 31, 112, 47, 113, 48, 0, 0, 0, 115, 114, -1, 22, 2, 0, 3, 1, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 33, 0, 116, 2, 117, 0, 118, 4, 119, 5, 120, 12, 121, 12, 122, 49, 123, 49, 124, 0, 125, 0, 126, 50, 127, 50, 128, 50, 129, 50, 0, 0, 0, 131, 130, -1, 7, 2, 0, 3, 1, 4, 1, 5, 2, 6, 51, 7, 4, 8, 5, 0, 0, 0, 132, 132, -1, 9, 2, 0, 3, 1, 4, 1, 5, 2, 6, 52, 7, 4, 8, 53, 133, 7, 134, 2, 0, 0, 0, 136, 135, -1, 14, 137, 13, 138, 54, 139, 4, 140, 1, 141, 4, 142, 4, 143, 4, 144, 55, 145, 55, 146, 55, 147, 55, 148, 6, 149, 4, 150, 4, 0, 0, 0, 151, 151, -1, 9, 2, 0, 3, 1, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 152, 12, 153, 56, 0, 0, 0, 155, 154, -1, 4, 156, 12, 34, 3, 157, 4, 158, 5, 0, 9, 0, 160, 159, -1, 13, 2, 0, 3, 1, 4, 1, 5, 2, 6, 57, 7, 4, 8, 58, 161, 59, 162, 60, 163, 60, 164, 0, 165, 61, 166, 21, 0, 9, 0, 160, 167, -1, 13, 2, 0, 3, 1, 4, 1, 5, 2, 6, 62, 7, 4, 8, 58, 161, 63, 162, 60, 163, 60, 164, 0, 165, 64, 166, 21, 0, 9, 0, 160, 168, -1, 13, 2, 0, 3, 1, 4, 1, 5, 2, 6, 65, 7, 4, 8, 58, 161, 66, 162, 60, 163, 60, 164, 2, 165, 67, 166, 21, 0, 9, 0, 160, 169, -1, 13, 2, 0, 3, 1, 4, 1, 5, 2, 6, 68, 7, 4, 8, 58, 161, 69, 162, 60, 163, 60, 164, 2, 165, 70, 166, 21, 0 </int_array>
<string> "conns" </string> <string> "conns" </string>
<int_array len="0"> </int_array> <int_array len="0"> </int_array>
</dictionary> </dictionary>

File diff suppressed because one or more lines are too long

View File

@ -333,6 +333,12 @@ Error OS_Unix::kill(const ProcessID& p_pid) {
return ret?ERR_INVALID_PARAMETER:OK; return ret?ERR_INVALID_PARAMETER:OK;
} }
int OS_Unix::get_process_ID() const {
return getpid();
};
bool OS_Unix::has_environment(const String& p_var) const { bool OS_Unix::has_environment(const String& p_var) const {
return getenv(p_var.utf8().get_data())!=NULL; return getenv(p_var.utf8().get_data())!=NULL;

View File

@ -98,6 +98,7 @@ public:
virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL); virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL);
virtual Error kill(const ProcessID& p_pid); virtual Error kill(const ProcessID& p_pid);
virtual int get_process_ID() const;
virtual bool has_environment(const String& p_var) const; virtual bool has_environment(const String& p_var) const;
virtual String get_environment(const String& p_var) const; virtual String get_environment(const String& p_var) const;

View File

@ -10,7 +10,6 @@ env.modules_sources=[
#env.add_source_files(env.modules_sources,"*.cpp") #env.add_source_files(env.modules_sources,"*.cpp")
Export('env') Export('env')
for x in env.module_list: for x in env.module_list:
if (x in env.disabled_modules): if (x in env.disabled_modules):
continue continue

View File

@ -1095,7 +1095,7 @@ MethodInfo GDFunctions::get_info(Function p_func) {
return mi; return mi;
} break; } break;
case MATH_RAND: { case MATH_RAND: {
MethodInfo mi("rand"); MethodInfo mi("randi");
mi.return_val.type=Variant::INT; mi.return_val.type=Variant::INT;
return mi; return mi;
} break; } break;

View File

@ -635,6 +635,19 @@ Variant GDFunction::call(GDInstance *p_instance,const Variant **p_args, int p_ar
err.argument-=1; err.argument-=1;
} }
} }
} if (methodstr=="free") {
if (err.error==Variant::CallError::CALL_ERROR_INVALID_METHOD) {
if (base->is_ref()) {
err_text="Attempted to free a reference.";
break;
} else if (base->get_type()==Variant::OBJECT) {
err_text="Attempted to free a locked object (calling or emitting).";
break;
}
}
} }
err_text=_get_call_error(err,"function '"+methodstr+"' in base '"+basestr+"'",(const Variant**)argptrs); err_text=_get_call_error(err,"function '"+methodstr+"' in base '"+basestr+"'",(const Variant**)argptrs);
break; break;

View File

@ -11,7 +11,7 @@
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:launchMode="singleTask" android:launchMode="singleTask"
android:screenOrientation="landscape" android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden"> android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

View File

@ -15,8 +15,3 @@
# 'key.alias' for the name of the key to use. # 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target. # The password will be asked during the build when you use the 'release' target.
key.store=/home/luis/Downloads/carnavalguachin.keystore
key.alias=momoselacome
key.store.password=12345678
key.alias.password=12345678

View File

@ -135,7 +135,7 @@ public class Godot extends Activity implements SensorEventListener
}; };
public ResultCallback result_callback; public ResultCallback result_callback;
private PaymentsManager mPaymentsManager; private PaymentsManager mPaymentsManager = null;
@Override protected void onActivityResult (int requestCode, int resultCode, Intent data) { @Override protected void onActivityResult (int requestCode, int resultCode, Intent data) {
if(requestCode == PaymentsManager.REQUEST_CODE_FOR_PURCHASE){ if(requestCode == PaymentsManager.REQUEST_CODE_FOR_PURCHASE){
@ -168,6 +168,7 @@ public class Godot extends Activity implements SensorEventListener
@Override protected void onCreate(Bundle icicle) { @Override protected void onCreate(Bundle icicle) {
System.out.printf("** GODOT ACTIVITY CREATED HERE ***\n");
super.onCreate(icicle); super.onCreate(icicle);
_self = this; _self = this;

View File

@ -0,0 +1,83 @@
package com.android.godot;
import android.app.Activity;
public class GodotPaymentV3 extends Godot.SingletonBase {
private Godot activity;
private Integer purchaseCallbackId = 0;
private String accessToken;
private String purchaseValidationUrlPrefix;
public void purchase( String _sku) {
final String sku = _sku;
activity.getPaymentsManager().setBaseSingleton(this);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
activity.getPaymentsManager().requestPurchase(sku);
}
});
};
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"});
activity=(Godot) p_activity;
}
public void callbackSuccess(){
GodotLib.callobject(purchaseCallbackId, "purchase_success", new Object[]{});
}
public void callbackFail(){
GodotLib.callobject(purchaseCallbackId, "purchase_fail", new Object[]{});
}
public void callbackCancel(){
GodotLib.callobject(purchaseCallbackId, "purchase_cancel", new Object[]{});
}
public int getPurchaseCallbackId() {
return purchaseCallbackId;
}
public void setPurchaseCallbackId(int purchaseCallbackId) {
this.purchaseCallbackId = purchaseCallbackId;
}
public String getPurchaseValidationUrlPrefix(){
return this.purchaseValidationUrlPrefix ;
}
public void setPurchaseValidationUrlPrefix(String url){
this.purchaseValidationUrlPrefix = url;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
}

View File

@ -0,0 +1,71 @@
package com.android.godot.payments;
import com.android.vending.billing.IInAppBillingService;
import android.content.Context;
import android.os.AsyncTask;
import android.os.RemoteException;
import android.util.Log;
abstract public class ConsumeTask {
private Context context;
private IInAppBillingService mService;
public ConsumeTask(IInAppBillingService mService, Context context ){
this.context = context;
this.mService = mService;
}
public void consume(final String sku){
// Log.d("XXX", "Consuming product " + sku);
PaymentsCache pc = new PaymentsCache(context);
Boolean isBlocked = pc.getConsumableFlag("block", sku);
String _token = pc.getConsumableValue("token", sku);
// Log.d("XXX", "token " + _token);
if(!isBlocked && _token == null){
// _token = "inapp:"+context.getPackageName()+":android.test.purchased";
// Log.d("XXX", "Consuming product " + sku + " with token " + _token);
}else if(!isBlocked){
// Log.d("XXX", "It is not blocked ¿?");
return;
}else if(_token == null){
// Log.d("XXX", "No token available");
this.error("No token for sku:" + sku);
return;
}
final String token = _token;
new AsyncTask<String, String, String>(){
@Override
protected String doInBackground(String... params) {
try {
// Log.d("XXX", "Requesting to release item.");
int response = mService.consumePurchase(3, context.getPackageName(), token);
// Log.d("XXX", "release response code: " + response);
if(response == 0 || response == 8){
return null;
}
} catch (RemoteException e) {
return e.getMessage();
}
return "Some error";
}
protected void onPostExecute(String param){
if(param == null){
success();
}else{
error(param);
}
}
}.execute();
}
abstract protected void success();
abstract protected void error(String message);
}

View File

@ -0,0 +1,79 @@
package com.android.godot.payments;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.godot.GodotLib;
import com.android.godot.utils.Crypt;
import com.android.vending.billing.IInAppBillingService;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
abstract public class HandlePurchaseTask {
private Activity context;
public HandlePurchaseTask(Activity context ){
this.context = context;
}
public void handlePurchaseRequest(int resultCode, Intent data){
// Log.d("XXX", "Handling purchase response");
// int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
PaymentsCache pc = new PaymentsCache(context);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
// String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
if (resultCode == Activity.RESULT_OK) {
try {
Log.d("SARLANGA", purchaseData);
JSONObject jo = new JSONObject(purchaseData);
// String sku = jo.getString("productId");
// alert("You have bought the " + sku + ". Excellent choice, aventurer!");
// String orderId = jo.getString("orderId");
// String packageName = jo.getString("packageName");
String productId = jo.getString("productId");
// Long purchaseTime = jo.getLong("purchaseTime");
// Integer state = jo.getInt("purchaseState");
String developerPayload = jo.getString("developerPayload");
String purchaseToken = jo.getString("purchaseToken");
if(! pc.getConsumableValue("validation_hash", productId).equals(developerPayload) ) {
error("Untrusted callback");
return;
}
pc.setConsumableValue("ticket", productId, purchaseData);
pc.setConsumableFlag("block", productId, true);
pc.setConsumableValue("token", productId, purchaseToken);
success(purchaseToken, productId);
return;
} catch (JSONException e) {
error(e.getMessage());
}
}else if( resultCode == Activity.RESULT_CANCELED){
canceled();
}
}
abstract protected void success(String purchaseToken, String sku);
abstract protected void error(String message);
abstract protected void canceled();
}

View File

@ -0,0 +1,42 @@
package com.android.godot.payments;
import android.content.Context;
import android.content.SharedPreferences;
public class PaymentsCache {
public Context context;
public PaymentsCache(Context context){
this.context = context;
}
public void setConsumableFlag(String set, String sku, Boolean flag){
SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean(sku, flag);
editor.commit();
}
public boolean getConsumableFlag(String set, String sku){
SharedPreferences sharedPref = context.getSharedPreferences(
"consumables_" + set, Context.MODE_PRIVATE);
return sharedPref.getBoolean(sku, false);
}
public void setConsumableValue(String set, String sku, String value){
SharedPreferences sharedPref = context.getSharedPreferences("consumables_" + set, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(sku, value);
editor.commit();
}
public String getConsumableValue(String set, String sku){
SharedPreferences sharedPref = context.getSharedPreferences(
"consumables_" + set, Context.MODE_PRIVATE);
return sharedPref.getString(sku, null);
}
}

View File

@ -0,0 +1,151 @@
package com.android.godot.payments;
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 com.android.godot.Godot;
import com.android.godot.GodotPaymentV3;
import com.android.vending.billing.IInAppBillingService;
public class PaymentsManager {
public static final int BILLING_RESPONSE_RESULT_OK = 0;
public static final int REQUEST_CODE_FOR_PURCHASE = 0x1001;
private Activity activity;
IInAppBillingService mService;
public void setActivity(Activity activity){
this.activity = activity;
}
public static PaymentsManager createManager(Activity activity){
PaymentsManager manager = new PaymentsManager(activity);
return manager;
}
private PaymentsManager(Activity activity){
this.activity = activity;
}
public PaymentsManager initService(){
activity.bindService(
new Intent("com.android.vending.billing.InAppBillingService.BIND"),
mServiceConn,
Context.BIND_AUTO_CREATE);
return this;
}
public void destroy(){
if (mService != null) {
activity.unbindService(mServiceConn);
}
}
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(String sku){
new PurchaseTask(mService, Godot.getInstance()) {
@Override
protected void error(String message) {
godotPaymentV3.callbackFail();
}
@Override
protected void canceled() {
godotPaymentV3.callbackCancel();
}
}.purchase(sku);
}
public void processPurchaseResponse(int resultCode, Intent data) {
new HandlePurchaseTask(activity){
@Override
protected void success(String purchaseToken, String sku) {
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){
@Override
protected void success() {
new ConsumeTask(mService, activity) {
@Override
protected void success() {
godotPaymentV3.callbackSuccess();
}
@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);
}
private GodotPaymentV3 godotPaymentV3;
public void setBaseSingleton(GodotPaymentV3 godotPaymentV3) {
this.godotPaymentV3 = godotPaymentV3;
}
}

View File

@ -0,0 +1,121 @@
package com.android.godot.payments;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.godot.GodotLib;
import com.android.godot.utils.Crypt;
import com.android.vending.billing.IInAppBillingService;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
abstract public class PurchaseTask {
private Activity context;
private IInAppBillingService mService;
public PurchaseTask(IInAppBillingService mService, Activity context ){
this.context = context;
this.mService = mService;
}
private boolean isLooping = false;
public void purchase(final String sku){
// Log.d("XXX", "Starting purchase");
PaymentsCache pc = new PaymentsCache(context);
Boolean isBlocked = pc.getConsumableFlag("block", sku);
// if(isBlocked){
// Log.d("XXX", "Is awaiting payment confirmation");
// error("Awaiting payment confirmation");
// return;
// }
final String hash = Crypt.createRandomHash() + Crypt.createRandomHash();
Bundle buyIntentBundle;
try {
buyIntentBundle = mService.getBuyIntent(3, context.getApplicationContext().getPackageName(), sku, "inapp", hash );
} catch (RemoteException e) {
// Log.d("XXX", "Error: " + e.getMessage());
error(e.getMessage());
return;
}
Object rc = buyIntentBundle.get("RESPONSE_CODE");
int responseCode = 0;
if(rc == null){
responseCode = PaymentsManager.BILLING_RESPONSE_RESULT_OK;
}else if( rc instanceof Integer){
responseCode = ((Integer)rc).intValue();
}else if( rc instanceof Long){
responseCode = (int)((Long)rc).longValue();
}
// Log.d("XXX", "Buy intent response code: " + responseCode);
if(responseCode == 1 || responseCode == 3 || responseCode == 4){
canceled();
return ;
}
if(responseCode == 7){
new ConsumeTask(mService, context) {
@Override
protected void success() {
// Log.d("XXX", "Product was erroniously purchased!");
if(isLooping){
// Log.d("XXX", "It is looping");
error("Error while purchasing product");
return;
}
isLooping=true;
PurchaseTask.this.purchase(sku);
}
@Override
protected void error(String message) {
PurchaseTask.this.error(message);
}
}.consume(sku);
return;
}
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
pc.setConsumableValue("validation_hash", sku, hash);
try {
if(context == null){
// Log.d("XXX", "No context!");
}
if(pendingIntent == null){
// Log.d("XXX", "No pending intent");
}
// Log.d("XXX", "Starting activity for purchase!");
context.startIntentSenderForResult(
pendingIntent.getIntentSender(),
PaymentsManager.REQUEST_CODE_FOR_PURCHASE,
new Intent(),
Integer.valueOf(0), Integer.valueOf(0),
Integer.valueOf(0));
} catch (SendIntentException e) {
error(e.getMessage());
}
}
abstract protected void error(String message);
abstract protected void canceled();
}

View File

@ -0,0 +1,97 @@
package com.android.godot.payments;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.godot.Godot;
import com.android.godot.GodotLib;
import com.android.godot.GodotPaymentV3;
import com.android.godot.utils.Crypt;
import com.android.godot.utils.HttpRequester;
import com.android.godot.utils.RequestParams;
import com.android.vending.billing.IInAppBillingService;
import android.app.Activity;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
abstract public class ValidateTask {
private Activity context;
private GodotPaymentV3 godotPaymentsV3;
public ValidateTask(Activity context, GodotPaymentV3 godotPaymentsV3){
this.context = context;
this.godotPaymentsV3 = godotPaymentsV3;
}
public void validatePurchase(final String sku){
new AsyncTask<String, String, String>(){
private ProgressDialog dialog;
@Override
protected void onPreExecute(){
dialog = ProgressDialog.show(context, null, "Please wait...");
}
@Override
protected String doInBackground(String... params) {
PaymentsCache pc = new PaymentsCache(context);
String url = godotPaymentsV3.getPurchaseValidationUrlPrefix();
RequestParams param = new RequestParams();
param.setUrl(url);
param.put("ticket", pc.getConsumableValue("ticket", sku));
param.put("purchaseToken", pc.getConsumableValue("token", sku));
param.put("sku", sku);
// Log.d("XXX", "Haciendo request a " + url);
// Log.d("XXX", "ticket: " + pc.getConsumableValue("ticket", sku));
// Log.d("XXX", "purchaseToken: " + pc.getConsumableValue("token", sku));
// Log.d("XXX", "sku: " + sku);
param.put("package", context.getApplicationContext().getPackageName());
HttpRequester requester = new HttpRequester();
String jsonResponse = requester.post(param);
// Log.d("XXX", "Validation response:\n"+jsonResponse);
return jsonResponse;
}
@Override
protected void onPostExecute(String response){
if(dialog != null){
dialog.dismiss();
}
JSONObject j;
try {
j = new JSONObject(response);
if(j.getString("status").equals("OK")){
success();
return;
}else if(j.getString("status") != null){
error(j.getString("message"));
}else{
error("Connection error");
}
} catch (JSONException e) {
error(e.getMessage());
}catch (Exception e){
error(e.getMessage());
}
}
}.execute();
}
abstract protected void success();
abstract protected void error(String message);
abstract protected void canceled();
}

View File

@ -0,0 +1,39 @@
package com.android.godot.utils;
import java.security.MessageDigest;
import java.util.Random;
public class Crypt {
public static String md5(String input){
try {
// Create MD5 Hash
MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
digest.update(input.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuffer hexString = new StringBuffer();
for (int i=0; i<messageDigest.length; i++)
hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
return hexString.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public static String createRandomHash(){
return md5(Long.toString(createRandomLong()));
}
public static long createAbsRandomLong(){
return Math.abs(createRandomLong());
}
public static long createRandomLong(){
Random r = new Random();
return r.nextLong();
}
}

View File

@ -0,0 +1,54 @@
package com.android.godot.utils;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.conn.ssl.SSLSocketFactory;
/**
*
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class CustomSSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public CustomSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}

View File

@ -0,0 +1,206 @@
package com.android.godot.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
/**
*
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class HttpRequester {
private Context context;
private static final int TTL = 600000; // 10 minutos
private long cttl=0;
public HttpRequester(){
// Log.d("XXX", "Creando http request sin contexto");
}
public HttpRequester(Context context){
this.context=context;
// Log.d("XXX", "Creando http request con contexto");
}
public String post(RequestParams params){
HttpPost httppost = new HttpPost(params.getUrl());
try {
httppost.setEntity(new UrlEncodedFormEntity(params.toPairsList()));
return request(httppost);
} catch (UnsupportedEncodingException e) {
return null;
}
}
public String get(RequestParams params){
String response = getResponseFromCache(params.getUrl());
if(response == null){
// Log.d("XXX", "Cache miss!");
HttpGet httpget = new HttpGet(params.getUrl());
long timeInit = new Date().getTime();
response = request(httpget);
long delay = new Date().getTime() - timeInit;
Log.d("com.app11tt.android.utils.HttpRequest::get(url)", "Url: " + params.getUrl() + " downloaded in " + String.format("%.03f", delay/1000.0f) + " seconds");
if(response == null || response.length() == 0){
response = "";
}else{
saveResponseIntoCache(params.getUrl(), response);
}
}
Log.d("XXX", "Req: " + params.getUrl());
Log.d("XXX", "Resp: " + response);
return response;
}
private String request(HttpUriRequest request){
// Log.d("XXX", "Haciendo request a: " + request.getURI() );
Log.d("PPP", "Haciendo request a: " + request.getURI() );
long init = new Date().getTime();
HttpClient httpclient = getNewHttpClient();
HttpParams httpParameters = httpclient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 0);
HttpConnectionParams.setSoTimeout(httpParameters, 0);
HttpConnectionParams.setTcpNoDelay(httpParameters, true);
try {
HttpResponse response = httpclient.execute(request);
Log.d("PPP", "Fin de request (" + (new Date().getTime() - init) + ") a: " + request.getURI() );
// Log.d("XXX1", "Status:" + response.getStatusLine().toString());
if(response.getStatusLine().getStatusCode() == 200){
String strResponse = EntityUtils.toString(response.getEntity());
// Log.d("XXX2", strResponse);
return strResponse;
}else{
Log.d("XXX3", "Response status code:" + response.getStatusLine().getStatusCode() + "\n" + EntityUtils.toString(response.getEntity()));
return null;
}
} catch (ClientProtocolException e) {
Log.d("XXX3", e.getMessage());
} catch (IOException e) {
Log.d("XXX4", e.getMessage());
}
return null;
}
private HttpClient getNewHttpClient() {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
return new DefaultHttpClient();
}
}
private static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append((line + "\n"));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
public void saveResponseIntoCache(String request, String response){
if(context == null){
// Log.d("XXX", "No context, cache failed!");
return;
}
SharedPreferences sharedPref = context.getSharedPreferences("http_get_cache", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("request_" + Crypt.md5(request), response);
editor.putLong("request_" + Crypt.md5(request) + "_ttl", new Date().getTime() + getTtl());
editor.commit();
}
public String getResponseFromCache(String request){
if(context == null){
Log.d("XXX", "No context, cache miss");
return null;
}
SharedPreferences sharedPref = context.getSharedPreferences( "http_get_cache", Context.MODE_PRIVATE);
long ttl = getResponseTtl(request);
if(ttl == 0l || (new Date().getTime() - ttl) > 0l){
Log.d("XXX", "Cache invalid ttl:" + ttl + " vs now:" + new Date().getTime());
return null;
}
return sharedPref.getString("request_" + Crypt.md5(request), null);
}
public long getResponseTtl(String request){
SharedPreferences sharedPref = context.getSharedPreferences(
"http_get_cache", Context.MODE_PRIVATE);
return sharedPref.getLong("request_" + Crypt.md5(request) + "_ttl", 0l);
}
public long getTtl() {
return cttl > 0 ? cttl : TTL;
}
public void setTtl(long ttl) {
this.cttl = (ttl*1000) + new Date().getTime();
}
}

View File

@ -0,0 +1,58 @@
package com.android.godot.utils;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
/**
*
* @author Luis Linietsky <luis.linietsky@gmail.com>
*/
public class RequestParams {
private HashMap<String,String> params;
private String url;
public RequestParams(){
params = new HashMap<String,String>();
}
public void put(String key, String value){
params.put(key, value);
}
public String get(String key){
return params.get(key);
}
public void remove(Object key){
params.remove(key);
}
public boolean has(String key){
return params.containsKey(key);
}
public List<NameValuePair> toPairsList(){
List<NameValuePair> fields = new ArrayList<NameValuePair>();
for(String key : params.keySet()){
fields.add(new BasicNameValuePair(key, this.get(key)));
}
return fields;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}

View File

@ -0,0 +1,144 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.vending.billing;
import android.os.Bundle;
/**
* InAppBillingService is the service that provides in-app billing version 3 and beyond.
* This service provides the following features:
* 1. Provides a new API to get details of in-app items published for the app including
* price, type, title and description.
* 2. The purchase flow is synchronous and purchase information is available immediately
* after it completes.
* 3. Purchase information of in-app purchases is maintained within the Google Play system
* till the purchase is consumed.
* 4. An API to consume a purchase of an inapp item. All purchases of one-time
* in-app items are consumable and thereafter can be purchased again.
* 5. An API to get current purchases of the user immediately. This will not contain any
* consumed purchases.
*
* All calls will give a response code with the following possible values
* RESULT_OK = 0 - success
* RESULT_USER_CANCELED = 1 - user pressed back or canceled a dialog
* RESULT_BILLING_UNAVAILABLE = 3 - this billing API version is not supported for the type requested
* RESULT_ITEM_UNAVAILABLE = 4 - requested SKU is not available for purchase
* RESULT_DEVELOPER_ERROR = 5 - invalid arguments provided to the API
* RESULT_ERROR = 6 - Fatal error during the API action
* RESULT_ITEM_ALREADY_OWNED = 7 - Failure to purchase since item is already owned
* RESULT_ITEM_NOT_OWNED = 8 - Failure to consume since item is not owned
*/
interface IInAppBillingService {
/**
* Checks support for the requested billing API version, package and in-app type.
* Minimum API version supported by this interface is 3.
* @param apiVersion the billing version which the app is using
* @param packageName the package name of the calling app
* @param type type of the in-app item being purchased "inapp" for one-time purchases
* and "subs" for subscription.
* @return RESULT_OK(0) on success, corresponding result code on failures
*/
int isBillingSupported(int apiVersion, String packageName, String type);
/**
* Provides details of a list of SKUs
* Given a list of SKUs of a valid type in the skusBundle, this returns a bundle
* with a list JSON strings containing the productId, price, title and description.
* This API can be called with a maximum of 20 SKUs.
* @param apiVersion billing API version that the Third-party is using
* @param packageName the package name of the calling app
* @param skusBundle bundle containing a StringArrayList of SKUs with key "ITEM_ID_LIST"
* @return Bundle containing the following key-value pairs
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
* failure as listed above.
* "DETAILS_LIST" with a StringArrayList containing purchase information
* in JSON format similar to:
* '{ "productId" : "exampleSku", "type" : "inapp", "price" : "$5.00",
* "title : "Example Title", "description" : "This is an example description" }'
*/
Bundle getSkuDetails(int apiVersion, String packageName, String type, in Bundle skusBundle);
/**
* Returns a pending intent to launch the purchase flow for an in-app item by providing a SKU,
* the type, a unique purchase token and an optional developer payload.
* @param apiVersion billing API version that the app is using
* @param packageName package name of the calling app
* @param sku the SKU of the in-app item as published in the developer console
* @param type the type of the in-app item ("inapp" for one-time purchases
* and "subs" for subscription).
* @param developerPayload optional argument to be sent back with the purchase information
* @return Bundle containing the following key-value pairs
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
* failure as listed above.
* "BUY_INTENT" - PendingIntent to start the purchase flow
*
* The Pending intent should be launched with startIntentSenderForResult. When purchase flow
* has completed, the onActivityResult() will give a resultCode of OK or CANCELED.
* If the purchase is successful, the result data will contain the following key-value pairs
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
* failure as listed above.
* "INAPP_PURCHASE_DATA" - String in JSON format similar to
* '{"orderId":"12999763169054705758.1371079406387615",
* "packageName":"com.example.app",
* "productId":"exampleSku",
* "purchaseTime":1345678900000,
* "purchaseToken" : "122333444455555",
* "developerPayload":"example developer payload" }'
* "INAPP_DATA_SIGNATURE" - String containing the signature of the purchase data that
* was signed with the private key of the developer
* TODO: change this to app-specific keys.
*/
Bundle getBuyIntent(int apiVersion, String packageName, String sku, String type,
String developerPayload);
/**
* Returns the current SKUs owned by the user of the type and package name specified along with
* purchase information and a signature of the data to be validated.
* This will return all SKUs that have been purchased in V3 and managed items purchased using
* V1 and V2 that have not been consumed.
* @param apiVersion billing API version that the app is using
* @param packageName package name of the calling app
* @param type the type of the in-app items being requested
* ("inapp" for one-time purchases and "subs" for subscription).
* @param continuationToken to be set as null for the first call, if the number of owned
* skus are too many, a continuationToken is returned in the response bundle.
* This method can be called again with the continuation token to get the next set of
* owned skus.
* @return Bundle containing the following key-value pairs
* "RESPONSE_CODE" with int value, RESULT_OK(0) if success, other response codes on
* failure as listed above.
* "INAPP_PURCHASE_ITEM_LIST" - StringArrayList containing the list of SKUs
* "INAPP_PURCHASE_DATA_LIST" - StringArrayList containing the purchase information
* "INAPP_DATA_SIGNATURE_LIST"- StringArrayList containing the signatures
* of the purchase information
* "INAPP_CONTINUATION_TOKEN" - String containing a continuation token for the
* next set of in-app purchases. Only set if the
* user has more owned skus than the current list.
*/
Bundle getPurchases(int apiVersion, String packageName, String type, String continuationToken);
/**
* Consume the last purchase of the given SKU. This will result in this item being removed
* from all subsequent responses to getPurchases() and allow re-purchase of this item.
* @param apiVersion billing API version that the app is using
* @param packageName package name of the calling app
* @param purchaseToken token in the purchase information JSON that identifies the purchase
* to be consumed
* @return 0 if consumption succeeded. Appropriate error values for failures.
*/
int consumePurchase(int apiVersion, String packageName, String purchaseToken);
}

View File

@ -440,7 +440,8 @@ public:
case Variant::STRING: { case Variant::STRING: {
jobject o = env->CallObjectMethodA(instance,E->get().method,v); jobject o = env->CallObjectMethodA(instance,E->get().method,v);
String singname = env->GetStringUTFChars((jstring)o, NULL ); String str = env->GetStringUTFChars((jstring)o, NULL );
ret=str;
} break; } break;
case Variant::STRING_ARRAY: { case Variant::STRING_ARRAY: {
@ -665,11 +666,12 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_initialize(JNIEnv * env,
initialized=true; initialized=true;
_godot_instance=activity;
JavaVM *jvm; JavaVM *jvm;
env->GetJavaVM(&jvm); env->GetJavaVM(&jvm);
_godot_instance=env->NewGlobalRef(activity);
// _godot_instance=activity;
__android_log_print(ANDROID_LOG_INFO,"godot","***************** HELLO FROM JNI!!!!!!!!"); __android_log_print(ANDROID_LOG_INFO,"godot","***************** HELLO FROM JNI!!!!!!!!");
@ -816,8 +818,10 @@ static void _initialize_java_modules() {
jmethodID getClassLoader = env->GetMethodID(activityClass,"getClassLoader", "()Ljava/lang/ClassLoader;"); jmethodID getClassLoader = env->GetMethodID(activityClass,"getClassLoader", "()Ljava/lang/ClassLoader;");
jobject cls = env->CallObjectMethod(_godot_instance, getClassLoader); jobject cls = env->CallObjectMethod(_godot_instance, getClassLoader);
//cls=env->NewGlobalRef(cls);
jclass classLoader = env->FindClass("java/lang/ClassLoader"); jclass classLoader = env->FindClass("java/lang/ClassLoader");
//classLoader=(jclass)env->NewGlobalRef(classLoader);
jmethodID findClass = env->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); jmethodID findClass = env->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
@ -835,6 +839,7 @@ static void _initialize_java_modules() {
ERR_EXPLAIN("Couldn't find singleton for class: "+m); ERR_EXPLAIN("Couldn't find singleton for class: "+m);
ERR_CONTINUE(!singletonClass); ERR_CONTINUE(!singletonClass);
} }
//singletonClass=(jclass)env->NewGlobalRef(singletonClass);
__android_log_print(ANDROID_LOG_INFO,"godot","****^*^*?^*^*class data %x",singletonClass); __android_log_print(ANDROID_LOG_INFO,"godot","****^*^*?^*^*class data %x",singletonClass);
jmethodID initialize = env->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lcom/android/godot/Godot$SingletonBase;"); jmethodID initialize = env->GetStaticMethodID(singletonClass, "initialize", "(Landroid/app/Activity;)Lcom/android/godot/Godot$SingletonBase;");

View File

@ -108,8 +108,15 @@ static int frame_count = 0;
if ([[UIDevice currentDevice]respondsToSelector:@selector(identifierForVendor)]) { if ([[UIDevice currentDevice]respondsToSelector:@selector(identifierForVendor)]) {
uuid = [UIDevice currentDevice].identifierForVendor.UUIDString; uuid = [UIDevice currentDevice].identifierForVendor.UUIDString;
}else{ }else{
// return [UIDevice currentDevice]. uniqueIdentifier
uuid = [[UIDevice currentDevice] performSelector:@selector(uniqueIdentifier)]; // before iOS 6, so just generate an identifier and store it
uuid = [[NSUserDefaults standardUserDefaults] objectForKey:@"identiferForVendor"];
if( !uuid ) {
CFUUIDRef cfuuid = CFUUIDCreate(NULL);
uuid = (__bridge_transfer NSString*)CFUUIDCreateString(NULL, cfuuid);
CFRelease(cfuuid);
[[NSUserDefaults standardUserDefaults] setObject:uuid forKey:@"identifierForVendor"];
}
} }
OSIPhone::get_singleton()->set_unique_ID(String::utf8([uuid UTF8String])); OSIPhone::get_singleton()->set_unique_ID(String::utf8([uuid UTF8String]));

View File

@ -37,7 +37,6 @@ def get_flags():
('tools', 'yes'), ('tools', 'yes'),
('nedmalloc', 'no'), ('nedmalloc', 'no'),
('webp', 'yes'), ('webp', 'yes'),
('module_FacebookScorer_ios_enabled', 'no'),
] ]

View File

@ -64,25 +64,22 @@ bool _play_video(String p_path) {
p_path = Globals::get_singleton()->globalize_path(p_path); p_path = Globals::get_singleton()->globalize_path(p_path);
// NSString *file_path = [NSString stringWithCString:p_path.utf8().get_data() encoding:NSASCIIStringEncoding];
NSString* file_path = [[[NSString alloc] initWithUTF8String:p_path.utf8().get_data()] autorelease]; NSString* file_path = [[[NSString alloc] initWithUTF8String:p_path.utf8().get_data()] autorelease];
NSURL *file_url = [NSURL fileURLWithPath:file_path]; NSURL *file_url = [NSURL fileURLWithPath:file_path];
_instance.moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:file_url]; _instance.moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:file_url];
_instance.moviePlayerController.controlStyle = MPMovieControlStyleNone; _instance.moviePlayerController.controlStyle = MPMovieControlStyleNone;
[_instance.moviePlayerController setScalingMode:MPMovieScalingModeAspectFit]; // [_instance.moviePlayerController setScalingMode:MPMovieScalingModeAspectFit];
// [_instance.moviePlayerController setScalingMode:MPMovieScalingModeAspectFill]; [_instance.moviePlayerController setScalingMode:MPMovieScalingModeAspectFill];
[[NSNotificationCenter defaultCenter] addObserver:_instance [[NSNotificationCenter defaultCenter] addObserver:_instance
selector:@selector(moviePlayBackDidFinish:) selector:@selector(moviePlayBackDidFinish:)
name:MPMoviePlayerPlaybackDidFinishNotification name:MPMoviePlayerPlaybackDidFinishNotification
object:_instance.moviePlayerController]; object:_instance.moviePlayerController];
[[_instance window] makeKeyAndVisible]; [_instance.moviePlayerController.view setFrame:_instance.bounds];
_instance.backgroundWindow = [[UIApplication sharedApplication] keyWindow];
[_instance.moviePlayerController.view setFrame:_instance.backgroundWindow.frame];
_instance.moviePlayerController.view.userInteractionEnabled = NO; _instance.moviePlayerController.view.userInteractionEnabled = NO;
[_instance.backgroundWindow addSubview:_instance.moviePlayerController.view]; [_instance addSubview:_instance.moviePlayerController.view];
[_instance.moviePlayerController play]; [_instance.moviePlayerController play];
return true; return true;
@ -484,6 +481,14 @@ static void clear_touches() {
return self; return self;
} }
// -(BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers {
// return YES;
// }
// - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
// return YES;
// }
// Stop animating and release resources when they are no longer needed. // Stop animating and release resources when they are no longer needed.
- (void)dealloc - (void)dealloc
{ {
@ -510,8 +515,4 @@ static void clear_touches() {
_stop_video(); _stop_video();
} }
- (void)handleTap:(UITapGestureRecognizer *)gesture {
NSLog(@"Gesture\n");
}
@end @end

View File

@ -167,6 +167,31 @@ Error InAppStore::request_product_info(Variant p_params) {
ret["type"] = "purchase"; ret["type"] = "purchase";
ret["result"] = "ok"; ret["result"] = "ok";
ret["product_id"] = pid; ret["product_id"] = pid;
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0){
NSURL *receiptFileURL = nil;
NSBundle *bundle = [NSBundle mainBundle];
if ([bundle respondsToSelector:@selector(appStoreReceiptURL)]) {
// Get the transaction receipt file path location in the app bundle.
receiptFileURL = [bundle appStoreReceiptURL];
// Read in the contents of the transaction file.
ret["receipt"] = receiptFileURL;
} else {
// Fall back to deprecated transaction receipt,
// which is still available in iOS 7.
// Use SKPaymentTransaction's transactionReceipt.
ret["receipt"] = transaction.transactionReceipt;
}
}else{
ret["receipt"] = transaction.transactionReceipt;
}
InAppStore::get_singleton()->_post_event(ret); InAppStore::get_singleton()->_post_event(ret);
[[SKPaymentQueue defaultQueue] finishTransaction:transaction]; [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
} break; } break;

View File

@ -38,7 +38,6 @@ def get_flags():
('tools', 'yes'), ('tools', 'yes'),
('nedmalloc', 'no'), ('nedmalloc', 'no'),
('webp', 'yes'), ('webp', 'yes'),
('module_FacebookScorer_ios_enabled', 'no'),
] ]

View File

@ -715,17 +715,18 @@ bool CanvasItem::is_block_transform_notify_enabled() const {
return block_transform_notify; return block_transform_notify;
} }
void CanvasItem::set_on_top(bool p_on_top) { void CanvasItem::set_draw_behind_parent(bool p_enable) {
if (on_top==p_on_top) if (behind==p_enable)
return; return;
on_top=p_on_top; behind=p_enable;
VisualServer::get_singleton()->canvas_item_set_on_top(canvas_item,on_top); VisualServer::get_singleton()->canvas_item_set_on_top(canvas_item,!behind);
} }
bool CanvasItem::is_on_top() const { bool CanvasItem::is_draw_behind_parent_enabled() const{
return on_top; return behind;
} }
@ -764,8 +765,11 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_self_opacity","self_opacity"),&CanvasItem::set_self_opacity); ObjectTypeDB::bind_method(_MD("set_self_opacity","self_opacity"),&CanvasItem::set_self_opacity);
ObjectTypeDB::bind_method(_MD("get_self_opacity"),&CanvasItem::get_self_opacity); ObjectTypeDB::bind_method(_MD("get_self_opacity"),&CanvasItem::get_self_opacity);
ObjectTypeDB::bind_method(_MD("set_on_top","on_top"),&CanvasItem::set_on_top); ObjectTypeDB::bind_method(_MD("set_draw_behind_parent","enabe"),&CanvasItem::set_draw_behind_parent);
ObjectTypeDB::bind_method(_MD("is_on_top"),&CanvasItem::is_on_top); ObjectTypeDB::bind_method(_MD("is_draw_behind_parent_enabled"),&CanvasItem::is_draw_behind_parent_enabled);
ObjectTypeDB::bind_method(_MD("_set_on_top","on_top"),&CanvasItem::_set_on_top);
ObjectTypeDB::bind_method(_MD("_is_on_top"),&CanvasItem::_is_on_top);
//ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform); //ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform);
@ -796,7 +800,8 @@ void CanvasItem::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/visible"), _SCS("_set_visible_"),_SCS("_is_visible_") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/visible"), _SCS("_set_visible_"),_SCS("_is_visible_") );
ADD_PROPERTY( PropertyInfo(Variant::REAL,"visibility/opacity",PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_opacity"),_SCS("get_opacity") ); ADD_PROPERTY( PropertyInfo(Variant::REAL,"visibility/opacity",PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_opacity"),_SCS("get_opacity") );
ADD_PROPERTY( PropertyInfo(Variant::REAL,"visibility/self_opacity",PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_self_opacity"),_SCS("get_self_opacity") ); ADD_PROPERTY( PropertyInfo(Variant::REAL,"visibility/self_opacity",PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_self_opacity"),_SCS("get_self_opacity") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/on_top"), _SCS("set_on_top"),_SCS("is_on_top") ); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/behind_parent"), _SCS("set_draw_behind_parent"),_SCS("is_draw_behind_parent_enabled") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/on_top",PROPERTY_HINT_NONE,"",0), _SCS("_set_on_top"),_SCS("_is_on_top") ); //compatibility
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), _SCS("set_blend_mode"),_SCS("get_blend_mode") ); ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), _SCS("set_blend_mode"),_SCS("get_blend_mode") );
//exporting these two things doesn't really make much sense i think //exporting these two things doesn't really make much sense i think
@ -859,7 +864,7 @@ CanvasItem::CanvasItem() : xform_change(this) {
first_draw=false; first_draw=false;
blend_mode=BLEND_MODE_MIX; blend_mode=BLEND_MODE_MIX;
drawing=false; drawing=false;
on_top=true; behind=false;
block_transform_notify=false; block_transform_notify=false;
viewport=NULL; viewport=NULL;
canvas_layer=NULL; canvas_layer=NULL;

View File

@ -77,7 +77,7 @@ private:
bool pending_children_sort; bool pending_children_sort;
bool drawing; bool drawing;
bool block_transform_notify; bool block_transform_notify;
bool on_top; bool behind;
mutable Matrix32 global_transform; mutable Matrix32 global_transform;
mutable bool global_invalid; mutable bool global_invalid;
@ -102,6 +102,9 @@ private:
void _notify_transform(CanvasItem *p_node); void _notify_transform(CanvasItem *p_node);
void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); }
bool _is_on_top() const { return !is_draw_behind_parent_enabled(); }
protected: protected:
@ -175,8 +178,8 @@ public:
void set_as_toplevel(bool p_toplevel); void set_as_toplevel(bool p_toplevel);
bool is_set_as_toplevel() const; bool is_set_as_toplevel() const;
void set_on_top(bool p_on_top); void set_draw_behind_parent(bool p_enable);
bool is_on_top() const; bool is_draw_behind_parent_enabled() const;
CanvasItem *get_parent_item() const; CanvasItem *get_parent_item() const;

View File

@ -351,11 +351,13 @@ void Control::_notification(int p_notification) {
window->tooltip_timer = memnew( Timer ); window->tooltip_timer = memnew( Timer );
add_child(window->tooltip_timer); add_child(window->tooltip_timer);
window->tooltip_timer->force_parent_owned();
window->tooltip_timer->set_wait_time( GLOBAL_DEF("display/tooltip_delay",0.7)); window->tooltip_timer->set_wait_time( GLOBAL_DEF("display/tooltip_delay",0.7));
window->tooltip_timer->connect("timeout",this,"_window_show_tooltip"); window->tooltip_timer->connect("timeout",this,"_window_show_tooltip");
window->tooltip=NULL; window->tooltip=NULL;
window->tooltip_popup = memnew( TooltipPanel ); window->tooltip_popup = memnew( TooltipPanel );
add_child(window->tooltip_popup); add_child(window->tooltip_popup);
window->tooltip_popup->force_parent_owned();
window->tooltip_label = memnew( TooltipLabel ); window->tooltip_label = memnew( TooltipLabel );
window->tooltip_popup->add_child(window->tooltip_label); window->tooltip_popup->add_child(window->tooltip_label);
window->tooltip_popup->set_as_toplevel(true); window->tooltip_popup->set_as_toplevel(true);

View File

@ -264,6 +264,8 @@ public:
static void set_human_readable_collision_renaming(bool p_enabled); static void set_human_readable_collision_renaming(bool p_enabled);
static void init_node_hrcr(); static void init_node_hrcr();
void force_parent_owned() { data.parent_owned=true; } //hack to avoid duplicate nodes
/* CANVAS */ /* CANVAS */
Node(); Node();

View File

@ -375,6 +375,18 @@ bool BodyPair2DSW::setup(float p_step) {
} }
#endif #endif
c.bounce=MAX(A->get_bounce(),B->get_bounce());
if (c.bounce) {
Vector2 crA( -A->get_angular_velocity() * c.rA.y, A->get_angular_velocity() * c.rA.x );
Vector2 crB( -B->get_angular_velocity() * c.rB.y, B->get_angular_velocity() * c.rB.x );
Vector2 dv = B->get_linear_velocity() + crB - A->get_linear_velocity() - crA;
c.bounce = c.bounce * dv.dot(c.normal);
}
} }
return true; return true;
@ -420,8 +432,7 @@ void BodyPair2DSW::solve(float p_step) {
A->apply_bias_impulse(c.rA,-jb); A->apply_bias_impulse(c.rA,-jb);
B->apply_bias_impulse(c.rB, jb); B->apply_bias_impulse(c.rB, jb);
real_t bounce=MAX(A->get_bounce(),B->get_bounce()); real_t jn = -(c.bounce + vn)*c.mass_normal;
real_t jn = -(bounce + vn)*c.mass_normal;
real_t jnOld = c.acc_normal_impulse; real_t jnOld = c.acc_normal_impulse;
c.acc_normal_impulse = MAX(jnOld + jn, 0.0f); c.acc_normal_impulse = MAX(jnOld + jn, 0.0f);

View File

@ -66,6 +66,8 @@ class BodyPair2DSW : public Constraint2DSW {
bool active; bool active;
Vector2 rA,rB; Vector2 rA,rB;
bool reused; bool reused;
float bounce;
}; };
Vector2 offset_B; //use local A coordinates to avoid numerical issues on collision detection Vector2 offset_B; //use local A coordinates to avoid numerical issues on collision detection

View File

@ -510,6 +510,20 @@ void CodeTextEditor::set_error(const String& p_error) {
} }
void CodeTextEditor::_update_font() {
String editor_font = EditorSettings::get_singleton()->get("text_editor/font");
if (editor_font!="") {
Ref<Font> fnt = ResourceLoader::load(editor_font);
if (fnt.is_valid()) {
text_editor->add_font_override("font",fnt);
return;
}
}
text_editor->add_font_override("font",get_font("source","Fonts"));
}
void CodeTextEditor::_text_changed_idle_timeout() { void CodeTextEditor::_text_changed_idle_timeout() {
@ -527,8 +541,9 @@ void CodeTextEditor::_bind_methods() {
ObjectTypeDB::bind_method("_line_col_changed",&CodeTextEditor::_line_col_changed); ObjectTypeDB::bind_method("_line_col_changed",&CodeTextEditor::_line_col_changed);
ObjectTypeDB::bind_method("_text_changed",&CodeTextEditor::_text_changed); ObjectTypeDB::bind_method("_text_changed",&CodeTextEditor::_text_changed);
ObjectTypeDB::bind_method("_update_font",&CodeTextEditor::_update_font);
ObjectTypeDB::bind_method("_text_changed_idle_timeout",&CodeTextEditor::_text_changed_idle_timeout); ObjectTypeDB::bind_method("_text_changed_idle_timeout",&CodeTextEditor::_text_changed_idle_timeout);
ObjectTypeDB::bind_method("_complete_request",&CodeTextEditor::_complete_request); ObjectTypeDB::bind_method("_complete_request",&CodeTextEditor::_complete_request);
} }
CodeTextEditor::CodeTextEditor() { CodeTextEditor::CodeTextEditor() {
@ -571,4 +586,5 @@ CodeTextEditor::CodeTextEditor() {
text_editor->set_completion(true,cs); text_editor->set_completion(true,cs);
idle->connect("timeout", this,"_text_changed_idle_timeout"); idle->connect("timeout", this,"_text_changed_idle_timeout");
EditorSettings::get_singleton()->connect("settings_changed",this,"_update_font");
} }

View File

@ -131,7 +131,9 @@ class CodeTextEditor : public Control {
Label *error; Label *error;
void _complete_request(const String& p_request,int p_line); void _update_font();
void _complete_request(const String& p_request,int p_line);
protected: protected:
void set_error(const String& p_error); void set_error(const String& p_error);

View File

@ -3263,6 +3263,14 @@ EditorNode::EditorNode() {
editor_register_icons(theme); editor_register_icons(theme);
editor_register_fonts(theme); editor_register_fonts(theme);
String global_font = EditorSettings::get_singleton()->get("global/font");
if (global_font!="") {
Ref<Font> fnt = ResourceLoader::load(global_font);
if (fnt.is_valid()) {
theme->set_default_theme_font(fnt);
}
}
Ref<StyleBoxTexture> focus_sbt=memnew( StyleBoxTexture ); Ref<StyleBoxTexture> focus_sbt=memnew( StyleBoxTexture );
focus_sbt->set_texture(theme->get_icon("EditorFocus","EditorIcons")); focus_sbt->set_texture(theme->get_icon("EditorFocus","EditorIcons"));
for(int i=0;i<4;i++) { for(int i=0;i<4;i++) {

View File

@ -384,6 +384,9 @@ void EditorSettings::_load_defaults() {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
set("global/font","");
hints["global/font"]=PropertyInfo(Variant::STRING,"global/font",PROPERTY_HINT_GLOBAL_FILE,"*.fnt");
set("text_editor/background_color",Color::html("3b000000")); set("text_editor/background_color",Color::html("3b000000"));
set("text_editor/text_color",Color::html("aaaaaa")); set("text_editor/text_color",Color::html("aaaaaa"));
set("text_editor/text_selected_color",Color::html("000000")); set("text_editor/text_selected_color",Color::html("000000"));
@ -398,6 +401,9 @@ void EditorSettings::_load_defaults() {
set("text_editor/idle_parse_delay",2); set("text_editor/idle_parse_delay",2);
set("text_editor/create_signal_callbacks",true); set("text_editor/create_signal_callbacks",true);
set("text_editor/autosave_interval_seconds",60); set("text_editor/autosave_interval_seconds",60);
set("text_editor/font","");
hints["text_editor/font"]=PropertyInfo(Variant::STRING,"text_editor/font",PROPERTY_HINT_GLOBAL_FILE,"*.fnt");
set("3d_editor/default_fov",45.0); set("3d_editor/default_fov",45.0);
set("3d_editor/default_z_near",0.1); set("3d_editor/default_z_near",0.1);
@ -429,9 +435,9 @@ void EditorSettings::_load_defaults() {
set("import/pvrtc_texture_tool",""); set("import/pvrtc_texture_tool","");
#ifdef WINDOWS_ENABLED #ifdef WINDOWS_ENABLED
hints["import/pvrtc_texture_tool"]=PropertyInfo(Variant::STRING,"import/pvrtc_texture_tool",PROPERTY_HINT_FILE,"*.exe"); hints["import/pvrtc_texture_tool"]=PropertyInfo(Variant::STRING,"import/pvrtc_texture_tool",PROPERTY_HINT_GLOBAL_FILE,"*.exe");
#else #else
hints["import/pvrtc_texture_tool"]=PropertyInfo(Variant::STRING,"import/pvrtc_texture_tool",PROPERTY_HINT_FILE,""); hints["import/pvrtc_texture_tool"]=PropertyInfo(Variant::STRING,"import/pvrtc_texture_tool",PROPERTY_HINT_GLOBAL_FILE,"");
#endif #endif
set("PVRTC/fast_conversion",false); set("PVRTC/fast_conversion",false);

View File

@ -909,7 +909,14 @@ void CustomPropertyEditor::_action_pressed(int p_which) {
Vector<String> extensions=hint_text.split(","); Vector<String> extensions=hint_text.split(",");
for(int i=0;i<extensions.size();i++) { for(int i=0;i<extensions.size();i++) {
file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper() ); String filter = extensions[i];
if (filter.begins_with("."))
filter="*"+extensions[i];
else if (!filter.begins_with("*"))
filter="*."+extensions[i];
file->add_filter(filter+" ; "+extensions[i].to_upper() );
} }
} }