diff --git a/SConstruct b/SConstruct index a1a3238305..9cd1da7f45 100644 --- a/SConstruct +++ b/SConstruct @@ -54,13 +54,16 @@ methods.save_active_platforms(active_platforms,active_platform_ids) custom_tools=['default'] +platform_arg = ARGUMENTS.get("platform", False) + if (os.name=="posix"): pass elif (os.name=="nt"): - if (os.getenv("VSINSTALLDIR")==None): - custom_tools=['mingw'] + if (os.getenv("VSINSTALLDIR")==None or platform_arg=="android"): + custom_tools=['mingw'] env_base=Environment(tools=custom_tools,ENV = {'PATH' : os.environ['PATH']}); + #env_base=Environment(tools=custom_tools); env_base.global_defaults=global_defaults env_base.android_source_modules=[] @@ -363,8 +366,8 @@ if selected_platform in platform_list: #env['MSVS_VERSION']='9.0' env['MSVSBUILDCOM'] = "scons platform=" + selected_platform + " target=" + env["target"] + " bits=" + env["bits"] + " tools=yes" - env['MSVSREBUILDCOM'] = "scons platform=" + selected_platform + " target=" + env["target"] + " bits=" + env["bits"] + " tools=yes" - env['MSVSCLEANCOM'] = "scons platform=" + selected_platform + " target=" + env["target"] + " bits=" + env["bits"] + " tools=yes" + env['MSVSREBUILDCOM'] = "scons platform=" + selected_platform + " target=" + env["target"] + " bits=" + env["bits"] + " tools=yes vsproj=true" + env['MSVSCLEANCOM'] = "scons --clean platform=" + selected_platform + " target=" + env["target"] + " bits=" + env["bits"] + " tools=yes" debug_variants = ['Debug|Win32']+['Debug|x64'] release_variants = ['Release|Win32']+['Release|x64'] diff --git a/bin/tests/test_string.cpp b/bin/tests/test_string.cpp index 3c8d0f7d86..93b1835b78 100644 --- a/bin/tests/test_string.cpp +++ b/bin/tests/test_string.cpp @@ -31,7 +31,7 @@ //#include "math_funcs.h" #include #include "os/os.h" -#include "drivers/trex/regex.h" +#include "drivers/nrex/regex.h" #include "test_string.h" @@ -463,20 +463,16 @@ bool test_26() { OS::get_singleton()->print("\n\nTest 26: RegEx\n"); RegEx regexp("(.*):(.*)"); - List captures; - bool match = regexp.match("name:password", &captures); - printf("\tmatch: %s\n", match?"true":"false"); + int res = regexp.find("name:password"); + printf("\tmatch: %s\n", (res>=0)?"true":"false"); - printf("\t%i captures:\n", captures.size()); - List::Element *I = captures.front(); - while (I) { - - printf("%ls\n", I->get().c_str()); - - I = I->next(); - }; - return captures.size(); + printf("\t%i captures:\n", regexp.get_capture_count()); + for (int i = 0; iget_unix_time(); }; +uint64_t _OS::get_system_time_msec() const { + return OS::get_singleton()->get_system_time_msec(); +} + void _OS::delay_usec(uint32_t p_usec) const { OS::get_singleton()->delay_usec(p_usec); @@ -694,6 +698,17 @@ bool _OS::is_debug_build() const { } +void _OS::set_screen_orientation(ScreenOrientation p_orientation) { + + OS::get_singleton()->set_screen_orientation(OS::ScreenOrientation(p_orientation)); +} + +_OS::ScreenOrientation _OS::get_screen_orientation() const { + + return ScreenOrientation(OS::get_singleton()->get_screen_orientation()); +} + + String _OS::get_system_dir(SystemDir p_dir) const { return OS::get_singleton()->get_system_dir(OS::SystemDir(p_dir)); @@ -752,6 +767,9 @@ void _OS::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_window_maximized", "enabled"),&_OS::set_window_maximized); ObjectTypeDB::bind_method(_MD("is_window_maximized"),&_OS::is_window_maximized); + ObjectTypeDB::bind_method(_MD("set_screen_orientation","orientation"),&_OS::set_screen_orientation); + ObjectTypeDB::bind_method(_MD("get_screen_orientation"),&_OS::get_screen_orientation); + ObjectTypeDB::bind_method(_MD("set_iterations_per_second","iterations_per_second"),&_OS::set_iterations_per_second); ObjectTypeDB::bind_method(_MD("get_iterations_per_second"),&_OS::get_iterations_per_second); @@ -787,6 +805,7 @@ void _OS::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_time","utc"),&_OS::get_time,DEFVAL(false)); ObjectTypeDB::bind_method(_MD("get_time_zone_info"),&_OS::get_time_zone_info); ObjectTypeDB::bind_method(_MD("get_unix_time"),&_OS::get_unix_time); + ObjectTypeDB::bind_method(_MD("get_system_time_msec"), &_OS::get_system_time_msec); ObjectTypeDB::bind_method(_MD("set_icon"),&_OS::set_icon); @@ -863,6 +882,14 @@ void _OS::_bind_methods() { BIND_CONSTANT( MONTH_NOVEMBER ); BIND_CONSTANT( MONTH_DECEMBER ); + BIND_CONSTANT( SCREEN_ORIENTATION_LANDSCAPE ); + BIND_CONSTANT( SCREEN_ORIENTATION_PORTRAIT ); + BIND_CONSTANT( SCREEN_ORIENTATION_REVERSE_LANDSCAPE ); + BIND_CONSTANT( SCREEN_ORIENTATION_REVERSE_PORTRAIT ); + BIND_CONSTANT( SCREEN_ORIENTATION_SENSOR_LANDSCAPE ); + BIND_CONSTANT( SCREEN_ORIENTATION_SENSOR_PORTRAIT ); + BIND_CONSTANT( SCREEN_ORIENTATION_SENSOR ); + BIND_CONSTANT( SYSTEM_DIR_DESKTOP); BIND_CONSTANT( SYSTEM_DIR_DCIM ); BIND_CONSTANT( SYSTEM_DIR_DOCUMENTS ); @@ -1678,12 +1705,89 @@ Variant _Marshalls::base64_to_variant(const String& p_str) { return v; }; +String _Marshalls::raw_to_base64(const DVector &p_arr) { + + int len = p_arr.size(); + DVector::Read r = p_arr.read(); + + int b64len = len / 3 * 4 + 4 + 1; + DVector b64buff; + b64buff.resize(b64len); + DVector::Write w64 = b64buff.write(); + + int strlen = base64_encode((char*)(&w64[0]), (char*)(&r[0]), len); + w64[strlen] = 0; + String ret = (char*)&w64[0]; + + return ret; +}; + +DVector _Marshalls::base64_to_raw(const String &p_str) { + + int strlen = p_str.length(); + CharString cstr = p_str.ascii(); + + int arr_len; + DVector buf; + { + buf.resize(strlen / 4 * 3 + 1); + DVector::Write w = buf.write(); + + arr_len = base64_decode((char*)(&w[0]), (char*)cstr.get_data(), strlen); + }; + buf.resize(arr_len); + + // conversion from DVector to raw array? + return buf; +}; + +String _Marshalls::utf8_to_base64(const String& p_str) { + + CharString cstr = p_str.utf8(); + int len = cstr.length(); + + int b64len = len / 3 * 4 + 4 + 1; + DVector b64buff; + b64buff.resize(b64len); + DVector::Write w64 = b64buff.write(); + + int strlen = base64_encode((char*)(&w64[0]), (char*)cstr.get_data(), len); + + w64[strlen] = 0; + String ret = (char*)&w64[0]; + + return ret; +}; + +String _Marshalls::base64_to_utf8(const String& p_str) { + + int strlen = p_str.length(); + CharString cstr = p_str.ascii(); + + DVector buf; + buf.resize(strlen / 4 * 3 + 1 + 1); + DVector::Write w = buf.write(); + + int len = base64_decode((char*)(&w[0]), (char*)cstr.get_data(), strlen); + + w[len] = 0; + String ret = String::utf8((char*)&w[0]); + + return ret; +}; + void _Marshalls::_bind_methods() { ObjectTypeDB::bind_method(_MD("variant_to_base64:String","variant"),&_Marshalls::variant_to_base64); ObjectTypeDB::bind_method(_MD("base64_to_variant:Variant","base64_str"),&_Marshalls::base64_to_variant); + ObjectTypeDB::bind_method(_MD("raw_to_base64:String","array"),&_Marshalls::raw_to_base64); + ObjectTypeDB::bind_method(_MD("base64_to_raw:RawArray","base64_str"),&_Marshalls::base64_to_raw); + + ObjectTypeDB::bind_method(_MD("utf8_to_base64:String","utf8_str"),&_Marshalls::utf8_to_base64); + ObjectTypeDB::bind_method(_MD("base64_to_utf8:String","base64_str"),&_Marshalls::base64_to_utf8); + }; @@ -1772,6 +1876,7 @@ void _Thread::_start_func(void *ud) { memdelete(tud); Variant::CallError ce; const Variant* arg[1]={&t->userdata}; + t->ret=t->target_instance->call(t->target_method,arg,1,ce); if (ce.error!=Variant::CallError::CALL_OK) { @@ -1796,6 +1901,7 @@ void _Thread::_start_func(void *ud) { default: {} } + ERR_EXPLAIN("Could not call function '"+t->target_method.operator String()+"'' starting thread ID: "+t->get_id()+" Reason: "+reason); ERR_FAIL(); } diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 74f29c23e8..ed3db29259 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -208,6 +208,7 @@ public: Dictionary get_time(bool utc) const; Dictionary get_time_zone_info() const; uint64_t get_unix_time() const; + uint64_t get_system_time_msec() const; int get_static_memory_usage() const; int get_static_memory_peak_usage() const; @@ -239,11 +240,25 @@ public: SYSTEM_DIR_RINGTONES, }; + enum ScreenOrientation { + + SCREEN_ORIENTATION_LANDSCAPE, + SCREEN_ORIENTATION_PORTRAIT, + SCREEN_ORIENTATION_REVERSE_LANDSCAPE, + SCREEN_ORIENTATION_REVERSE_PORTRAIT, + SCREEN_ORIENTATION_SENSOR_LANDSCAPE, + SCREEN_ORIENTATION_SENSOR_PORTRAIT, + SCREEN_ORIENTATION_SENSOR, + }; + String get_system_dir(SystemDir p_dir) const; String get_data_dir() const; + void set_screen_orientation(ScreenOrientation p_orientation); + ScreenOrientation get_screen_orientation() const; + void set_time_scale(float p_scale); float get_time_scale(); @@ -255,6 +270,7 @@ public: }; VARIANT_ENUM_CAST(_OS::SystemDir); +VARIANT_ENUM_CAST(_OS::ScreenOrientation); class _Geometry : public Object { @@ -436,6 +452,12 @@ public: String variant_to_base64(const Variant& p_var); Variant base64_to_variant(const String& p_str); + String raw_to_base64(const DVector& p_arr); + DVector base64_to_raw(const String& p_str); + + String utf8_to_base64(const String& p_str); + String base64_to_utf8(const String& p_str); + _Marshalls() {}; }; diff --git a/core/globals.cpp b/core/globals.cpp index 8a7d66b68a..731c5b7dff 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -1149,6 +1149,12 @@ Error Globals::_save_settings_text(const String& p_file,const Map& p_ignore_masks) { ERR_FAIL_COND_V(p_path=="",ERR_INVALID_PARAMETER); @@ -1321,7 +1327,7 @@ Vector Globals::get_optimizer_presets() const { if (!E->get().name.begins_with("optimizer_presets/")) continue; - names.push_back(E->get().name.get_slice("/",1)); + names.push_back(E->get().name.get_slicec('/',1)); } names.sort(); @@ -1361,6 +1367,9 @@ void Globals::_bind_methods() { ObjectTypeDB::bind_method(_MD("has_singleton"),&Globals::has_singleton); ObjectTypeDB::bind_method(_MD("get_singleton"),&Globals::get_singleton_object); ObjectTypeDB::bind_method(_MD("load_resource_pack"),&Globals::_load_resource_pack); + + ObjectTypeDB::bind_method(_MD("save_custom"),&Globals::_save_custom_bnd); + } Globals::Globals() { diff --git a/core/globals.h b/core/globals.h index f739bcfb90..2ec56966f6 100644 --- a/core/globals.h +++ b/core/globals.h @@ -86,6 +86,7 @@ protected: List singletons; + Error _save_custom_bnd(const String& p_file); bool _load_resource_pack(const String& p_pack); diff --git a/core/image.cpp b/core/image.cpp index 037018519e..c31fa47847 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -1016,10 +1016,10 @@ void Image::create( const char ** p_xpm ) { String line_str=line_ptr; line_str.replace("\t"," "); - size_width=line_str.get_slice(" ",0).to_int(); - size_height=line_str.get_slice(" ",1).to_int(); - colormap_size=line_str.get_slice(" ",2).to_int(); - pixelchars=line_str.get_slice(" ",3).to_int(); + size_width=line_str.get_slicec(' ',0).to_int(); + size_height=line_str.get_slicec(' ',1).to_int(); + colormap_size=line_str.get_slicec(' ',2).to_int(); + pixelchars=line_str.get_slicec(' ',3).to_int(); ERR_FAIL_COND(colormap_size > 32766); ERR_FAIL_COND(pixelchars > 5); ERR_FAIL_COND(size_width > 32767); diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index 29f27dcbda..65b1ca5207 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -5,10 +5,12 @@ #include "print_string.h" #define COMP_MAGIC 0x43454447 +#include "core/variant.h" +#include Error FileAccessEncrypted::open_and_parse(FileAccess *p_base,const Vector& p_key,Mode p_mode) { - print_line("open and parse!"); + //print_line("open and parse!"); ERR_FAIL_COND_V(file!=NULL,ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(p_key.size()!=32,ERR_INVALID_PARAMETER); diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index dbd009e319..24012660d2 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -325,7 +325,7 @@ Error HTTPClient::poll(){ if (i==0 && responses[i].begins_with("HTTP")) { - String num = responses[i].get_slice(" ",1); + String num = responses[i].get_slicec(' ',1); response_num=num.to_int(); } else { diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index c5506f1a74..ed5a45c9ef 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -47,7 +47,7 @@ IP_Address::IP_Address(const String& p_string) { } for(int i=0;i<4;i++) { - field[i]=p_string.get_slice(".",i).to_int(); + field[i]=p_string.get_slicec('.',i).to_int(); } } diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 0f6f8a74b1..c6cf631de6 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -1819,7 +1819,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_ Property p; p.name_idx=get_string_index(F->get().name); p.value=E->get()->get(F->get().name); - if (F->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO && p.value.is_zero()) + if ((F->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO && p.value.is_zero())||(F->get().usage&PROPERTY_USAGE_STORE_IF_NONONE && p.value.is_one()) ) continue; p.pi=F->get(); diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp index 36746a4111..b744cbf967 100644 --- a/core/io/resource_format_xml.cpp +++ b/core/io/resource_format_xml.cpp @@ -1207,47 +1207,47 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) r_v=Vector3( - data.get_slice(",",0).to_double(), - data.get_slice(",",1).to_double(), - data.get_slice(",",2).to_double() + data.get_slicec(',',0).to_double(), + data.get_slicec(',',1).to_double(), + data.get_slicec(',',2).to_double() ); } else if (type=="vector2") { r_v=Vector2( - data.get_slice(",",0).to_double(), - data.get_slice(",",1).to_double() + data.get_slicec(',',0).to_double(), + data.get_slicec(',',1).to_double() ); } else if (type=="plane") { r_v=Plane( - data.get_slice(",",0).to_double(), - data.get_slice(",",1).to_double(), - data.get_slice(",",2).to_double(), - data.get_slice(",",3).to_double() + data.get_slicec(',',0).to_double(), + data.get_slicec(',',1).to_double(), + data.get_slicec(',',2).to_double(), + data.get_slicec(',',3).to_double() ); } else if (type=="quaternion") { r_v=Quat( - data.get_slice(",",0).to_double(), - data.get_slice(",",1).to_double(), - data.get_slice(",",2).to_double(), - data.get_slice(",",3).to_double() + data.get_slicec(',',0).to_double(), + data.get_slicec(',',1).to_double(), + data.get_slicec(',',2).to_double(), + data.get_slicec(',',3).to_double() ); } else if (type=="rect2") { r_v=Rect2( Vector2( - data.get_slice(",",0).to_double(), - data.get_slice(",",1).to_double() + data.get_slicec(',',0).to_double(), + data.get_slicec(',',1).to_double() ), Vector2( - data.get_slice(",",2).to_double(), - data.get_slice(",",3).to_double() + data.get_slicec(',',2).to_double(), + data.get_slicec(',',3).to_double() ) ); @@ -1256,14 +1256,14 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) r_v=AABB( Vector3( - data.get_slice(",",0).to_double(), - data.get_slice(",",1).to_double(), - data.get_slice(",",2).to_double() + data.get_slicec(',',0).to_double(), + data.get_slicec(',',1).to_double(), + data.get_slicec(',',2).to_double() ), Vector3( - data.get_slice(",",3).to_double(), - data.get_slice(",",4).to_double(), - data.get_slice(",",5).to_double() + data.get_slicec(',',3).to_double(), + data.get_slicec(',',4).to_double(), + data.get_slicec(',',5).to_double() ) ); @@ -1272,7 +1272,7 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) Matrix32 m3; for (int i=0;i<3;i++) { for (int j=0;j<2;j++) { - m3.elements[i][j]=data.get_slice(",",i*2+j).to_double(); + m3.elements[i][j]=data.get_slicec(',',i*2+j).to_double(); } } r_v=m3; @@ -1282,7 +1282,7 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) Matrix3 m3; for (int i=0;i<3;i++) { for (int j=0;j<3;j++) { - m3.elements[i][j]=data.get_slice(",",i*3+j).to_double(); + m3.elements[i][j]=data.get_slicec(',',i*3+j).to_double(); } } r_v=m3; @@ -1292,24 +1292,24 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) Transform tr; for (int i=0;i<3;i++) { for (int j=0;j<3;j++) { - tr.basis.elements[i][j]=data.get_slice(",",i*3+j).to_double(); + tr.basis.elements[i][j]=data.get_slicec(',',i*3+j).to_double(); } } tr.origin=Vector3( - data.get_slice(",",9).to_double(), - data.get_slice(",",10).to_double(), - data.get_slice(",",11).to_double() + data.get_slicec(',',9).to_double(), + data.get_slicec(',',10).to_double(), + data.get_slicec(',',11).to_double() ); r_v=tr; } else if (type=="color") { r_v=Color( - data.get_slice(",",0).to_double(), - data.get_slice(",",1).to_double(), - data.get_slice(",",2).to_double(), - data.get_slice(",",3).to_double() + data.get_slicec(',',0).to_double(), + data.get_slicec(',',1).to_double(), + data.get_slicec(',',2).to_double(), + data.get_slicec(',',3).to_double() ); } else if (type=="node_path") { @@ -1674,8 +1674,8 @@ void ResourceInteractiveLoaderXML::open(FileAccess *p_f) { ERR_FAIL(); } - int major = version.get_slice(".",0).to_int(); - int minor = version.get_slice(".",1).to_int(); + int major = version.get_slicec('.',0).to_int(); + int minor = version.get_slicec('.',1).to_int(); if (major>VERSION_MAJOR) { @@ -2607,9 +2607,12 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res String name = PE->get().name; Variant value = res->get(name); - if (PE->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero()) + + + if ((PE->get().usage&PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero())||(PE->get().usage&PROPERTY_USAGE_STORE_IF_NONONE && value.is_one()) ) continue; + write_property(name,value); } diff --git a/core/method_bind.cpp b/core/method_bind.cpp index 3429e5f0af..ce57380434 100644 --- a/core/method_bind.cpp +++ b/core/method_bind.cpp @@ -40,8 +40,8 @@ PropertyInfo MethodBind::get_argument_info(int p_argument) const { PropertyInfo pi( get_argument_type(p_argument), name ); if ((pi.type==Variant::OBJECT) && name.find(":")!=-1) { pi.hint=PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string=name.get_slice(":",1); - pi.name=name.get_slice(":",0); + pi.hint_string=name.get_slicec(':',1); + pi.name=name.get_slicec(':',0); } return pi; diff --git a/core/object.cpp b/core/object.cpp index 6bb7973cef..07ac430d7a 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -258,12 +258,15 @@ bool Object::_predelete() { _predelete_ok=1; notification(NOTIFICATION_PREDELETE,true); + if (_predelete_ok) { + _type_ptr=NULL; //must restore so destructors can access type ptr correctly + } return _predelete_ok; } void Object::_postinitialize() { - + _type_ptr=_get_type_namev(); _initialize_typev(); notification(NOTIFICATION_POSTINITIALIZE); @@ -1707,7 +1710,7 @@ bool Object::is_edited() const { Object::Object() { - + _type_ptr=NULL; _block_signals=false; _predelete_ok=0; _instance_ID=0; diff --git a/core/object.h b/core/object.h index 9680af924a..eb0e78a8c3 100644 --- a/core/object.h +++ b/core/object.h @@ -82,7 +82,8 @@ enum PropertyUsageFlags { PROPERTY_USAGE_BUNDLE=128, //used for optimized bundles PROPERTY_USAGE_CATEGORY=256, PROPERTY_USAGE_STORE_IF_NONZERO=512, //only store if nonzero - PROPERTY_USAGE_NO_INSTANCE_STATE=1024, + PROPERTY_USAGE_STORE_IF_NONONE=1024, //only store if false + PROPERTY_USAGE_NO_INSTANCE_STATE=2048, PROPERTY_USAGE_DEFAULT=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK, PROPERTY_USAGE_DEFAULT_INTL=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK|PROPERTY_USAGE_INTERNATIONALIZED, @@ -97,6 +98,8 @@ enum PropertyUsageFlags { #define ADD_PROPERTYI( m_property, m_setter, m_getter, m_index ) ObjectTypeDB::add_property( get_type_static(), m_property, m_setter, m_getter, m_index ) #define ADD_PROPERTYNZ( m_property, m_setter, m_getter ) ObjectTypeDB::add_property( get_type_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONZERO), m_setter, m_getter ) #define ADD_PROPERTYINZ( m_property, m_setter, m_getter, m_index ) ObjectTypeDB::add_property( get_type_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONZERO), m_setter, m_getter, m_index ) +#define ADD_PROPERTYNO( m_property, m_setter, m_getter ) ObjectTypeDB::add_property( get_type_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONONE), m_setter, m_getter ) +#define ADD_PROPERTYINO( m_property, m_setter, m_getter, m_index ) ObjectTypeDB::add_property( get_type_static(), (m_property).added_usage(PROPERTY_USAGE_STORE_IF_NONONE), m_setter, m_getter, m_index ) struct PropertyInfo { @@ -179,10 +182,10 @@ public:\ virtual String get_type() const { \ return String(#m_type);\ }\ -virtual StringName get_type_name() const { \ +virtual const StringName* _get_type_namev() const { \ if (!_type_name)\ _type_name=get_type_static();\ - return _type_name;\ + return &_type_name;\ }\ static _FORCE_INLINE_ void* get_type_ptr_static() { \ static int ptr;\ @@ -388,6 +391,8 @@ friend void postinitialize_handler(Object*); ScriptInstance *script_instance; RefPtr script; Dictionary metadata; + mutable StringName _type_name; + mutable const StringName* _type_ptr; void _add_user_signal(const String& p_name, const Array& p_pargs=Array()); bool _has_user_signal(const StringName& p_name) const; @@ -445,7 +450,11 @@ protected: Variant _call_deferred_bind(const Variant** p_args, int p_argcount, Variant::CallError& r_error); - + virtual const StringName* _get_type_namev() const { + if (!_type_name) + _type_name=get_type_static(); + return &_type_name; + } DVector _get_meta_list_bind() const; Array _get_property_list_bind() const; @@ -523,11 +532,19 @@ public: virtual String get_type() const { return "Object"; } virtual String get_save_type() const { return get_type(); } //type stored when saving - virtual StringName get_type_name() const { return StringName("Object"); } + + + virtual bool is_type(const String& p_type) const { return (p_type=="Object"); } virtual bool is_type_ptr(void *p_ptr) const { return get_type_ptr_static()==p_ptr; } - + _FORCE_INLINE_ const StringName& get_type_name() const { + if (!_type_ptr) { + return *_get_type_namev(); + } else { + return *_type_ptr; + } + } /* IAPI */ // void set(const String& p_name, const Variant& p_value); diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index a2cae50940..c291714573 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -205,7 +205,7 @@ ObjectTypeDB::TypeInfo::~TypeInfo() { } -bool ObjectTypeDB::is_type(const String &p_type,const String& p_inherits) { +bool ObjectTypeDB::is_type(const StringName &p_type,const StringName& p_inherits) { OBJTYPE_LOCK; @@ -220,7 +220,7 @@ bool ObjectTypeDB::is_type(const String &p_type,const String& p_inherits) { return false; } -void ObjectTypeDB::get_type_list( List *p_types) { +void ObjectTypeDB::get_type_list( List *p_types) { OBJTYPE_LOCK; @@ -235,7 +235,7 @@ void ObjectTypeDB::get_type_list( List *p_types) { } -void ObjectTypeDB::get_inheriters_from( const String& p_type,List *p_types) { +void ObjectTypeDB::get_inheriters_from( const StringName& p_type,List *p_types) { OBJTYPE_LOCK; @@ -249,7 +249,7 @@ void ObjectTypeDB::get_inheriters_from( const String& p_type,List *p_typ } -String ObjectTypeDB::type_inherits_from(const String& p_type) { +StringName ObjectTypeDB::type_inherits_from(const StringName& p_type) { OBJTYPE_LOCK; @@ -258,7 +258,7 @@ String ObjectTypeDB::type_inherits_from(const String& p_type) { return ti->inherits; } -bool ObjectTypeDB::type_exists(const String &p_type) { +bool ObjectTypeDB::type_exists(const StringName &p_type) { OBJTYPE_LOCK; return types.has(p_type); @@ -269,7 +269,7 @@ void ObjectTypeDB::add_compatibility_type(const StringName& p_type,const StringN compat_types[p_type]=p_fallback; } -Object *ObjectTypeDB::instance(const String &p_type) { +Object *ObjectTypeDB::instance(const StringName &p_type) { TypeInfo *ti; { @@ -287,7 +287,7 @@ Object *ObjectTypeDB::instance(const String &p_type) { return ti->creation_func(); } -bool ObjectTypeDB::can_instance(const String &p_type) { +bool ObjectTypeDB::can_instance(const StringName &p_type) { OBJTYPE_LOCK; @@ -650,7 +650,13 @@ bool ObjectTypeDB::set_property(Object* p_object,const StringName& p_property, c Variant index=psg->index; const Variant* arg[2]={&index,&p_value}; Variant::CallError ce; - p_object->call(psg->setter,arg,2,ce); +// p_object->call(psg->setter,arg,2,ce); + if (psg->_setptr) { + psg->_setptr->call(p_object,arg,2,ce); + } else { + p_object->call(psg->setter,arg,2,ce); + } + } else { const Variant* arg[1]={&p_value}; diff --git a/core/object_type_db.h b/core/object_type_db.h index 27c1506960..caa5baddd5 100644 --- a/core/object_type_db.h +++ b/core/object_type_db.h @@ -228,13 +228,13 @@ public: T::register_custom_data_to_otdb(); } - static void get_type_list( List *p_types); - static void get_inheriters_from( const String& p_type,List *p_types); - static String type_inherits_from(const String& p_type); - static bool type_exists(const String &p_type); - static bool is_type(const String &p_type,const String& p_inherits); - static bool can_instance(const String &p_type); - static Object *instance(const String &p_type); + static void get_type_list( List *p_types); + static void get_inheriters_from( const StringName& p_type,List *p_types); + static StringName type_inherits_from(const StringName& p_type); + static bool type_exists(const StringName &p_type); + static bool is_type(const StringName &p_type,const StringName& p_inherits); + static bool can_instance(const StringName &p_type); + static Object *instance(const StringName &p_type); #if 0 template diff --git a/core/os/os.cpp b/core/os/os.cpp index f292456079..efcd492230 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -50,7 +50,9 @@ uint64_t OS::get_unix_time() const { return 0; }; - +uint64_t OS::get_system_time_msec() const { + return 0; +} void OS::debug_break() { // something diff --git a/core/os/os.h b/core/os/os.h index 0230a75ca0..e8ecfa1054 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -254,6 +254,7 @@ public: virtual Time get_time(bool local=false) const=0; virtual TimeZoneInfo get_time_zone_info() const=0; virtual uint64_t get_unix_time() const; + virtual uint64_t get_system_time_msec() const; virtual void delay_usec(uint32_t p_usec) const=0; virtual uint64_t get_ticks_usec() const=0; diff --git a/core/print_string.cpp b/core/print_string.cpp index a06d4de237..42e018f303 100644 --- a/core/print_string.cpp +++ b/core/print_string.cpp @@ -32,6 +32,7 @@ static PrintHandlerList *print_handler_list=NULL; bool _print_line_enabled=true; +bool _print_error_enabled = true; void add_print_handler(PrintHandlerList *p_handler) { diff --git a/core/print_string.h b/core/print_string.h index 854f8ec2e5..4ea389b3a1 100644 --- a/core/print_string.h +++ b/core/print_string.h @@ -52,6 +52,7 @@ void add_print_handler(PrintHandlerList *p_handler); void remove_print_handler(PrintHandlerList *p_handler); extern bool _print_line_enabled; +extern bool _print_error_enabled; extern void print_line(String p_string); #endif diff --git a/core/script_debugger_local.cpp b/core/script_debugger_local.cpp index 2266b05f6d..649bbe89f0 100644 --- a/core/script_debugger_local.cpp +++ b/core/script_debugger_local.cpp @@ -60,7 +60,7 @@ void ScriptDebuggerLocal::debug(ScriptLanguage *p_script,bool p_can_continue) { if (line.get_slice_count(" ")==1) { print_line("*Frame "+itos(current_frame)+" - "+p_script->debug_get_stack_level_source(current_frame)+":"+itos(p_script->debug_get_stack_level_line(current_frame))+" in function '"+p_script->debug_get_stack_level_function(current_frame)+"'"); } else { - int frame = line.get_slice(" ",1).to_int(); + int frame = line.get_slicec(' ',1).to_int(); if (frame<0 || frame >=total_frames) { print_line("Error: Invalid frame."); } else { @@ -108,7 +108,7 @@ void ScriptDebuggerLocal::debug(ScriptLanguage *p_script,bool p_can_continue) { print_line("Usage: print "); } else { - String expr = line.get_slice(" ",2); + String expr = line.get_slicec(' ',2); String res = p_script->debug_parse_stack_level_expression(current_frame,expr); print_line(res); } @@ -130,9 +130,9 @@ void ScriptDebuggerLocal::debug(ScriptLanguage *p_script,bool p_can_continue) { } else { - String bppos=line.get_slice(" ",1); - String source=bppos.get_slice(":",0).strip_edges(); - int line=bppos.get_slice(":",1).strip_edges().to_int(); + String bppos=line.get_slicec(' ',1); + String source=bppos.get_slicec(':',0).strip_edges(); + int line=bppos.get_slicec(':',1).strip_edges().to_int(); source = breakpoint_find_source(source); @@ -147,9 +147,9 @@ void ScriptDebuggerLocal::debug(ScriptLanguage *p_script,bool p_can_continue) { clear_breakpoints(); } else { - String bppos=line.get_slice(" ",1); - String source=bppos.get_slice(":",0).strip_edges(); - int line=bppos.get_slice(":",1).strip_edges().to_int(); + String bppos=line.get_slicec(' ',1); + String source=bppos.get_slicec(':',0).strip_edges(); + int line=bppos.get_slicec(':',1).strip_edges().to_int(); source = breakpoint_find_source(source); diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index 33e9dc0fd9..d42f879441 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -34,7 +34,11 @@ Error ScriptDebuggerRemote::connect_to_host(const String& p_host,uint16_t p_port) { - IP_Address ip = IP::get_singleton()->resolve_hostname(p_host); + IP_Address ip; + if (p_host.is_valid_ip_address()) + ip=p_host; + else + ip = IP::get_singleton()->resolve_hostname(p_host); int port = p_port; @@ -127,7 +131,7 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { ERR_CONTINUE( cmd[0].get_type()!=Variant::STRING ); String command = cmd[0]; - cmd.remove(0); + if (command=="get_stack_dump") { @@ -150,7 +154,7 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { } else if (command=="get_stack_frame_vars") { - + cmd.remove(0); ERR_CONTINUE( cmd.size()!=1 ); int lv = cmd[0]; @@ -243,6 +247,17 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { if (request_scene_tree) request_scene_tree(request_scene_tree_ud); + + } else if (command=="breakpoint") { + + bool set = cmd[3]; + if (set) + insert_breakpoint(cmd[2],cmd[1]); + else + remove_breakpoint(cmd[2],cmd[1]); + + } else { + _parse_live_edit(cmd); } @@ -287,6 +302,37 @@ void ScriptDebuggerRemote::_get_output() { messages.pop_front(); locking=false; } + + while (errors.size()) { + locking=true; + packet_peer_stream->put_var("error"); + OutputError oe = errors.front()->get(); + + packet_peer_stream->put_var(oe.callstack.size()+2); + + Array error_data; + + error_data.push_back(oe.hr); + error_data.push_back(oe.min); + error_data.push_back(oe.sec); + error_data.push_back(oe.msec); + error_data.push_back(oe.source_func); + error_data.push_back(oe.source_file); + error_data.push_back(oe.source_line); + error_data.push_back(oe.error); + error_data.push_back(oe.error_descr); + error_data.push_back(oe.warning); + packet_peer_stream->put_var(error_data); + packet_peer_stream->put_var(oe.callstack.size()); + for(int i=0;iput_var(oe.callstack[i]); + + } + + errors.pop_front(); + locking=false; + + } mutex->unlock(); } @@ -301,6 +347,160 @@ void ScriptDebuggerRemote::line_poll() { } +void ScriptDebuggerRemote::_err_handler(void* ud,const char* p_func,const char*p_file,int p_line,const char *p_err, const char * p_descr,ErrorHandlerType p_type) { + + if (p_type==ERR_HANDLER_SCRIPT) + return; //ignore script errors, those go through debugger + + ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote*)ud; + + OutputError oe; + oe.error=p_err; + oe.error_descr=p_descr; + oe.source_file=p_file; + oe.source_line=p_line; + oe.source_func=p_func; + oe.warning=p_type==ERR_HANDLER_WARNING; + uint64_t time = OS::get_singleton()->get_ticks_msec(); + oe.hr=time/3600000; + oe.min=(time/60000)%60; + oe.sec=(time/1000)%60; + oe.msec=time%1000; + Array cstack; + + Vector si; + + for(int i=0;idebug_get_current_stack_info(); + if (si.size()) + break; + } + + cstack.resize(si.size()*2); + for(int i=0;iget_path(); + line=si[i].line; + } + cstack[i*2+0]=path; + cstack[i*2+1]=line; + } + + oe.callstack=cstack; + + + sdr->mutex->lock(); + + if (!sdr->locking && sdr->tcp_client->is_connected()) { + + sdr->errors.push_back(oe); + } + + sdr->mutex->unlock(); +} + + +bool ScriptDebuggerRemote::_parse_live_edit(const Array& cmd) { + + String cmdstr = cmd[0]; + if (!live_edit_funcs || !cmdstr.begins_with("live_")) + return false; + + + //print_line(Variant(cmd).get_construct_string()); + if (cmdstr=="live_set_root") { + + if (!live_edit_funcs->root_func) + return true; + //print_line("root: "+Variant(cmd).get_construct_string()); + live_edit_funcs->root_func(live_edit_funcs->udata,cmd[1],cmd[2]); + + } else if (cmdstr=="live_node_path") { + + if (!live_edit_funcs->node_path_func) + return true; + //print_line("path: "+Variant(cmd).get_construct_string()); + + live_edit_funcs->node_path_func(live_edit_funcs->udata,cmd[1],cmd[2]); + + } else if (cmdstr=="live_res_path") { + + if (!live_edit_funcs->res_path_func) + return true; + live_edit_funcs->res_path_func(live_edit_funcs->udata,cmd[1],cmd[2]); + + } else if (cmdstr=="live_node_prop_res") { + if (!live_edit_funcs->node_set_res_func) + return true; + + live_edit_funcs->node_set_res_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_node_prop") { + + if (!live_edit_funcs->node_set_func) + return true; + live_edit_funcs->node_set_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_res_prop_res") { + + if (!live_edit_funcs->res_set_res_func) + return true; + live_edit_funcs->res_set_res_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_res_prop") { + + if (!live_edit_funcs->res_set_func) + return true; + live_edit_funcs->res_set_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_node_call") { + + if (!live_edit_funcs->node_call_func) + return true; + live_edit_funcs->node_call_func(live_edit_funcs->udata,cmd[1],cmd[2], cmd[3],cmd[4],cmd[5],cmd[6],cmd[7]); + + } else if (cmdstr=="live_res_call") { + + if (!live_edit_funcs->res_call_func) + return true; + live_edit_funcs->res_call_func(live_edit_funcs->udata,cmd[1],cmd[2], cmd[3],cmd[4],cmd[5],cmd[6],cmd[7]); + + } else if (cmdstr=="live_create_node") { + + live_edit_funcs->tree_create_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_instance_node") { + + live_edit_funcs->tree_instance_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_remove_node") { + + live_edit_funcs->tree_remove_node_func(live_edit_funcs->udata,cmd[1]); + + } else if (cmdstr=="live_remove_and_keep_node") { + + live_edit_funcs->tree_remove_and_keep_node_func(live_edit_funcs->udata,cmd[1],cmd[2]); + } else if (cmdstr=="live_restore_node") { + + live_edit_funcs->tree_restore_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3]); + + } else if (cmdstr=="live_duplicate_node") { + + live_edit_funcs->tree_duplicate_node_func(live_edit_funcs->udata,cmd[1],cmd[2]); + } else if (cmdstr=="live_reparent_node") { + + live_edit_funcs->tree_reparent_node_func(live_edit_funcs->udata,cmd[1],cmd[2],cmd[3],cmd[4]); + + } else { + + return false; + } + + return true; +} + void ScriptDebuggerRemote::_poll_events() { while(packet_peer_stream->get_available_packet_count()>0) { @@ -321,7 +521,7 @@ void ScriptDebuggerRemote::_poll_events() { ERR_CONTINUE( cmd[0].get_type()!=Variant::STRING ); String command = cmd[0]; - cmd.remove(0); + //cmd.remove(0); if (command=="break") { @@ -331,6 +531,15 @@ void ScriptDebuggerRemote::_poll_events() { if (request_scene_tree) request_scene_tree(request_scene_tree_ud); + } else if (command=="breakpoint") { + + bool set = cmd[3]; + if (set) + insert_breakpoint(cmd[2],cmd[1]); + else + remove_breakpoint(cmd[2],cmd[1]); + } else { + _parse_live_edit(cmd); } } @@ -394,10 +603,35 @@ void ScriptDebuggerRemote::_print_handler(void *p_this,const String& p_string) { ScriptDebuggerRemote *sdr = (ScriptDebuggerRemote*)p_this; + uint64_t ticks = OS::get_singleton()->get_ticks_usec()/1000; + sdr->msec_count+=ticks-sdr->last_msec; + sdr->last_msec=ticks; + + if (sdr->msec_count>1000) { + sdr->char_count=0; + sdr->msec_count=0; + } + + String s = p_string; + int allowed_chars = MIN(MAX(sdr->max_cps - sdr->char_count,0), s.length()); + + if (allowed_chars==0) + return; + + if (allowed_charschar_count+=allowed_chars; + + if (sdr->char_count>=sdr->max_cps) { + s+="\n[output overflow, print less text!]\n"; + } + sdr->mutex->lock(); if (!sdr->locking && sdr->tcp_client->is_connected()) { - sdr->output_strings .push_back(p_string); + sdr->output_strings.push_back(s); } sdr->mutex->unlock(); } @@ -413,6 +647,11 @@ void ScriptDebuggerRemote::set_request_scene_tree_message_func(RequestSceneTreeM request_scene_tree_ud=p_udata; } +void ScriptDebuggerRemote::set_live_edit_funcs(LiveEditFuncs *p_funcs) { + + live_edit_funcs=p_funcs; +} + ScriptDebuggerRemote::ScriptDebuggerRemote() { tcp_client = StreamPeerTCP::create_ref(); @@ -429,13 +668,22 @@ ScriptDebuggerRemote::ScriptDebuggerRemote() { last_perf_time=0; poll_every=0; request_scene_tree=NULL; + live_edit_funcs=NULL; + max_cps = GLOBAL_DEF("debug/max_remote_stdout_chars_per_second",2048); + char_count=0; + msec_count=0; + last_msec=0; + + eh.errfunc=_err_handler; + eh.userdata=this; + add_error_handler(&eh); } ScriptDebuggerRemote::~ScriptDebuggerRemote() { remove_print_handler(&phl); + remove_error_handler(&eh); memdelete(mutex); - } diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h index 89b9947c4b..c2642782a9 100644 --- a/core/script_debugger_remote.h +++ b/core/script_debugger_remote.h @@ -49,8 +49,31 @@ class ScriptDebuggerRemote : public ScriptDebugger { Object *performance; bool requested_quit; Mutex *mutex; + + struct OutputError { + + int hr; + int min; + int sec; + int msec; + String source_file; + String source_func; + int source_line; + String error; + String error_descr; + bool warning; + Array callstack; + + }; + List output_strings; List messages; + List errors; + + int max_cps; + int char_count; + uint64_t last_msec; + uint64_t msec_count; bool locking; //hack to avoid a deadloop static void _print_handler(void *p_this,const String& p_string); @@ -62,9 +85,16 @@ class ScriptDebuggerRemote : public ScriptDebugger { uint32_t poll_every; + bool _parse_live_edit(const Array &p_command); + RequestSceneTreeMessageFunc request_scene_tree; void *request_scene_tree_ud; + LiveEditFuncs *live_edit_funcs; + + ErrorHandlerList eh; + static void _err_handler(void*,const char*,const char*,int p_line,const char *, const char *,ErrorHandlerType p_type); + public: @@ -79,6 +109,7 @@ public: virtual void send_message(const String& p_message, const Array& p_args); virtual void set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata); + virtual void set_live_edit_funcs(LiveEditFuncs *p_funcs); ScriptDebuggerRemote(); ~ScriptDebuggerRemote(); diff --git a/core/script_language.h b/core/script_language.h index 7104fe4547..5a0f673b94 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -176,6 +176,13 @@ public: virtual void debug_get_globals(List *p_locals, List *p_values, int p_max_subitems=-1,int p_max_depth=-1)=0; virtual String debug_parse_stack_level_expression(int p_level,const String& p_expression,int p_max_subitems=-1,int p_max_depth=-1)=0; + struct StackInfo { + Ref