diff options
Diffstat (limited to 'core')
37 files changed, 1005 insertions, 177 deletions
diff --git a/core/func_ref.cpp b/core/func_ref.cpp index 644d8b5b63..ca890111be 100644 --- a/core/func_ref.cpp +++ b/core/func_ref.cpp @@ -61,11 +61,7 @@ void FuncRef::_bind_methods() { MethodInfo mi; mi.name="call_func"; Vector<Variant> defargs; - for(int i=0;i<10;i++) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_func:Variant",&FuncRef::call_func,mi,defargs); + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_func:Variant",&FuncRef::call_func,mi,defargs); } diff --git a/core/globals.cpp b/core/globals.cpp index e760bc00d4..b822f52f15 100644 --- a/core/globals.cpp +++ b/core/globals.cpp @@ -1332,17 +1332,18 @@ Variant _GLOBAL_DEF( const String& p_var, const Variant& p_default) { void Globals::add_singleton(const Singleton &p_singleton) { singletons.push_back(p_singleton); + singleton_ptrs[p_singleton.name]=p_singleton.ptr; } Object* Globals::get_singleton_object(const String& p_name) const { - for(const List<Singleton>::Element *E=singletons.front();E;E=E->next()) { - if (E->get().name == p_name) { - return E->get().ptr; - }; - }; - return NULL; + const Map<StringName,Object*>::Element *E=singleton_ptrs.find(p_name); + if (!E) + return NULL; + else + return E->get(); + }; bool Globals::has_singleton(const String& p_name) const { @@ -1375,6 +1376,25 @@ Vector<String> Globals::get_optimizer_presets() const { } +void Globals::_add_property_info_bind(const Dictionary& p_info) { + + ERR_FAIL_COND(!p_info.has("name")); + ERR_FAIL_COND(!p_info.has("type")); + + PropertyInfo pinfo; + pinfo.name = p_info["name"]; + ERR_FAIL_COND(!props.has(pinfo.name)); + pinfo.type = Variant::Type(p_info["type"].operator int()); + ERR_FAIL_INDEX(pinfo.type, Variant::VARIANT_MAX); + + if (p_info.has("hint")) + pinfo.hint = PropertyHint(p_info["hint"].operator int()); + if (p_info.has("hint_string")) + pinfo.hint_string = p_info["hint_string"]; + + set_custom_property_info(pinfo.name, pinfo); +} + void Globals::set_custom_property_info(const String& p_prop,const PropertyInfo& p_info) { ERR_FAIL_COND(!props.has(p_prop)); @@ -1399,6 +1419,7 @@ void Globals::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_order","name"),&Globals::get_order); ObjectTypeDB::bind_method(_MD("set_persisting","name","enable"),&Globals::set_persisting); ObjectTypeDB::bind_method(_MD("is_persisting","name"),&Globals::is_persisting); + ObjectTypeDB::bind_method(_MD("add_property_info", "hint"),&Globals::_add_property_info_bind); ObjectTypeDB::bind_method(_MD("clear","name"),&Globals::clear); ObjectTypeDB::bind_method(_MD("localize_path","path"),&Globals::localize_path); ObjectTypeDB::bind_method(_MD("globalize_path","path"),&Globals::globalize_path); diff --git a/core/globals.h b/core/globals.h index 68bb859ace..5e0bdb0e54 100644 --- a/core/globals.h +++ b/core/globals.h @@ -91,11 +91,14 @@ protected: Error _save_settings_binary(const String& p_file,const Map<String,List<String> > &props,const CustomMap& p_custom=CustomMap()); List<Singleton> singletons; + Map<StringName,Object*> singleton_ptrs; Error _save_custom_bnd(const String& p_file); bool _load_resource_pack(const String& p_pack); + void _add_property_info_bind(const Dictionary& p_info); + protected: static void _bind_methods(); diff --git a/core/input_map.cpp b/core/input_map.cpp index 08ee8138a3..3a0f9596f5 100644 --- a/core/input_map.cpp +++ b/core/input_map.cpp @@ -290,6 +290,10 @@ bool InputMap::event_is_joy_motion_action_pressed(const InputEvent& p_event) con } +const Map<StringName, InputMap::Action>& InputMap::get_action_map() const { + return input_map; +} + void InputMap::load_from_globals() { input_map.clear();; diff --git a/core/input_map.h b/core/input_map.h index dc5a911963..a224765d8c 100644 --- a/core/input_map.h +++ b/core/input_map.h @@ -35,12 +35,14 @@ class InputMap : public Object { OBJ_TYPE( InputMap, Object ); - static InputMap *singleton; - +public: struct Action { int id; List<InputEvent> inputs; }; +private: + static InputMap *singleton; + mutable Map<StringName, Action> input_map; mutable Map<int,StringName> input_id_map; @@ -72,7 +74,7 @@ public: bool event_is_action(const InputEvent& p_event, const StringName& p_action) const; bool event_is_joy_motion_action_pressed(const InputEvent& p_event) const; - + const Map<StringName, Action>& get_action_map() const; void load_from_globals(); void load_default(); diff --git a/core/io/compression.cpp b/core/io/compression.cpp index a17e358cbb..ca44d24911 100644 --- a/core/io/compression.cpp +++ b/core/io/compression.cpp @@ -60,6 +60,10 @@ int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,M strm.avail_in=p_src_size; int aout = deflateBound(&strm,p_src_size);; + /*if (aout>p_src_size) { + deflateEnd(&strm); + return -1; + }*/ strm.avail_out=aout; strm.next_in=(Bytef*)p_src; strm.next_out=p_dst; @@ -107,19 +111,21 @@ int Compression::get_max_compressed_buffer_size(int p_src_size,Mode p_mode){ -void Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size,Mode p_mode){ +int Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size,Mode p_mode){ switch(p_mode) { case MODE_FASTLZ: { + int ret_size=0; + if (p_dst_max_size<16) { uint8_t dst[16]; - fastlz_decompress(p_src,p_src_size,dst,16); + ret_size = fastlz_decompress(p_src,p_src_size,dst,16); copymem(p_dst,dst,p_dst_max_size); } else { - fastlz_decompress(p_src,p_src_size,p_dst,p_dst_max_size); + ret_size = fastlz_decompress(p_src,p_src_size,p_dst,p_dst_max_size); } - return; + return ret_size; } break; case MODE_DEFLATE: { @@ -130,7 +136,7 @@ void Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t * strm.avail_in= 0; strm.next_in=Z_NULL; int err = inflateInit(&strm); - ERR_FAIL_COND(err!=Z_OK); + ERR_FAIL_COND_V(err!=Z_OK,-1); strm.avail_in=p_src_size; strm.avail_out=p_dst_max_size; @@ -138,11 +144,12 @@ void Compression::decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t * strm.next_out=p_dst; err = inflate(&strm,Z_FINISH); + int total = strm.total_out; inflateEnd(&strm); - ERR_FAIL_COND(err!=Z_STREAM_END); - return; + ERR_FAIL_COND_V(err!=Z_STREAM_END,-1); + return total; } break; } - ERR_FAIL(); + ERR_FAIL_V(-1); } diff --git a/core/io/compression.h b/core/io/compression.h index 07a293c940..e0a4d31a51 100644 --- a/core/io/compression.h +++ b/core/io/compression.h @@ -43,7 +43,7 @@ public: static int compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size,Mode p_mode=MODE_FASTLZ); static int get_max_compressed_buffer_size(int p_src_size,Mode p_mode=MODE_FASTLZ); - static void decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size,Mode p_mode=MODE_FASTLZ); + static int decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size,Mode p_mode=MODE_FASTLZ); Compression(); }; diff --git a/core/io/networked_multiplayer_peer.cpp b/core/io/networked_multiplayer_peer.cpp index 851064b6e8..47e5f3729c 100644 --- a/core/io/networked_multiplayer_peer.cpp +++ b/core/io/networked_multiplayer_peer.cpp @@ -5,25 +5,34 @@ void NetworkedMultiplayerPeer::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_transfer_mode","mode"), &NetworkedMultiplayerPeer::set_transfer_mode ); ObjectTypeDB::bind_method(_MD("set_target_peer","id"), &NetworkedMultiplayerPeer::set_target_peer ); - ObjectTypeDB::bind_method(_MD("set_channel","id"), &NetworkedMultiplayerPeer::set_channel ); ObjectTypeDB::bind_method(_MD("get_packet_peer"), &NetworkedMultiplayerPeer::get_packet_peer ); - ObjectTypeDB::bind_method(_MD("get_packet_channel"), &NetworkedMultiplayerPeer::get_packet_channel ); ObjectTypeDB::bind_method(_MD("poll"), &NetworkedMultiplayerPeer::poll ); ObjectTypeDB::bind_method(_MD("get_connection_status"), &NetworkedMultiplayerPeer::get_connection_status ); + ObjectTypeDB::bind_method(_MD("get_unique_id"), &NetworkedMultiplayerPeer::get_unique_id ); + + ObjectTypeDB::bind_method(_MD("set_refuse_new_connections","enable"), &NetworkedMultiplayerPeer::set_refuse_new_connections ); + ObjectTypeDB::bind_method(_MD("is_refusing_new_connections"), &NetworkedMultiplayerPeer::is_refusing_new_connections ); BIND_CONSTANT( TRANSFER_MODE_UNRELIABLE ); + BIND_CONSTANT( TRANSFER_MODE_UNRELIABLE_ORDERED ); BIND_CONSTANT( TRANSFER_MODE_RELIABLE ); - BIND_CONSTANT( TRANSFER_MODE_ORDERED ); BIND_CONSTANT( CONNECTION_DISCONNECTED ); BIND_CONSTANT( CONNECTION_CONNECTING ); BIND_CONSTANT( CONNECTION_CONNECTED ); - ADD_SIGNAL( MethodInfo("peer_connected",PropertyInfo(Variant::STRING,"id"))); - ADD_SIGNAL( MethodInfo("peer_disconnected",PropertyInfo(Variant::STRING,"id"))); + BIND_CONSTANT( TARGET_PEER_BROADCAST ); + BIND_CONSTANT( TARGET_PEER_SERVER ); + + + ADD_SIGNAL( MethodInfo("peer_connected",PropertyInfo(Variant::INT,"id"))); + ADD_SIGNAL( MethodInfo("peer_disconnected",PropertyInfo(Variant::INT,"id"))); + ADD_SIGNAL( MethodInfo("server_disconnected")); + ADD_SIGNAL( MethodInfo("connection_succeeded") ); + ADD_SIGNAL( MethodInfo("connection_failed") ); } NetworkedMultiplayerPeer::NetworkedMultiplayerPeer() { diff --git a/core/io/networked_multiplayer_peer.h b/core/io/networked_multiplayer_peer.h index 7071a52d7b..485200a9a9 100644 --- a/core/io/networked_multiplayer_peer.h +++ b/core/io/networked_multiplayer_peer.h @@ -11,10 +11,14 @@ protected: static void _bind_methods(); public: + enum { + TARGET_PEER_BROADCAST=0, + TARGET_PEER_SERVER=1 + }; enum TransferMode { TRANSFER_MODE_UNRELIABLE, + TRANSFER_MODE_UNRELIABLE_ORDERED, TRANSFER_MODE_RELIABLE, - TRANSFER_MODE_ORDERED }; enum ConnectionStatus { @@ -25,17 +29,20 @@ public: virtual void set_transfer_mode(TransferMode p_mode)=0; - virtual void set_target_peer(const StringName& p_peer_id)=0; - virtual void set_channel(int p_channel)=0; - + virtual void set_target_peer(int p_peer_id)=0; - virtual StringName get_packet_peer() const=0; - virtual int get_packet_channel() const=0; + virtual int get_packet_peer() const=0; virtual bool is_server() const=0; virtual void poll()=0; + virtual int get_unique_id() const=0; + + virtual void set_refuse_new_connections(bool p_enable)=0; + virtual bool is_refusing_new_connections() const=0; + + virtual ConnectionStatus get_connection_status() const=0; NetworkedMultiplayerPeer(); diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index a620dc0fef..0544fd6ba8 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -2175,6 +2175,9 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path,const RES& p_ if (takeover_paths) { r->set_path(p_path+"::"+itos(r->get_subindex()),true); } +#ifdef TOOLS_ENABLED + r->set_edited(false); +#endif } else { save_unicode_string(r->get_path()); //actual external } diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp index 0d545b16f5..44fbaf02ac 100644 --- a/core/io/resource_format_xml.cpp +++ b/core/io/resource_format_xml.cpp @@ -2800,6 +2800,10 @@ Error ResourceFormatSaverXMLInstance::save(const String &p_path,const RES& p_res if (takeover_paths) { res->set_path(p_path+"::"+itos(idx),true); } +#ifdef TOOLS_ENABLED + res->set_edited(false); +#endif + } write_string("\n",false); diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp index 306e7d8c9d..baaeacaf18 100644 --- a/core/io/stream_peer.cpp +++ b/core/io/stream_peer.cpp @@ -222,6 +222,7 @@ void StreamPeer::put_double(double p_val){ void StreamPeer::put_utf8_string(const String& p_string) { CharString cs=p_string.utf8(); + put_u32(p_string.length()); put_data((const uint8_t*)cs.get_data(),cs.length()); } @@ -348,8 +349,10 @@ String StreamPeer::get_string(int p_bytes){ ERR_FAIL_COND_V(p_bytes<0,String()); Vector<char> buf; - buf.resize(p_bytes+1); - get_data((uint8_t*)&buf[0],p_bytes); + Error err = buf.resize(p_bytes+1); + ERR_FAIL_COND_V(err!=OK,String()); + err = get_data((uint8_t*)&buf[0],p_bytes); + ERR_FAIL_COND_V(err!=OK,String()); buf[p_bytes]=0; return buf.ptr(); @@ -359,8 +362,10 @@ String StreamPeer::get_utf8_string(int p_bytes){ ERR_FAIL_COND_V(p_bytes<0,String()); Vector<uint8_t> buf; - buf.resize(p_bytes); - get_data(buf.ptr(),p_bytes); + Error err = buf.resize(p_bytes); + ERR_FAIL_COND_V(err!=OK,String()); + err = get_data(buf.ptr(),p_bytes); + ERR_FAIL_COND_V(err!=OK,String()); String ret; ret.parse_utf8((const char*)buf.ptr(),buf.size()); @@ -371,8 +376,10 @@ Variant StreamPeer::get_var(){ int len = get_32(); Vector<uint8_t> var; - var.resize(len); - get_data(var.ptr(),len); + Error err = var.resize(len); + ERR_FAIL_COND_V(err!=OK,Variant()); + err = get_data(var.ptr(),len); + ERR_FAIL_COND_V(err!=OK,Variant()); Variant ret; decode_variant(ret,var.ptr(),len); @@ -420,3 +427,128 @@ void StreamPeer::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_utf8_string","bytes"),&StreamPeer::get_utf8_string); ObjectTypeDB::bind_method(_MD("get_var:Variant"),&StreamPeer::get_var); } +//////////////////////////////// + + +void StreamPeerBuffer::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("seek","pos"),&StreamPeerBuffer::seek); + ObjectTypeDB::bind_method(_MD("get_size"),&StreamPeerBuffer::get_size); + ObjectTypeDB::bind_method(_MD("get_pos"),&StreamPeerBuffer::get_pos); + ObjectTypeDB::bind_method(_MD("resize","size"),&StreamPeerBuffer::resize); + ObjectTypeDB::bind_method(_MD("set_data_array","data"),&StreamPeerBuffer::set_data_array); + ObjectTypeDB::bind_method(_MD("get_data_array"),&StreamPeerBuffer::get_data_array); + ObjectTypeDB::bind_method(_MD("clear"),&StreamPeerBuffer::clear); + ObjectTypeDB::bind_method(_MD("duplicate:StreamPeerBuffer"),&StreamPeerBuffer::duplicate); + +} + + +Error StreamPeerBuffer::put_data(const uint8_t* p_data,int p_bytes) { + + if (p_bytes<=0) + return OK; + + if (pointer+p_bytes > data.size()) { + data.resize(pointer+p_bytes); + + } + + DVector<uint8_t>::Write w = data.write(); + copymem(&w[pointer],p_data,p_bytes); + + pointer+=p_bytes; + return OK; +} + +Error StreamPeerBuffer::put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent){ + + r_sent=p_bytes; + return put_data(p_data,p_bytes); +} + +Error StreamPeerBuffer::get_data(uint8_t* p_buffer, int p_bytes){ + + int recv; + get_partial_data(p_buffer,p_bytes,recv); + if (recv!=p_bytes) + return ERR_INVALID_PARAMETER; + + return OK; + +} +Error StreamPeerBuffer::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received){ + + + if (pointer+p_bytes > data.size()) { + r_received=data.size()-pointer; + if (r_received<=0) { + r_received=0; + return OK; //you got 0 + } + } else { + r_received=p_bytes; + } + + DVector<uint8_t>::Read r = data.read(); + copymem(p_buffer,r.ptr(),r_received); +} + +int StreamPeerBuffer::get_available_bytes() const { + + return data.size()-pointer; +} + +void StreamPeerBuffer::seek(int p_pos){ + + ERR_FAIL_COND(p_pos < 0); + ERR_FAIL_COND(p_pos > data.size()); + pointer=p_pos; +} +int StreamPeerBuffer::get_size() const{ + + return data.size(); +} + +int StreamPeerBuffer::get_pos() const { + + return pointer; +} + +void StreamPeerBuffer::resize(int p_size){ + + data.resize(p_size); +} + +void StreamPeerBuffer::set_data_array(const DVector<uint8_t> & p_data){ + + data=p_data; + pointer=0; +} + +DVector<uint8_t> StreamPeerBuffer::get_data_array() const{ + + return data; +} + + +void StreamPeerBuffer::clear() { + + data.resize(0); + pointer=0; +} + + +Ref<StreamPeerBuffer> StreamPeerBuffer::duplicate() const { + + Ref<StreamPeerBuffer> spb; + spb.instance(); + spb->data=data; + return spb; +} + + +StreamPeerBuffer::StreamPeerBuffer() { + + pointer=0; +} diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h index 970e6695a5..f28e6f594d 100644 --- a/core/io/stream_peer.h +++ b/core/io/stream_peer.h @@ -91,4 +91,40 @@ public: StreamPeer() { big_endian=false; } }; + +class StreamPeerBuffer : public StreamPeer { + + OBJ_TYPE(StreamPeerBuffer,StreamPeer); + + DVector<uint8_t> data; + int pointer; +protected: + + static void _bind_methods(); +public: + Error put_data(const uint8_t* p_data,int p_bytes); + Error put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent); + + Error get_data(uint8_t* p_buffer, int p_bytes); + Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received); + + virtual int get_available_bytes() const; + + void seek(int p_pos); + int get_size() const; + int get_pos() const; + void resize(int p_size); + + + void set_data_array(const DVector<uint8_t> & p_data); + DVector<uint8_t> get_data_array() const; + + void clear(); + + Ref<StreamPeerBuffer> duplicate() const; + + StreamPeerBuffer(); +}; + + #endif // STREAM_PEER_H diff --git a/core/math/math_2d.h b/core/math/math_2d.h index fbf700fb9c..90aae9fe50 100644 --- a/core/math/math_2d.h +++ b/core/math/math_2d.h @@ -618,6 +618,15 @@ struct Matrix32 { operator String() const; + Matrix32(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) { + + elements[0][0] = xx; + elements[0][1] = xy; + elements[1][0] = yx; + elements[1][1] = yy; + elements[2][0] = ox; + elements[2][1] = oy; + } Matrix32(real_t p_rot, const Vector2& p_pos); Matrix32() { elements[0][0]=1.0; elements[1][1]=1.0; } diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index 8afd73f482..b4a13d8f6d 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -65,13 +65,9 @@ int Vector3::max_axis() const { void Vector3::snap(float p_val) { - x+=p_val/2.0; - x-=Math::fmod(x,p_val); - y+=p_val/2.0; - y-=Math::fmod(y,p_val); - z+=p_val/2.0; - z-=Math::fmod(z,p_val); - + x=Math::stepify(x,p_val); + y=Math::stepify(y,p_val); + z=Math::stepify(z,p_val); } Vector3 Vector3::snapped(float p_val) const { diff --git a/core/method_bind.h b/core/method_bind.h index 072953743c..04ff5c22c6 100644 --- a/core/method_bind.h +++ b/core/method_bind.h @@ -52,6 +52,7 @@ enum MethodFlags { METHOD_FLAG_REVERSE=16, // used for events METHOD_FLAG_VIRTUAL=32, METHOD_FLAG_FROM_SCRIPT=64, + METHOD_FLAG_VARARG=128, METHOD_FLAGS_DEFAULT=METHOD_FLAG_NORMAL, }; @@ -229,7 +230,7 @@ public: Vector<StringName> get_argument_names() const; #endif void set_hint_flags(uint32_t p_hint) { hint_flags=p_hint; } - uint32_t get_hint_flags() const { return hint_flags|(is_const()?METHOD_FLAG_CONST:0); } + uint32_t get_hint_flags() const { return hint_flags|(is_const()?METHOD_FLAG_CONST:0)|(is_vararg()?METHOD_FLAG_VARARG:0); } virtual String get_instance_type() const=0; _FORCE_INLINE_ int get_argument_count() const { return argument_count; }; @@ -267,7 +268,7 @@ public: _FORCE_INLINE_ int get_method_id() const { return method_id; } _FORCE_INLINE_ bool is_const() const { return _const; } _FORCE_INLINE_ bool has_return() const { return _returns; } - + virtual bool is_vararg() const { return false; } void set_default_arguments(const Vector<Variant>& p_defargs); @@ -277,7 +278,7 @@ public: template<class T> -class MethodBindNative : public MethodBind { +class MethodBindVarArg : public MethodBind { public: typedef Variant (T::*NativeCall)(const Variant**,int ,Variant::CallError &); protected: @@ -319,7 +320,9 @@ public: } #ifdef PTRCALL_ENABLED - virtual void ptrcall(Object* p_object,const void** p_args,void* r_ret) {} //todo + virtual void ptrcall(Object* p_object,const void** p_args,void* r_ret) { + ERR_FAIL(); //can't call + } //todo #endif @@ -327,14 +330,16 @@ public: virtual bool is_const() const { return false; } virtual String get_instance_type() const { return T::get_type_static(); } - MethodBindNative() { call_method=NULL; _set_returns(true);} + virtual bool is_vararg() const { return true; } + + MethodBindVarArg() { call_method=NULL; _set_returns(true);} }; template<class T > -MethodBind* create_native_method_bind( Variant (T::*p_method)(const Variant**,int ,Variant::CallError &), const MethodInfo& p_info ) { +MethodBind* create_vararg_method_bind( Variant (T::*p_method)(const Variant**,int ,Variant::CallError &), const MethodInfo& p_info ) { - MethodBindNative<T > * a = memnew( (MethodBindNative<T >) ); + MethodBindVarArg<T > * a = memnew( (MethodBindVarArg<T >) ); a->set_method(p_method); a->set_method_info(p_info); return a; diff --git a/core/object.cpp b/core/object.cpp index 26319d42dd..81fdc2a90c 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -59,30 +59,112 @@ struct _ObjectDebugLock { #endif + +PropertyInfo::operator Dictionary() const { + + Dictionary d; + d["name"]=name; + d["type"]=type; + d["hint"]=hint; + d["hint_string"]=hint_string; + d["usage"]=usage; + return d; + +} + +PropertyInfo PropertyInfo::from_dict(const Dictionary& p_dict) { + + PropertyInfo pi; + + if (p_dict.has("type")) + pi.type=Variant::Type(int(p_dict["type"])); + + if (p_dict.has("name")) + pi.name=p_dict["name"]; + + if (p_dict.has("hint")) + pi.hint=PropertyHint(int(p_dict["hint"])); + + if (p_dict.has("hint_string")) + + pi.hint_string=p_dict["hint_string"]; + + if (p_dict.has("usage")) + pi.usage=p_dict["usage"]; + + return pi; +} + + Array convert_property_list(const List<PropertyInfo> * p_list) { Array va; for (const List<PropertyInfo>::Element *E=p_list->front();E;E=E->next()) { - const PropertyInfo &pi = E->get(); - Dictionary d; - d["name"]=pi.name; - d["type"]=pi.type; - d["hint"]=pi.hint; - d["hint_string"]=pi.hint_string; - d["usage"]=pi.usage; - va.push_back(d); + + va.push_back(Dictionary(E->get())); } return va; } +MethodInfo::operator Dictionary() const { + + + Dictionary d; + d["name"]=name; + d["args"]=convert_property_list(&arguments); + Array da; + for(int i=0;i<default_arguments.size();i++) + da.push_back(default_arguments[i]); + d["default_args"]=da; + d["flags"]=flags; + d["id"]=id; + Dictionary r = return_val; + d["return"]=r; + return d; + +} + MethodInfo::MethodInfo() { id=0; flags=METHOD_FLAG_NORMAL; } +MethodInfo MethodInfo::from_dict(const Dictionary& p_dict) { + + MethodInfo mi; + + if (p_dict.has("name")) + mi.name=p_dict["name"]; + Array args; + if (p_dict.has("args")) { + args=p_dict["args"]; + } + + for(int i=0;i<args.size();i++) { + Dictionary d = args[i]; + mi.arguments.push_back(PropertyInfo::from_dict(d)); + } + Array defargs; + if (p_dict.has("default_args")) { + defargs=p_dict["default_args"]; + } + for(int i=0;i<defargs.size();i++) { + mi.default_arguments.push_back(defargs[i]); + } + + if (p_dict.has("return")) { + mi.return_val=PropertyInfo::from_dict(p_dict["return"]); + } + + if (p_dict.has("flags")) + mi.flags=p_dict["flags"]; + + return mi; +} + MethodInfo::MethodInfo(const String& p_name) { id=0; @@ -1012,25 +1094,6 @@ Array Object::_get_property_list_bind() const { } -static Dictionary _get_dict_from_method(const MethodInfo &mi) { - - Dictionary d; - d["name"]=mi.name; - d["args"]=convert_property_list(&mi.arguments); - Array da; - for(int i=0;i<mi.default_arguments.size();i++) - da.push_back(mi.default_arguments[i]); - d["default_args"]=da; - d["flags"]=mi.flags; - d["id"]=mi.id; - Dictionary r; - r["type"]=mi.return_val.type; - r["hint"]=mi.return_val.hint; - r["hint_string"]=mi.return_val.hint_string; - d["return_type"]=r; - return d; - -} Array Object::_get_method_list_bind() const { @@ -1040,7 +1103,7 @@ Array Object::_get_method_list_bind() const { for(List<MethodInfo>::Element *E=ml.front();E;E=E->next()) { - Dictionary d = _get_dict_from_method(E->get()); + Dictionary d = E->get(); //va.push_back(d); ret.push_back(d); } @@ -1305,7 +1368,7 @@ Array Object::_get_signal_list() const{ Array ret; for (List<MethodInfo>::Element *E=signal_list.front();E;E=E->next()) { - ret.push_back(_get_dict_from_method(E->get())); + ret.push_back(Dictionary(E->get())); } return ret; @@ -1630,42 +1693,26 @@ void Object::_bind_methods() { MethodInfo mi; mi.name="emit_signal"; mi.arguments.push_back( PropertyInfo( Variant::STRING, "signal")); - Vector<Variant> defargs; - for(int i=0;i<VARIANT_ARG_MAX;i++) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"emit_signal",&Object::_emit_signal,mi,defargs); + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"emit_signal",&Object::_emit_signal,mi); } { MethodInfo mi; mi.name="call"; mi.arguments.push_back( PropertyInfo( Variant::STRING, "method")); - Vector<Variant> defargs; - for(int i=0;i<10;i++) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call:Variant",&Object::_call_bind,mi,defargs); + + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call:Variant",&Object::_call_bind,mi); } { MethodInfo mi; mi.name="call_deferred"; mi.arguments.push_back( PropertyInfo( Variant::STRING, "method")); - Vector<Variant> defargs; - for(int i=0;i<VARIANT_ARG_MAX;i++) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"call_deferred",&Object::_call_deferred_bind,mi,defargs); + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"call_deferred",&Object::_call_deferred_bind,mi); } ObjectTypeDB::bind_method(_MD("callv:Variant","method","arg_array"),&Object::callv); diff --git a/core/object.h b/core/object.h index 400ab3070e..ac3fc51b3e 100644 --- a/core/object.h +++ b/core/object.h @@ -70,6 +70,14 @@ enum PropertyHint { PROPERTY_HINT_OBJECT_ID, PROPERTY_HINT_TYPE_STRING, ///< a type string, the hint is the base type to choose PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE, ///< so something else can provide this (used in scripts) + PROPERTY_HINT_METHOD_OF_VARIANT_TYPE, ///< a method of a type + PROPERTY_HINT_METHOD_OF_BASE_TYPE, ///< a method of a base type + PROPERTY_HINT_METHOD_OF_INSTANCE, ///< a method of an instance + PROPERTY_HINT_METHOD_OF_SCRIPT, ///< a method of a script & base + PROPERTY_HINT_PROPERTY_OF_VARIANT_TYPE, ///< a property of a type + PROPERTY_HINT_PROPERTY_OF_BASE_TYPE, ///< a property of a base type + PROPERTY_HINT_PROPERTY_OF_INSTANCE, ///< a property of an instance + PROPERTY_HINT_PROPERTY_OF_SCRIPT, ///< a property of a script & base PROPERTY_HINT_MAX, }; @@ -118,6 +126,11 @@ struct PropertyInfo { _FORCE_INLINE_ PropertyInfo added_usage(int p_fl) const { PropertyInfo pi=*this; pi.usage|=p_fl; return pi; } + + operator Dictionary() const; + + static PropertyInfo from_dict(const Dictionary& p_dict); + PropertyInfo() { type=Variant::NIL; hint=PROPERTY_HINT_NONE; usage = PROPERTY_USAGE_DEFAULT; } PropertyInfo( Variant::Type p_type, const String p_name, PropertyHint p_hint=PROPERTY_HINT_NONE, const String& p_hint_string="",uint32_t p_usage=PROPERTY_USAGE_DEFAULT) { type=p_type; name=p_name; hint=p_hint; hint_string=p_hint_string; usage=p_usage; @@ -142,6 +155,9 @@ struct MethodInfo { inline bool operator<(const MethodInfo& p_method) const { return id==p_method.id?(name < p_method.name):(id<p_method.id); } + operator Dictionary() const; + + static MethodInfo from_dict(const Dictionary& p_dict); MethodInfo(); MethodInfo(const String& p_name); MethodInfo(const String& p_name, const PropertyInfo& p_param1); diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index ba98797a89..b6a69e3bd4 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -642,7 +642,7 @@ void ObjectTypeDB::get_property_list(StringName p_type, List<PropertyInfo> *p_li TypeInfo *check=type; while(check) { - for(List<PropertyInfo>::Element *E=type->property_list.front();E;E=E->next()) { + for(List<PropertyInfo>::Element *E=check->property_list.front();E;E=E->next()) { if (p_validator) { diff --git a/core/object_type_db.h b/core/object_type_db.h index 3fcd38aa31..725b424c9a 100644 --- a/core/object_type_db.h +++ b/core/object_type_db.h @@ -415,13 +415,13 @@ public: #endif template<class M> - static MethodBind* bind_native_method(uint32_t p_flags, StringName p_name, M p_method,const MethodInfo& p_info=MethodInfo(),const Vector<Variant>& p_default_args=Vector<Variant>()) { + static MethodBind* bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method,const MethodInfo& p_info=MethodInfo(),const Vector<Variant>& p_default_args=Vector<Variant>()) { GLOBAL_LOCK_FUNCTION; - MethodBind *bind = create_native_method_bind(p_method,p_info); + MethodBind *bind = create_vararg_method_bind(p_method,p_info); ERR_FAIL_COND_V(!bind,NULL); String rettype; diff --git a/core/os/input.cpp b/core/os/input.cpp index 531db73838..401ab7ffe2 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -53,6 +53,8 @@ void Input::_bind_methods() { ObjectTypeDB::bind_method(_MD("is_mouse_button_pressed","button"),&Input::is_mouse_button_pressed); ObjectTypeDB::bind_method(_MD("is_joy_button_pressed","device","button"),&Input::is_joy_button_pressed); ObjectTypeDB::bind_method(_MD("is_action_pressed","action"),&Input::is_action_pressed); + ObjectTypeDB::bind_method(_MD("is_action_just_pressed","action"),&Input::is_action_just_pressed); + ObjectTypeDB::bind_method(_MD("is_action_just_released","action"),&Input::is_action_just_released); ObjectTypeDB::bind_method(_MD("add_joy_mapping","mapping", "update_existing"),&Input::add_joy_mapping, DEFVAL(false)); ObjectTypeDB::bind_method(_MD("remove_joy_mapping","guid"),&Input::remove_joy_mapping); ObjectTypeDB::bind_method(_MD("is_joy_known","device"),&Input::is_joy_known); diff --git a/core/os/input.h b/core/os/input.h index 16bcc0ff9a..665fb4ad99 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -55,12 +55,14 @@ public: static Input *get_singleton(); - virtual bool is_key_pressed(int p_scancode)=0; - virtual bool is_mouse_button_pressed(int p_button)=0; - virtual bool is_joy_button_pressed(int p_device, int p_button)=0; - virtual bool is_action_pressed(const StringName& p_action)=0; - - virtual float get_joy_axis(int p_device,int p_axis)=0; + virtual bool is_key_pressed(int p_scancode) const=0; + virtual bool is_mouse_button_pressed(int p_button) const=0; + virtual bool is_joy_button_pressed(int p_device, int p_button) const=0; + virtual bool is_action_pressed(const StringName& p_action) const=0; + virtual bool is_action_just_pressed(const StringName& p_action) const=0; + virtual bool is_action_just_released(const StringName& p_action) const=0; + + virtual float get_joy_axis(int p_device,int p_axis) const=0; virtual String get_joy_name(int p_idx)=0; virtual Array get_connected_joysticks()=0; virtual void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid)=0; @@ -80,9 +82,9 @@ public: virtual void warp_mouse_pos(const Vector2& p_to)=0; - virtual Vector3 get_accelerometer()=0; - virtual Vector3 get_magnetometer()=0; - virtual Vector3 get_gyroscope()=0; + virtual Vector3 get_accelerometer() const=0; + virtual Vector3 get_magnetometer() const=0; + virtual Vector3 get_gyroscope() const=0; virtual void action_press(const StringName& p_action)=0; virtual void action_release(const StringName& p_action)=0; diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp index 8c79657c64..9d920724e1 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -34,8 +34,56 @@ */ bool InputEvent::operator==(const InputEvent &p_event) const { + if (type != p_event.type){ + return false; + } - return true; + switch(type) { + case NONE: + return true; + case KEY: + return key.unicode == p_event.key.unicode + && key.scancode == p_event.key.scancode + && key.echo == p_event.key.echo + && key.pressed == p_event.key.pressed + && key.mod == p_event.key.mod; + case MOUSE_MOTION: + return mouse_motion.x == p_event.mouse_motion.x + && mouse_motion.y == p_event.mouse_motion.y + && mouse_motion.relative_x == p_event.mouse_motion.relative_y + && mouse_motion.button_mask == p_event.mouse_motion.button_mask + && key.mod == p_event.key.mod; + case MOUSE_BUTTON: + return mouse_button.pressed == p_event.mouse_button.pressed + && mouse_button.x == p_event.mouse_button.x + && mouse_button.y == p_event.mouse_button.y + && mouse_button.button_index == p_event.mouse_button.button_index + && mouse_button.button_mask == p_event.mouse_button.button_mask + && key.mod == p_event.key.mod; + case JOYSTICK_MOTION: + return joy_motion.axis == p_event.joy_motion.axis + && joy_motion.axis_value == p_event.joy_motion.axis_value; + case JOYSTICK_BUTTON: + return joy_button.pressed == p_event.joy_button.pressed + && joy_button.button_index == p_event.joy_button.button_index + && joy_button.pressure == p_event.joy_button.pressure; + case SCREEN_TOUCH: + return screen_touch.pressed == p_event.screen_touch.pressed + && screen_touch.index == p_event.screen_touch.index + && screen_touch.x == p_event.screen_touch.x + && screen_touch.y == p_event.screen_touch.y; + case SCREEN_DRAG: + return screen_drag.index == p_event.screen_drag.index + && screen_drag.x == p_event.screen_drag.x + && screen_drag.y == p_event.screen_drag.y; + case ACTION: + return action.action == p_event.action.action + && action.pressed == p_event.action.pressed; + default: + ERR_PRINT("No logic to compare InputEvents of this type, this shouldn't happen."); + } + + return false; } InputEvent::operator String() const { diff --git a/core/os/os.cpp b/core/os/os.cpp index 5f86962048..ee32476234 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -587,6 +587,9 @@ OS::OS() { _time_scale=1.0; _pixel_snap=false; _allow_hidpi=true; + _fixed_frames=0; + _idle_frames=0; + _in_fixed=false; Math::seed(1234567); } diff --git a/core/os/os.h b/core/os/os.h index 2521d67e29..8e9293b3c8 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -62,6 +62,10 @@ class OS { bool _pixel_snap; bool _allow_hidpi; + uint64_t _fixed_frames; + uint64_t _idle_frames; + bool _in_fixed; + char *last_error; public: @@ -282,6 +286,10 @@ public: uint64_t get_frames_drawn(); + uint64_t get_fixed_frames() const { return _fixed_frames; } + uint64_t get_idle_frames() const { return _idle_frames; } + bool is_in_fixed_frame() const { return _in_fixed; } + bool is_stdout_verbose() const; enum CursorShape { diff --git a/core/path_db.cpp b/core/path_db.cpp index d0feda5c82..132cc83a35 100644 --- a/core/path_db.cpp +++ b/core/path_db.cpp @@ -363,6 +363,7 @@ NodePath::NodePath(const String& p_path) { from=i+1; } + } path=path.substr(0,subpath_pos); @@ -380,6 +381,8 @@ NodePath::NodePath(const String& p_path) { last_is_slash=false; } + + } if (slices==0 && !absolute && !property) @@ -413,6 +416,7 @@ NodePath::NodePath(const String& p_path) { } else { last_is_slash=false; } + } diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 97bd5f2a32..3de26573f4 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -118,6 +118,7 @@ void register_core_types() { ObjectTypeDB::register_type<Resource>(); ObjectTypeDB::register_type<FuncRef>(); ObjectTypeDB::register_virtual_type<StreamPeer>(); + ObjectTypeDB::register_type<StreamPeerBuffer>(); ObjectTypeDB::register_create_type<StreamPeerTCP>(); ObjectTypeDB::register_create_type<TCP_Server>(); ObjectTypeDB::register_create_type<PacketPeerUDP>(); diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index 99d1e22c07..1ac0907967 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -219,7 +219,8 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { if (F->get().get_type()==Variant::OBJECT) { packet_peer_stream->put_var("*"+E->get()); - packet_peer_stream->put_var(safe_get_instance_id(F->get())); + String pretty_print = F->get().operator String(); + packet_peer_stream->put_var(pretty_print.ascii().get_data()); } else { packet_peer_stream->put_var(E->get()); packet_peer_stream->put_var(F->get()); @@ -242,7 +243,8 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { if (F->get().get_type()==Variant::OBJECT) { packet_peer_stream->put_var("*"+E->get()); - packet_peer_stream->put_var(safe_get_instance_id(F->get())); + String pretty_print = F->get().operator String(); + packet_peer_stream->put_var(pretty_print.ascii().get_data()); } else { packet_peer_stream->put_var(E->get()); packet_peer_stream->put_var(F->get()); diff --git a/core/script_language.cpp b/core/script_language.cpp index 75d8b6d285..fa1d01d3eb 100644 --- a/core/script_language.cpp +++ b/core/script_language.cpp @@ -33,6 +33,7 @@ int ScriptServer::_language_count=0; bool ScriptServer::scripting_enabled=true; bool ScriptServer::reload_scripts_on_save=false; +ScriptEditRequestFunction ScriptServer::edit_request_func=NULL; void Script::_notification( int p_what) { diff --git a/core/script_language.h b/core/script_language.h index 0e3f298790..1b037e908c 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -38,6 +38,8 @@ class ScriptLanguage; +typedef void (*ScriptEditRequestFunction)(const String& p_path); + class ScriptServer { enum { @@ -50,6 +52,8 @@ class ScriptServer { static bool reload_scripts_on_save; public: + static ScriptEditRequestFunction edit_request_func; + static void set_scripting_enabled(bool p_enabled); static bool is_scripting_enabled(); static int get_language_count(); @@ -88,6 +92,8 @@ public: virtual bool can_instance() const=0; + virtual Ref<Script> get_base_script() const=0; //for script inheritance + virtual StringName get_instance_base_type() const=0; // this may not work in all scripts, will return empty if so virtual ScriptInstance* instance_create(Object *p_this)=0; virtual bool instance_has(const Object *p_this) const=0; @@ -113,7 +119,8 @@ public: virtual bool get_property_default_value(const StringName& p_property,Variant& r_value) const=0; virtual void update_exports() {} //editor tool - virtual void get_method_list(List<MethodInfo> *p_list) const=0; + virtual void get_script_method_list(List<MethodInfo> *p_list) const=0; + virtual void get_script_property_list(List<PropertyInfo> *p_list) const=0; Script() {} @@ -121,6 +128,8 @@ public: class ScriptInstance { public: + + virtual bool set(const StringName& p_name, const Variant& p_value)=0; virtual bool get(const StringName& p_name, Variant &r_ret) const=0; virtual void get_property_list(List<PropertyInfo> *p_properties) const=0; @@ -148,6 +157,17 @@ public: virtual bool is_placeholder() const { return false; } + enum RPCMode { + RPC_MODE_DISABLED, + RPC_MODE_REMOTE, + RPC_MODE_SYNC, + RPC_MODE_MASTER, + RPC_MODE_SLAVE, + }; + + virtual RPCMode get_rpc_mode(const StringName& p_method) const=0; + virtual RPCMode get_rset_mode(const StringName& p_variable) const=0; + virtual ScriptLanguage *get_language()=0; virtual ~ScriptInstance(); }; @@ -279,6 +299,9 @@ public: virtual bool is_placeholder() const { return true; } + virtual RPCMode get_rpc_mode(const StringName& p_method) const { return RPC_MODE_DISABLED; } + virtual RPCMode get_rset_mode(const StringName& p_variable) const { return RPC_MODE_DISABLED; } + PlaceHolderScriptInstance(ScriptLanguage *p_language, Ref<Script> p_script,Object *p_owner); ~PlaceHolderScriptInstance(); diff --git a/core/string_db.cpp b/core/string_db.cpp index 9a693f88e9..bf92c4eac4 100644 --- a/core/string_db.cpp +++ b/core/string_db.cpp @@ -183,7 +183,8 @@ StringName::StringName(const char *p_name) { ERR_FAIL_COND(!configured); - ERR_FAIL_COND( !p_name || !p_name[0]); + if (!p_name || p_name[0]==0) + return; //empty, ignore _global_lock(); @@ -288,6 +289,9 @@ StringName::StringName(const String& p_name) { ERR_FAIL_COND(!configured); + if (p_name==String()) + return; + _global_lock(); uint32_t hash = p_name.hash(); diff --git a/core/translation.cpp b/core/translation.cpp index 01789747ea..4592d00598 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -32,11 +32,23 @@ #include "os/os.h" static const char* locale_list[]={ +"aa", // Afar +"aa_DJ", // Afar (Djibouti) +"aa_ER", // Afar (Eritrea) +"aa_ET", // Afar (Ethiopia) +"af", // Afrikaans +"af_ZA", // Afrikaans (South Africa) +"agr_PE", // Aguaruna (Peru) +"ak_GH", // Akan (Ghana) +"am_ET", // Amharic (Ethiopia) +"an_ES", // Aragonese (Spain) +"anp_IN", // Angika (India) "ar", // Arabic "ar_AE", // Arabic (United Arab Emirates) "ar_BH", // Arabic (Bahrain) "ar_DZ", // Arabic (Algeria) "ar_EG", // Arabic (Egypt) +"ar_IN", // Arabic (India) "ar_IQ", // Arabic (Iraq) "ar_JO", // Arabic (Jordan) "ar_KW", // Arabic (Kuwait) @@ -47,48 +59,91 @@ static const char* locale_list[]={ "ar_QA", // Arabic (Qatar) "ar_SA", // Arabic (Saudi Arabia) "ar_SD", // Arabic (Sudan) +"ar_SS", // Arabic (South Soudan) "ar_SY", // Arabic (Syria) "ar_TN", // Arabic (Tunisia) "ar_YE", // Arabic (Yemen) +"as_IN", // Assamese (India) +"ast_ES", // Asturian (Spain) +"ayc_PE", // Southern Aymara (Peru) +"ay_PE", // Aymara (Peru) +"az_AZ", // Azerbaijani (Azerbaijan) "be", // Belarusian "be_BY", // Belarusian (Belarus) +"bem_ZM", // Bemba (Zambia) +"ber_DZ", // Berber languages (Algeria) +"ber_MA", // Berber languages (Morocco) "bg", // Bulgarian "bg_BG", // Bulgarian (Bulgaria) +"bhb_IN", // Bhili (India) +"bho_IN", // Bhojpuri (India) +"bi_TV", // Bislama (Tuvalu) "bn", // Bengali "bn_BD", // Bengali (Bangladesh) "bn_IN", // Bengali (India) +"bo", // Tibetan +"bo_CN", // Tibetan (China) +"bo_IN", // Tibetan (India) +"br_FR", // Breton (France) +"brx_IN", // Bodo (India) +"bs_BA", // Bosnian (Bosnia and Herzegovina) +"byn_ER", // Bilin (Eritrea) "ca", // Catalan +"ca_AD", // Catalan (Andorra) "ca_ES", // Catalan (Spain) +"ca_FR", // Catalan (France) +"ca_IT", // Catalan (Italy) +"ce_RU", // Chechen (Russia) +"chr_US", // Cherokee (United States) +"cmn_TW", // Mandarin Chinese (Taiwan) +"crh_UA", // Crimean Tatar (Ukraine) +"csb_PL", // Kashubian (Poland) "cs", // Czech "cs_CZ", // Czech (Czech Republic) +"cv_RU", // Chuvash (Russia) +"cy_GB", // Welsh (United Kingdom) "da", // Danish "da_DK", // Danish (Denmark) "de", // German "de_AT", // German (Austria) +"de_BE", // German (Belgium) "de_CH", // German (Switzerland) "de_DE", // German (Germany) +"de_IT", // German (Italy) "de_LU", // German (Luxembourg) +"doi_IN", // Dogri (India) +"dv_MV", // Dhivehi (Maldives) +"dz_BT", // Dzongkha (Bhutan) "el", // Greek "el_CY", // Greek (Cyprus) "el_GR", // Greek (Greece) "en", // English +"en_AG", // English (Antigua and Barbuda) "en_AU", // English (Australia) +"en_BW", // English (Botswana) "en_CA", // English (Canada) +"en_DK", // English (Denmark) "en_GB", // English (United Kingdom) +"en_HK", // English (Hong Kong) "en_IE", // English (Ireland) +"en_IL", // English (Israel) "en_IN", // English (India) -"en_MT", // English (Malta) +"en_NG", // English (Nigeria) "en_NZ", // English (New Zealand) "en_PH", // English (Philippines) "en_SG", // English (Singapore) "en_US", // English (United States) "en_ZA", // English (South Africa) +"en_ZM", // English (Zambia) +"en_ZW", // English (Zimbabwe) +"eo", // Esperanto "es", // Spanish "es_AR", // Spanish (Argentina) "es_BO", // Spanish (Bolivia) "es_CL", // Spanish (Chile) "es_CO", // Spanish (Colombia) "es_CR", // Spanish (Costa Rica) +"es_CU", // Spanish (Cuba) "es_DO", // Spanish (Dominican Republic) "es_EC", // Spanish (Ecuador) "es_ES", // Spanish (Spain) @@ -106,100 +161,252 @@ static const char* locale_list[]={ "es_VE", // Spanish (Venezuela) "et", // Estonian "et_EE", // Estonian (Estonia) +"eu", // Basque +"eu_ES", // Basque (Spain) +"fa", // Persian +"fa_IR", // Persian (Iran) +"ff_SN", // Fulah (Senegal) "fi", // Finnish "fi_FI", // Finnish (Finland) +"fil_PH", // Filipino (Philippines) +"fo_FO", // Faroese (Faroe Islands) "fr", // French "fr_BE", // French (Belgium) "fr_CA", // French (Canada) "fr_CH", // French (Switzerland) "fr_FR", // French (France) "fr_LU", // French (Luxembourg) +"fur_IT", // Friulian (Italy) +"fy_DE", // Western Frisian (Germany) +"fy_NL", // Western Frisian (Netherlands) "ga", // Irish "ga_IE", // Irish (Ireland) -"hi", // Hindi (India) +"gd_GB", // Scottish Gaelic (United Kingdom) +"gez_ER", // Geez (Eritrea) +"gez_ET", // Geez (Ethiopia) +"gl_ES", // Galician (Spain) +"gu_IN", // Gujarati (India) +"gv_GB", // Manx (United Kingdom) +"hak_TW", // Hakka Chinese (Taiwan) +"ha_NG", // Hausa (Nigeria) +"he", // Hebrew +"he_IL", // Hebrew (Israel) +"hi", // Hindi "hi_IN", // Hindi (India) +"hne_IN", // Chhattisgarhi (India) "hr", // Croatian "hr_HR", // Croatian (Croatia) +"hsb_DE", // Upper Sorbian (Germany) +"ht_HT", // Haitian (Haiti) "hu", // Hungarian "hu_HU", // Hungarian (Hungary) -"in", // Indonesian -"in_ID", // Indonesian (Indonesia) +"hus_MX", // Huastec (Mexico) +"hy_AM", // Armenian (Armenia) +"ia_FR", // Interlingua (France) +"id", // Indonesian +"id_ID", // Indonesian (Indonesia) +"ig_NG", // Igbo (Nigeria) +"ik_CA", // Inupiaq (Canada) "is", // Icelandic "is_IS", // Icelandic (Iceland) "it", // Italian "it_CH", // Italian (Switzerland) "it_IT", // Italian (Italy) -"iw", // Hebrew -"iw_IL", // Hebrew (Israel) +"iu_CA", // Inuktitut (Canada) "ja", // Japanese "ja_JP", // Japanese (Japan) -"ja_JP_JP", // Japanese (Japan,JP) +"kab_DZ", // Kabyle (Algeria) +"ka_GE", // Georgian (Georgia) +"kk_KZ", // Kazakh (Kazakhstan) +"kl_GL", // Kalaallisut (Greenland) +"km_KH", // Central Khmer (Cambodia) +"kn_IN", // Kannada (India) +"kok_IN", // Konkani (India) "ko", // Korean "ko_KR", // Korean (South Korea) +"ks_IN", // Kashmiri (India) +"ku", // Kurdish +"ku_TR", // Kurdish (Turkey) +"kw_GB", // Cornish (United Kingdom) +"ky_KG", // Kirghiz (Kyrgyzstan) +"lb_LU", // Luxembourgish (Luxembourg) +"lg_UG", // Ganda (Uganda) +"li_BE", // Limburgan (Belgium) +"li_NL", // Limburgan (Netherlands) +"lij_IT", // Ligurian (Italy) +"ln_CD", // Lingala (Congo) +"lo_LA", // Lao (Laos) "lt", // Lithuanian "lt_LT", // Lithuanian (Lithuania) "lv", // Latvian "lv_LV", // Latvian (Latvia) +"lzh_TW", // Literary Chinese (Taiwan) +"mag_IN", // Magahi (India) +"mai_IN", // Maithili (India) +"mg_MG", // Malagasy (Madagascar) +"mh_MH", // Marshallese (Marshall Islands) +"mhr_RU", // Eastern Mari (Russia) +"mi_NZ", // Maori (New Zealand) +"miq_NI", // Mískito (Nicaragua) "mk", // Macedonian "mk_MK", // Macedonian (Macedonia) +"ml_IN", // Malayalam (India) +"mni_IN", // Manipuri (India) +"mn_MN", // Mongolian (Mongolia) +"mr_IN", // Marathi (India) "ms", // Malay "ms_MY", // Malay (Malaysia) "mt", // Maltese "mt_MT", // Maltese (Malta) +"my_MM", // Burmese (Myanmar) +"myv_RU", // Erzya (Russia) +"nah_MX", // Nahuatl languages (Mexico) +"nan_TW", // Min Nan Chinese (Taiwan) +"nb", // Norwegian Bokmål +"nb_NO", // Norwegian Bokmål (Norway) +"nds_DE", // Low German (Germany) +"nds_NL", // Low German (Netherlands) +"ne_NP", // Nepali (Nepal) +"nhn_MX", // Central Nahuatl (Mexico) +"niu_NU", // Niuean (Niue) +"niu_NZ", // Niuean (New Zealand) "nl", // Dutch +"nl_AW", // Dutch (Aruba) "nl_BE", // Dutch (Belgium) "nl_NL", // Dutch (Netherlands) -"no", // Norwegian -"no_NO", // Norwegian (Norway) -"no_NO_NY", // Norwegian (Norway,Nynorsk) +"nn", // Norwegian Nynorsk +"nn_NO", // Norwegian Nynorsk (Norway) +"nr_ZA", // South Ndebele (South Africa) +"nso_ZA", // Pedi (South Africa) +"oc_FR", // Occitan (France) +"om", // Oromo +"om_ET", // Oromo (Ethiopia) +"om_KE", // Oromo (Kenya) +"or_IN", // Oriya (India) +"os_RU", // Ossetian (Russia) +"pa_IN", // Panjabi (India) +"pap", // Papiamento +"pap_AN", // Papiamento (Netherlands Antilles) +"pap_AW", // Papiamento (Aruba) +"pap_CW", // Papiamento (Curaçao) +"pa_PK", // Panjabi (Pakistan) "pl", // Polish "pl_PL", // Polish (Poland) +"ps_AF", // Pushto (Afghanistan) "pt", // Portuguese "pt_BR", // Portuguese (Brazil) "pt_PT", // Portuguese (Portugal) +"quy_PE", // Ayacucho Quechua (Peru) +"quz_PE", // Cusco Quechua (Peru) +"raj_IN", // Rajasthani (India) "ro", // Romanian "ro_RO", // Romanian (Romania) "ru", // Russian "ru_RU", // Russian (Russia) +"ru_UA", // Russian (Ukraine) +"rw_RW", // Kinyarwanda (Rwanda) +"sa_IN", // Sanskrit (India) +"sat_IN", // Santali (India) +"sc_IT", // Sardinian (Italy) +"sd_IN", // Sindhi (India) +"se_NO", // Northern Sami (Norway) +"sgs_LT", // Samogitian (Lithuania) +"shs_CA", // Shuswap (Canada) +"sid_ET", // Sidamo (Ethiopia) +"si_LK", // Sinhala (Sri Lanka) "sk", // Slovak "sk_SK", // Slovak (Slovakia) "sl", // Slovenian "sl_SI", // Slovenian (Slovenia) +"so", // Somali +"so_DJ", // Somali (Djibouti) +"so_ET", // Somali (Ethiopia) +"so_KE", // Somali (Kenya) +"so_SO", // Somali (Somalia) +"son_ML", // Songhai languages (Mali) "sq", // Albanian "sq_AL", // Albanian (Albania) +"sq_KV", // Albanian (Kosovo) +"sq_MK", // Albanian (Macedonia) "sr", // Serbian -"sr_BA", // Serbian (Bosnia and Herzegovina) -"sr_CS", // Serbian (Serbia and Montenegro) "sr_ME", // Serbian (Montenegro) "sr_RS", // Serbian (Serbia) +"ss_ZA", // Swati (South Africa) +"st_ZA", // Southern Sotho (South Africa) "sv", // Swedish +"sv_FI", // Swedish (Finland) "sv_SE", // Swedish (Sweden) +"sw_KE", // Swahili (Kenya) +"sw_TZ", // Swahili (Tanzania) +"szl_PL", // Silesian (Poland) +"ta", // Tamil +"ta_IN", // Tamil (India) +"ta_LK", // Tamil (Sri Lanka) +"tcy_IN", // Tulu (India) +"te_IN", // Telugu (India) +"tg_TJ", // Tajik (Tajikistan) +"the_NP", // Chitwania Tharu (Nepal) "th", // Thai "th_TH", // Thai (Thailand) -"th_TH_TH", // Thai (Thailand,TH) +"ti", // Tigrinya +"ti_ER", // Tigrinya (Eritrea) +"ti_ET", // Tigrinya (Ethiopia) +"tig_ER", // Tigre (Eritrea) +"tk_TM", // Turkmen (Turkmenistan) +"tl_PH", // Tagalog (Philippines) +"tn_ZA", // Tswana (South Africa) "tr", // Turkish +"tr_CY", // Turkish (Cyprus) "tr_TR", // Turkish (Turkey) +"ts_ZA", // Tsonga (South Africa) +"tt_RU", // Tatar (Russia) +"ug_CN", // Uighur (China) "uk", // Ukrainian "uk_UA", // Ukrainian (Ukraine) +"unm_US", // Unami (United States) "ur", // Urdu "ur_IN", // Urdu (India) "ur_PK", // Urdu (Pakistan) +"uz", // Uzbek +"uz_UZ", // Uzbek (Uzbekistan) +"ve_ZA", // Venda (South Africa) "vi", // Vietnamese "vi_VN", // Vietnamese (Vietnam) +"wa_BE", // Walloon (Belgium) +"wae_CH", // Walser (Switzerland) +"wal_ET", // Wolaytta (Ethiopia) +"wo_SN", // Wolof (Senegal) +"xh_ZA", // Xhosa (South Africa) +"yi_US", // Yiddish (United States) +"yo_NG", // Yoruba (Nigeria) +"yue_HK", // Yue Chinese (Hong Kong) "zh", // Chinese "zh_CN", // Chinese (China) "zh_HK", // Chinese (Hong Kong) "zh_SG", // Chinese (Singapore) "zh_TW", // Chinese (Taiwan) +"zu_ZA", // Zulu (South Africa) 0 }; static const char* locale_names[]={ +"Afar", +"Afar (Djibouti)", +"Afar (Eritrea)", +"Afar (Ethiopia)", +"Afrikaans", +"Afrikaans (South Africa)", +"Aguaruna (Peru)", +"Akan (Ghana)", +"Amharic (Ethiopia)", +"Aragonese (Spain)", +"Angika (India)", "Arabic", "Arabic (United Arab Emirates)", "Arabic (Bahrain)", "Arabic (Algeria)", "Arabic (Egypt)", +"Arabic (India)", "Arabic (Iraq)", "Arabic (Jordan)", "Arabic (Kuwait)", @@ -210,48 +417,91 @@ static const char* locale_names[]={ "Arabic (Qatar)", "Arabic (Saudi Arabia)", "Arabic (Sudan)", +"Arabic (South Soudan)", "Arabic (Syria)", "Arabic (Tunisia)", "Arabic (Yemen)", +"Assamese (India)", +"Asturian (Spain)", +"Southern Aymara (Peru)", +"Aymara (Peru)", +"Azerbaijani (Azerbaijan)", "Belarusian", "Belarusian (Belarus)", +"Bemba (Zambia)", +"Berber languages (Algeria)", +"Berber languages (Morocco)", "Bulgarian", "Bulgarian (Bulgaria)", +"Bhili (India)", +"Bhojpuri (India)", +"Bislama (Tuvalu)", "Bengali", "Bengali (Bangladesh)", "Bengali (India)", +"Tibetan", +"Tibetan (China)", +"Tibetan (India)", +"Breton (France)", +"Bodo (India)", +"Bosnian (Bosnia and Herzegovina)", +"Bilin (Eritrea)", "Catalan", +"Catalan (Andorra)", "Catalan (Spain)", +"Catalan (France)", +"Catalan (Italy)", +"Chechen (Russia)", +"Cherokee (United States)", +"Mandarin Chinese (Taiwan)", +"Crimean Tatar (Ukraine)", +"Kashubian (Poland)", "Czech", "Czech (Czech Republic)", +"Chuvash (Russia)", +"Welsh (United Kingdom)", "Danish", "Danish (Denmark)", "German", "German (Austria)", +"German (Belgium)", "German (Switzerland)", "German (Germany)", +"German (Italy)", "German (Luxembourg)", +"Dogri (India)", +"Dhivehi (Maldives)", +"Dzongkha (Bhutan)", "Greek", "Greek (Cyprus)", "Greek (Greece)", "English", +"English (Antigua and Barbuda)", "English (Australia)", +"English (Botswana)", "English (Canada)", +"English (Denmark)", "English (United Kingdom)", +"English (Hong Kong)", "English (Ireland)", +"English (Israel)", "English (India)", -"English (Malta)", +"English (Nigeria)", "English (New Zealand)", "English (Philippines)", "English (Singapore)", "English (United States)", "English (South Africa)", +"English (Zambia)", +"English (Zimbabwe)", +"Esperanto", "Spanish", "Spanish (Argentina)", "Spanish (Bolivia)", "Spanish (Chile)", "Spanish (Colombia)", "Spanish (Costa Rica)", +"Spanish (Cuba)", "Spanish (Dominican Republic)", "Spanish (Ecuador)", "Spanish (Spain)", @@ -269,91 +519,231 @@ static const char* locale_names[]={ "Spanish (Venezuela)", "Estonian", "Estonian (Estonia)", +"Basque", +"Basque (Spain)", +"Persian", +"Persian (Iran)", +"Fulah (Senegal)", "Finnish", "Finnish (Finland)", +"Filipino (Philippines)", +"Faroese (Faroe Islands)", "French", "French (Belgium)", "French (Canada)", "French (Switzerland)", "French (France)", "French (Luxembourg)", +"Friulian (Italy)", +"Western Frisian (Germany)", +"Western Frisian (Netherlands)", "Irish", "Irish (Ireland)", +"Scottish Gaelic (United Kingdom)", +"Geez (Eritrea)", +"Geez (Ethiopia)", +"Galician (Spain)", +"Gujarati (India)", +"Manx (United Kingdom)", +"Hakka Chinese (Taiwan)", +"Hausa (Nigeria)", +"Hebrew", +"Hebrew (Israel)", +"Hindi", "Hindi (India)", -"Hindi (India)", +"Chhattisgarhi (India)", "Croatian", "Croatian (Croatia)", +"Upper Sorbian (Germany)", +"Haitian (Haiti)", "Hungarian", "Hungarian (Hungary)", +"Huastec (Mexico)", +"Armenian (Armenia)", +"Interlingua (France)", "Indonesian", "Indonesian (Indonesia)", +"Igbo (Nigeria)", +"Inupiaq (Canada)", "Icelandic", "Icelandic (Iceland)", "Italian", "Italian (Switzerland)", "Italian (Italy)", -"Hebrew", -"Hebrew (Israel)", +"Inuktitut (Canada)", "Japanese", "Japanese (Japan)", -"Japanese (Japan JP)", +"Kabyle (Algeria)", +"Georgian (Georgia)", +"Kazakh (Kazakhstan)", +"Kalaallisut (Greenland)", +"Central Khmer (Cambodia)", +"Kannada (India)", +"Konkani (India)", "Korean", "Korean (South Korea)", +"Kashmiri (India)", +"Kurdish", +"Kurdish (Turkey)", +"Cornish (United Kingdom)", +"Kirghiz (Kyrgyzstan)", +"Luxembourgish (Luxembourg)", +"Ganda (Uganda)", +"Limburgan (Belgium)", +"Limburgan (Netherlands)", +"Ligurian (Italy)", +"Lingala (Congo)", +"Lao (Laos)", "Lithuanian", "Lithuanian (Lithuania)", "Latvian", "Latvian (Latvia)", +"Literary Chinese (Taiwan)", +"Magahi (India)", +"Maithili (India)", +"Malagasy (Madagascar)", +"Marshallese (Marshall Islands)", +"Eastern Mari (Russia)", +"Maori (New Zealand)", +"Mískito (Nicaragua)", "Macedonian", "Macedonian (Macedonia)", +"Malayalam (India)", +"Manipuri (India)", +"Mongolian (Mongolia)", +"Marathi (India)", "Malay", "Malay (Malaysia)", "Maltese", "Maltese (Malta)", +"Burmese (Myanmar)", +"Erzya (Russia)", +"Nahuatl languages (Mexico)", +"Min Nan Chinese (Taiwan)", +"Norwegian Bokmål", +"Norwegian Bokmål (Norway)", +"Low German (Germany)", +"Low German (Netherlands)", +"Nepali (Nepal)", +"Central Nahuatl (Mexico)", +"Niuean (Niue)", +"Niuean (New Zealand)", "Dutch", +"Dutch (Aruba)", "Dutch (Belgium)", "Dutch (Netherlands)", -"Norwegian", -"Norwegian (Norway)", -"Norwegian (Norway Nynorsk)", +"Norwegian Nynorsk", +"Norwegian Nynorsk (Norway)", +"South Ndebele (South Africa)", +"Pedi (South Africa)", +"Occitan (France)", +"Oromo", +"Oromo (Ethiopia)", +"Oromo (Kenya)", +"Oriya (India)", +"Ossetian (Russia)", +"Panjabi (India)", +"Papiamento", +"Papiamento (Netherlands Antilles)", +"Papiamento (Aruba)", +"Papiamento (Curaçao)", +"Panjabi (Pakistan)", "Polish", "Polish (Poland)", +"Pushto (Afghanistan)", "Portuguese", "Portuguese (Brazil)", "Portuguese (Portugal)", +"Ayacucho Quechua (Peru)", +"Cusco Quechua (Peru)", +"Rajasthani (India)", "Romanian", "Romanian (Romania)", "Russian", "Russian (Russia)", +"Russian (Ukraine)", +"Kinyarwanda (Rwanda)", +"Sanskrit (India)", +"Santali (India)", +"Sardinian (Italy)", +"Sindhi (India)", +"Northern Sami (Norway)", +"Samogitian (Lithuania)", +"Shuswap (Canada)", +"Sidamo (Ethiopia)", +"Sinhala (Sri Lanka)", "Slovak", "Slovak (Slovakia)", "Slovenian", "Slovenian (Slovenia)", +"Somali", +"Somali (Djibouti)", +"Somali (Ethiopia)", +"Somali (Kenya)", +"Somali (Somalia)", +"Songhai languages (Mali)", "Albanian", "Albanian (Albania)", +"Albanian (Kosovo)", +"Albanian (Macedonia)", "Serbian", -"Serbian (Bosnia and Herzegovina)", -"Serbian (Serbia and Montenegro)", "Serbian (Montenegro)", "Serbian (Serbia)", +"Swati (South Africa)", +"Southern Sotho (South Africa)", "Swedish", +"Swedish (Finland)", "Swedish (Sweden)", +"Swahili (Kenya)", +"Swahili (Tanzania)", +"Silesian (Poland)", +"Tamil", +"Tamil (India)", +"Tamil (Sri Lanka)", +"Tulu (India)", +"Telugu (India)", +"Tajik (Tajikistan)", +"Chitwania Tharu (Nepal)", "Thai", "Thai (Thailand)", -"Thai (Thailand TH)", +"Tigrinya", +"Tigrinya (Eritrea)", +"Tigrinya (Ethiopia)", +"Tigre (Eritrea)", +"Turkmen (Turkmenistan)", +"Tagalog (Philippines)", +"Tswana (South Africa)", "Turkish", +"Turkish (Cyprus)", "Turkish (Turkey)", +"Tsonga (South Africa)", +"Tatar (Russia)", +"Uighur (China)", "Ukrainian", "Ukrainian (Ukraine)", +"Unami (United States)", "Urdu", "Urdu (India)", "Urdu (Pakistan)", +"Uzbek", +"Uzbek (Uzbekistan)", +"Venda (South Africa)", "Vietnamese", "Vietnamese (Vietnam)", +"Walloon (Belgium)", +"Walser (Switzerland)", +"Wolaytta (Ethiopia)", +"Wolof (Senegal)", +"Xhosa (South Africa)", +"Yiddish (United States)", +"Yoruba (Nigeria)", +"Yue Chinese (Hong Kong)", "Chinese", "Chinese (China)", "Chinese (Hong Kong)", "Chinese (Singapore)", "Chinese (Taiwan)", +"Zulu (South Africa)", 0 }; diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index d6d32ccaef..e8a71d4991 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -52,26 +52,46 @@ void UndoRedo::_discard_redo() { } - -void UndoRedo::create_action(const String& p_name,bool p_mergeable) { +void UndoRedo::create_action(const String& p_name,MergeMode p_mode) { if (action_level==0) { _discard_redo(); - if (p_mergeable && actions.size() && actions[actions.size()-1].name==p_name) { - //old will replace new (it's mergeable after all) - // should check references though! + // Check if the merge operation is valid + if (p_mode!=MERGE_DISABLE && actions.size() && actions[actions.size()-1].name==p_name) { + current_action=actions.size()-2; - actions[current_action+1].do_ops.clear(); - //actions[current_action+1].undo_ops.clear(); - no, this is kept - merging=true; + + if (p_mode==MERGE_ENDS) { + + // Clear all do ops from last action, and delete all object references + List<Operation>::Element *E=actions[current_action+1].do_ops.front(); + + while (E) { + + if (E->get().type==Operation::TYPE_REFERENCE) { + + Object *obj=ObjectDB::get_instance(E->get().object); + + if (obj) + memdelete(obj); + } + + E=E->next(); + actions[current_action+1].do_ops.pop_front(); + } + } + + merge_mode=p_mode; } else { + Action new_action; new_action.name=p_name; actions.push_back(new_action); - merging=false; + + merge_mode=MERGE_DISABLE; } } @@ -102,8 +122,10 @@ void UndoRedo::add_undo_method(Object *p_object,const String& p_method,VARIANT_A VARIANT_ARGPTRS ERR_FAIL_COND(action_level<=0); ERR_FAIL_COND((current_action+1)>=actions.size()); - if (merging) - return; //- no undo if merging + + // No undo if the merge mode is MERGE_ENDS + if (merge_mode==MERGE_ENDS) + return; Operation undo_op; undo_op.object=p_object->get_instance_ID(); @@ -139,6 +161,10 @@ void UndoRedo::add_undo_property(Object *p_object,const String& p_property,const ERR_FAIL_COND(action_level<=0); ERR_FAIL_COND((current_action+1)>=actions.size()); + // No undo if the merge mode is MERGE_ENDS + if (merge_mode==MERGE_ENDS) + return; + Operation undo_op; undo_op.object=p_object->get_instance_ID(); if (p_object->cast_to<Resource>()) @@ -167,6 +193,11 @@ void UndoRedo::add_undo_reference(Object *p_object) { ERR_FAIL_COND(action_level<=0); ERR_FAIL_COND((current_action+1)>=actions.size()); + + // No undo if the merge mode is MERGE_ENDS + if (merge_mode==MERGE_ENDS) + return; + Operation undo_op; undo_op.object=p_object->get_instance_ID(); if (p_object->cast_to<Resource>()) @@ -352,7 +383,7 @@ UndoRedo::UndoRedo() { action_level=0; current_action=-1; max_steps=-1; - merging=true; + merge_mode=MERGE_DISABLE; callback=NULL; callback_ud=NULL; @@ -448,7 +479,7 @@ Variant UndoRedo::_add_undo_method(const Variant** p_args, int p_argcount, Varia void UndoRedo::_bind_methods() { - ObjectTypeDB::bind_method(_MD("create_action","name","mergeable"),&UndoRedo::create_action, DEFVAL(false) ); + ObjectTypeDB::bind_method(_MD("create_action","name","merge_mode"),&UndoRedo::create_action, DEFVAL(MERGE_DISABLE) ); ObjectTypeDB::bind_method(_MD("commit_action"),&UndoRedo::commit_action); //ObjectTypeDB::bind_method(_MD("add_do_method","p_object", "p_method", "VARIANT_ARG_LIST"),&UndoRedo::add_do_method); @@ -459,13 +490,9 @@ void UndoRedo::_bind_methods() { mi.name="add_do_method"; mi.arguments.push_back( PropertyInfo( Variant::OBJECT, "object")); mi.arguments.push_back( PropertyInfo( Variant::STRING, "method")); - Vector<Variant> defargs; - for(int i=0;i<VARIANT_ARG_MAX;++i) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"add_do_method",&UndoRedo::_add_do_method,mi,defargs); + + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"add_do_method",&UndoRedo::_add_do_method,mi); } { @@ -473,13 +500,9 @@ void UndoRedo::_bind_methods() { mi.name="add_undo_method"; mi.arguments.push_back( PropertyInfo( Variant::OBJECT, "object")); mi.arguments.push_back( PropertyInfo( Variant::STRING, "method")); - Vector<Variant> defargs; - for(int i=0;i<VARIANT_ARG_MAX;++i) { - mi.arguments.push_back( PropertyInfo( Variant::NIL, "arg"+itos(i))); - defargs.push_back(Variant()); - } - ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"add_undo_method",&UndoRedo::_add_undo_method,mi,defargs); + + ObjectTypeDB::bind_vararg_method(METHOD_FLAGS_DEFAULT,"add_undo_method",&UndoRedo::_add_undo_method,mi); } ObjectTypeDB::bind_method(_MD("add_do_property","object", "property", "value:Variant"),&UndoRedo::add_do_property); @@ -489,4 +512,8 @@ void UndoRedo::_bind_methods() { ObjectTypeDB::bind_method(_MD("clear_history"),&UndoRedo::clear_history); ObjectTypeDB::bind_method(_MD("get_current_action_name"),&UndoRedo::get_current_action_name); ObjectTypeDB::bind_method(_MD("get_version"),&UndoRedo::get_version); + + BIND_CONSTANT(MERGE_DISABLE); + BIND_CONSTANT(MERGE_ENDS); + BIND_CONSTANT(MERGE_ALL); } diff --git a/core/undo_redo.h b/core/undo_redo.h index 7f63ba9ed6..208eb6ed5e 100644 --- a/core/undo_redo.h +++ b/core/undo_redo.h @@ -41,6 +41,12 @@ class UndoRedo : public Object { OBJ_SAVE_TYPE( UndoRedo ); public: + enum MergeMode { + MERGE_DISABLE, + MERGE_ENDS, + MERGE_ALL + }; + typedef void (*CommitNotifyCallback)(void *p_ud,const String& p_name); Variant _add_do_method(const Variant** p_args, int p_argcount, Variant::CallError& r_error); Variant _add_undo_method(const Variant** p_args, int p_argcount, Variant::CallError& r_error); @@ -76,7 +82,7 @@ private: int current_action; int action_level; int max_steps; - bool merging; + MergeMode merge_mode; uint64_t version; void _pop_history_tail(); @@ -98,7 +104,7 @@ protected: public: - void create_action(const String& p_name="",bool p_mergeable=false); + void create_action(const String& p_name="",MergeMode p_mode=MERGE_DISABLE); void add_do_method(Object *p_object,const String& p_method,VARIANT_ARG_LIST); void add_undo_method(Object *p_object,const String& p_method,VARIANT_ARG_LIST); @@ -128,4 +134,6 @@ public: ~UndoRedo(); }; +VARIANT_ENUM_CAST( UndoRedo::MergeMode ); + #endif // UNDO_REDO_H diff --git a/core/variant.h b/core/variant.h index b8b028a760..90be593bd9 100644 --- a/core/variant.h +++ b/core/variant.h @@ -426,7 +426,7 @@ public: static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list); static void get_numeric_constants_for_type(Variant::Type p_type, List<StringName> *p_constants); static bool has_numeric_constant(Variant::Type p_type, const StringName& p_value); - static int get_numeric_constant_value(Variant::Type p_type, const StringName& p_value); + static int get_numeric_constant_value(Variant::Type p_type, const StringName& p_value,bool *r_valid=NULL); typedef String (*ObjectDeConstruct)(const Variant& p_object,void *ud); typedef void (*ObjectConstruct)(const String& p_text,void *ud,Variant& r_value); diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 069c20bc6e..e7e71e8251 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -54,10 +54,10 @@ struct _VariantCall { int arg_count; Vector<Variant> default_args; Vector<Variant::Type> arg_types; - -#ifdef DEBUG_ENABLED Vector<StringName> arg_names; Variant::Type return_type; + +#ifdef DEBUG_ENABLED bool returns; #endif VariantFunc func; @@ -1324,14 +1324,22 @@ bool Variant::has_numeric_constant(Variant::Type p_type, const StringName& p_val return cd.value.has(p_value); } -int Variant::get_numeric_constant_value(Variant::Type p_type, const StringName& p_value) { +int Variant::get_numeric_constant_value(Variant::Type p_type, const StringName& p_value, bool *r_valid) { + + if (r_valid) + *r_valid=false; ERR_FAIL_INDEX_V(p_type,Variant::VARIANT_MAX,0); _VariantCall::ConstantData& cd = _VariantCall::constant_data[p_type]; Map<StringName,int>::Element *E = cd.value.find(p_value); - ERR_FAIL_COND_V(!E,0); + if (!E) { + return -1; + } + if (r_valid) + *r_valid=true; + return E->get(); } diff --git a/core/variant_op.cpp b/core/variant_op.cpp index c537ed230f..fd64b58bd5 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -3046,7 +3046,7 @@ bool Variant::iter_next(Variant& r_iter,bool &valid) const { const String *str=reinterpret_cast<const String*>(_data._mem); int idx = r_iter; idx++; - if (idx >= str->size()) + if (idx >= str->length()) return false; r_iter = idx; return true; |