Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Kostadin Damyanov 2015-08-09 12:45:21 +03:00
commit cdf1ac7d58
152 changed files with 10703 additions and 7971 deletions

View File

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

View File

@ -31,7 +31,7 @@
//#include "math_funcs.h"
#include <stdio.h>
#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<String> 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<String>::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; i<regexp.get_capture_count(); i++)
{
printf("%ls\n", regexp.get_capture(i).c_str());
}
return res;
};
struct test_27_data {

View File

@ -494,6 +494,10 @@ uint64_t _OS::get_unix_time() const {
return OS::get_singleton()->get_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<uint8_t> &p_arr) {
int len = p_arr.size();
DVector<uint8_t>::Read r = p_arr.read();
int b64len = len / 3 * 4 + 4 + 1;
DVector<uint8_t> b64buff;
b64buff.resize(b64len);
DVector<uint8_t>::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<uint8_t> _Marshalls::base64_to_raw(const String &p_str) {
int strlen = p_str.length();
CharString cstr = p_str.ascii();
int arr_len;
DVector<uint8_t> buf;
{
buf.resize(strlen / 4 * 3 + 1);
DVector<uint8_t>::Write w = buf.write();
arr_len = base64_decode((char*)(&w[0]), (char*)cstr.get_data(), strlen);
};
buf.resize(arr_len);
// conversion from DVector<uint8_t> 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<uint8_t> b64buff;
b64buff.resize(b64len);
DVector<uint8_t>::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<uint8_t> buf;
buf.resize(strlen / 4 * 3 + 1 + 1);
DVector<uint8_t>::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();
}

View File

@ -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<uint8_t>& p_arr);
DVector<uint8_t> base64_to_raw(const String& p_str);
String utf8_to_base64(const String& p_str);
String base64_to_utf8(const String& p_str);
_Marshalls() {};
};

View File

@ -1149,6 +1149,12 @@ Error Globals::_save_settings_text(const String& p_file,const Map<String,List<St
return OK;
}
Error Globals::_save_custom_bnd(const String &p_file) { // add other params as dictionary and array?
return save_custom(p_file);
};
Error Globals::save_custom(const String& p_path,const CustomMap& p_custom,const Set<String>& p_ignore_masks) {
ERR_FAIL_COND_V(p_path=="",ERR_INVALID_PARAMETER);
@ -1321,7 +1327,7 @@ Vector<String> 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() {

View File

@ -86,6 +86,7 @@ protected:
List<Singleton> singletons;
Error _save_custom_bnd(const String& p_file);
bool _load_resource_pack(const String& p_pack);

View File

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

View File

@ -5,10 +5,12 @@
#include "print_string.h"
#define COMP_MAGIC 0x43454447
#include "core/variant.h"
#include <stdio.h>
Error FileAccessEncrypted::open_and_parse(FileAccess *p_base,const Vector<uint8_t>& 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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<String> *p_types) {
void ObjectTypeDB::get_type_list( List<StringName> *p_types) {
OBJTYPE_LOCK;
@ -235,7 +235,7 @@ void ObjectTypeDB::get_type_list( List<String> *p_types) {
}
void ObjectTypeDB::get_inheriters_from( const String& p_type,List<String> *p_types) {
void ObjectTypeDB::get_inheriters_from( const StringName& p_type,List<StringName> *p_types) {
OBJTYPE_LOCK;
@ -249,7 +249,7 @@ void ObjectTypeDB::get_inheriters_from( const String& p_type,List<String> *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};

View File

@ -228,13 +228,13 @@ public:
T::register_custom_data_to_otdb();
}
static void get_type_list( List<String> *p_types);
static void get_inheriters_from( const String& p_type,List<String> *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<StringName> *p_types);
static void get_inheriters_from( const StringName& p_type,List<StringName> *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<class N, class M>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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;i<oe.callstack.size();i++) {
packet_peer_stream->put_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<ScriptLanguage::StackInfo> si;
for(int i=0;i<ScriptServer::get_language_count();i++) {
si=ScriptServer::get_language(i)->debug_get_current_stack_info();
if (si.size())
break;
}
cstack.resize(si.size()*2);
for(int i=0;i<si.size();i++) {
String path;
int line=0;
if (si[i].script.is_valid()) {
path=si[i].script->get_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_chars<s.length()) {
s=s.substr(0,allowed_chars);
}
sdr->char_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);
}

View File

@ -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<String> output_strings;
List<Message> messages;
List<OutputError> 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();

View File

@ -176,6 +176,13 @@ public:
virtual void debug_get_globals(List<String> *p_locals, List<Variant> *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<Script> script;
int line;
};
virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); }
/* LOADER FUNCTIONS */
virtual void get_recognized_extensions(List<String> *p_extensions) const=0;
@ -238,6 +245,32 @@ public:
typedef void (*RequestSceneTreeMessageFunc)(void *);
struct LiveEditFuncs {
void *udata;
void (*node_path_func)(void *,const NodePath &p_path,int p_id);
void (*res_path_func)(void *,const String &p_path,int p_id);
void (*node_set_func)(void *,int p_id,const StringName& p_prop,const Variant& p_value);
void (*node_set_res_func)(void *,int p_id,const StringName& p_prop,const String& p_value);
void (*node_call_func)(void *,int p_id,const StringName& p_method,VARIANT_ARG_DECLARE);
void (*res_set_func)(void *,int p_id,const StringName& p_prop,const Variant& p_value);
void (*res_set_res_func)(void *,int p_id,const StringName& p_prop,const String& p_value);
void (*res_call_func)(void *,int p_id,const StringName& p_method,VARIANT_ARG_DECLARE);
void (*root_func)(void*, const NodePath& p_scene_path,const String& p_scene_from);
void (*tree_create_node_func)(void*,const NodePath& p_parent,const String& p_type,const String& p_name);
void (*tree_instance_node_func)(void*,const NodePath& p_parent,const String& p_path,const String& p_name);
void (*tree_remove_node_func)(void*,const NodePath& p_at);
void (*tree_remove_and_keep_node_func)(void*,const NodePath& p_at,ObjectID p_keep_id);
void (*tree_restore_node_func)(void*,ObjectID p_id,const NodePath& p_at,int p_at_pos);
void (*tree_duplicate_node_func)(void*,const NodePath& p_at,const String& p_new_name);
void (*tree_reparent_node_func)(void*,const NodePath& p_at,const NodePath& p_new_place,const String& p_new_name,int p_at_pos);
};
_FORCE_INLINE_ static ScriptDebugger * get_singleton() { return singleton; }
void set_lines_left(int p_left);
int get_lines_left() const;
@ -252,10 +285,12 @@ public:
bool is_breakpoint_line(int p_line) const;
void clear_breakpoints();
virtual void debug(ScriptLanguage *p_script,bool p_can_continue=true)=0;
virtual void idle_poll();
virtual void line_poll();
void set_break_language(ScriptLanguage *p_lang);
ScriptLanguage* get_break_language() const;
@ -265,6 +300,7 @@ public:
virtual void request_quit() {}
virtual void set_request_scene_tree_message_func(RequestSceneTreeMessageFunc p_func, void *p_udata) {}
virtual void set_live_edit_funcs(LiveEditFuncs *p_funcs) {}
ScriptDebugger();
virtual ~ScriptDebugger() {singleton=NULL;}

View File

@ -158,7 +158,7 @@ void StringName::operator=(const StringName& p_name) {
_data = p_name._data;
}
}
/* was inlined
StringName::operator String() const {
if (_data)
@ -166,7 +166,7 @@ StringName::operator String() const {
return "";
}
*/
StringName::StringName(const StringName& p_name) {
ERR_FAIL_COND(!configured);

View File

@ -114,7 +114,17 @@ public:
}
bool operator!=(const StringName& p_name) const;
operator String() const;
_FORCE_INLINE_ operator String() const {
if (_data) {
if (_data->cname )
return String(_data->cname);
else
return _data->name;
}
return String();
}
static StringName search(const char *p_name);
static StringName search(const CharType *p_name);

View File

@ -244,7 +244,12 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
Resource* res = obj->cast_to<Resource>();
if (res)
res->set_edited(true);
#endif
if (method_callback) {
method_callback(method_callbck_ud,obj,op.name,VARIANT_ARGS_FROM_ARRAY(op.args));
}
} break;
case Operation::TYPE_PROPERTY: {
@ -254,6 +259,9 @@ void UndoRedo::_process_operation_list(List<Operation>::Element *E) {
if (res)
res->set_edited(true);
#endif
if (property_callback) {
property_callback(prop_callback_ud,obj,op.name,op.args[0]);
}
} break;
case Operation::TYPE_REFERENCE: {
//do nothing
@ -325,6 +333,19 @@ void UndoRedo::set_commit_notify_callback(CommitNotifyCallback p_callback,void*
callback_ud=p_ud;
}
void UndoRedo::set_method_notify_callback(MethodNotifyCallback p_method_callback,void* p_ud) {
method_callback=p_method_callback;
method_callbck_ud=p_ud;
}
void UndoRedo::set_property_notify_callback(PropertyNotifyCallback p_property_callback,void* p_ud){
property_callback=p_property_callback;
prop_callback_ud=p_ud;
}
UndoRedo::UndoRedo() {
version=1;
@ -334,6 +355,12 @@ UndoRedo::UndoRedo() {
merging=true;
callback=NULL;
callback_ud=NULL;
method_callbck_ud=NULL;
prop_callback_ud=NULL;
method_callback=NULL;
property_callback=NULL;
}
UndoRedo::~UndoRedo() {

View File

@ -45,6 +45,9 @@ public:
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);
typedef void (*MethodNotifyCallback)(void *p_ud,Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE);
typedef void (*PropertyNotifyCallback)(void *p_ud,Object*p_base,const StringName& p_property,const Variant& p_value);
private:
struct Operation {
@ -83,6 +86,11 @@ private:
CommitNotifyCallback callback;
void* callback_ud;
void* method_callbck_ud;
void* prop_callback_ud;
MethodNotifyCallback method_callback;
PropertyNotifyCallback property_callback;
protected:
@ -113,6 +121,9 @@ public:
void set_commit_notify_callback(CommitNotifyCallback p_callback,void* p_ud);
void set_method_notify_callback(MethodNotifyCallback p_method_callback,void* p_ud);
void set_property_notify_callback(PropertyNotifyCallback p_property_callback,void* p_ud);
UndoRedo();
~UndoRedo();
};

View File

@ -67,11 +67,14 @@ void String::copy_from(const char *p_cstr) {
return;
}
resize(len+1); // include 0
for(int i=0;i<len+1;i++) {
set(i,p_cstr[i]);
CharType *dst = this->ptr();
for (int i=0;i<len+1;i++) {
dst[i]=p_cstr[i];
}
}
@ -486,7 +489,7 @@ String String::capitalize() const {
String cap;
for (int i=0;i<aux.get_slice_count(" ");i++) {
String slice=aux.get_slice(" ",i);
String slice=aux.get_slicec(' ',i);
if (slice.length()>0) {
slice[0]=_find_upper(slice[0]);
@ -577,6 +580,41 @@ String String::get_slice(String p_splitter, int p_slice) const {
}
String String::get_slicec(CharType p_splitter, int p_slice) const {
if (empty())
return String();
if (p_slice<0)
return String();
const CharType *c=this->ptr();
int i=0;
int prev=0;
int count=0;
while(true) {
if (c[i]==0 || c[i]==p_splitter) {
if (p_slice==count) {
return substr(prev,i-prev);
} else {
count++;
prev=i+1;
}
}
i++;
}
return String(); //no find!
}
Vector<String> String::split_spaces() const {
@ -3333,8 +3371,8 @@ String String::path_to(const String& p_path) const {
//nothing
} else {
//dos style
String src_begin=src.get_slice("/",0);
String dst_begin=dst.get_slice("/",0);
String src_begin=src.get_slicec('/',0);
String dst_begin=dst.get_slicec('/',0);
if (src_begin!=dst_begin)
return p_path; //impossible to do this

View File

@ -153,6 +153,7 @@ public:
int get_slice_count(String p_splitter) const;
String get_slice(String p_splitter,int p_slice) const;
String get_slicec(CharType splitter,int p_slice) const;
Vector<String> split(const String &p_splitter,bool p_allow_empty=true) const;
Vector<String> split_spaces() const;

View File

@ -878,6 +878,63 @@ bool Variant::is_zero() const {
return false;
}
bool Variant::is_one() const {
switch( type ) {
case NIL: {
return true;
} break;
// atomic types
case BOOL: {
return _data._bool==true;
} break;
case INT: {
return _data._int==1;
} break;
case REAL: {
return _data._real==1;
} break;
case VECTOR2: {
return *reinterpret_cast<const Vector2*>(_data._mem)==Vector2(1,1);
} break;
case RECT2: {
return *reinterpret_cast<const Rect2*>(_data._mem)==Rect2(1,1,1,1);
} break;
case VECTOR3: {
return *reinterpret_cast<const Vector3*>(_data._mem)==Vector3(1,1,1);
} break;
case PLANE: {
return *reinterpret_cast<const Plane*>(_data._mem)==Plane(1,1,1,1);
} break;
case COLOR: {
return *reinterpret_cast<const Color*>(_data._mem)==Color(1,1,1,1);
} break;
default: { return !is_zero(); }
}
return false;
}
void Variant::reference(const Variant& p_variant) {

View File

@ -185,6 +185,7 @@ public:
_FORCE_INLINE_ bool is_array() const { return type>=ARRAY; };
bool is_shared() const;
bool is_zero() const;
bool is_one() const;
operator bool() const;
operator signed int() const;

View File

@ -340,12 +340,14 @@ template<class T>
void Vector<T>::remove(int p_index) {
ERR_FAIL_INDEX(p_index, size());
for (int i=p_index; i<size()-1; i++) {
T*p=ptr();
int len=size();
for (int i=p_index; i<len-1; i++) {
set(i, get(i+1));
p[i]=p[i+1];
};
resize(size()-1);
resize(len-1);
};
template<class T>

View File

@ -1,15 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<resource_file type="PackedScene" subresource_count="24" version="1.0" version_name="Godot Engine v1.0.rc2.custom_build">
<ext_resource path="res://osb_jump.png" type="Texture"></ext_resource>
<resource_file type="PackedScene" subresource_count="25" version="1.1" version_name="Godot Engine v1.1.stable.custom_build">
<ext_resource path="res://player.gd" type="Script"></ext_resource>
<ext_resource path="res://robot_demo.png" type="Texture"></ext_resource>
<ext_resource path="res://bullet.png" type="Texture"></ext_resource>
<ext_resource path="res://osb_right.png" type="Texture"></ext_resource>
<ext_resource path="res://sound_coin.wav" type="Sample"></ext_resource>
<ext_resource path="res://osb_fire.png" type="Texture"></ext_resource>
<ext_resource path="res://sound_jump.wav" type="Sample"></ext_resource>
<ext_resource path="res://sound_shoot.wav" type="Sample"></ext_resource>
<ext_resource path="res://osb_left.png" type="Texture"></ext_resource>
<ext_resource path="res://robot_demo.png" type="Texture"></ext_resource>
<ext_resource path="res://player.gd" type="Script"></ext_resource>
<ext_resource path="res://sound_jump.wav" type="Sample"></ext_resource>
<ext_resource path="res://osb_right.png" type="Texture"></ext_resource>
<ext_resource path="res://osb_jump.png" type="Texture"></ext_resource>
<ext_resource path="res://osb_fire.png" type="Texture"></ext_resource>
<resource type="RayShape2D" path="local://1">
<real name="custom_solver_bias"> 0.5 </real>
<real name="length"> 20 </real>
@ -19,6 +19,11 @@
<real name="custom_solver_bias"> 0 </real>
<vector2_array name="points" len="3"> -19.902, -24.8691, 19.3625, -24.6056, -0.138023, 16.5036 </vector2_array>
</resource>
<resource type="ColorRamp" path="local://14">
<real_array name="offsets" len="2"> 0, 1 </real_array>
<color_array name="colors" len="2"> 1, 1, 1, 1, 0, 0, 0, 0.0442478 </color_array>
</resource>
<resource type="Animation" path="local://3">
<string name="resource/name"> "idle" </string>
@ -31,6 +36,8 @@
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
<real_array len="8"> 0, 1.25, 1.5, 2, 4.5, 4.75, 5, 5.25 </real_array>
<string> "transitions" </string>
<real_array len="8"> 1, 1, 1, 1, 1, 1, 1, 1 </real_array>
<string> "values" </string>
@ -44,8 +51,6 @@
<int> 19 </int>
<int> 16 </int>
</array>
<string> "times" </string>
<real_array len="8"> 0, 1.25, 1.5, 2, 4.5, 4.75, 5, 5.25 </real_array>
</dictionary>
</resource>
@ -60,6 +65,8 @@
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
<real_array len="3"> 0, 0.25, 0.5 </real_array>
<string> "transitions" </string>
<real_array len="3"> 1, 1, 1 </real_array>
<string> "values" </string>
@ -68,8 +75,6 @@
<int> 24 </int>
<int> 23 </int>
</array>
<string> "times" </string>
<real_array len="3"> 0, 0.25, 0.5 </real_array>
</dictionary>
</resource>
@ -84,14 +89,14 @@
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 25 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
@ -105,6 +110,8 @@
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
<real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
<string> "transitions" </string>
<real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
<string> "values" </string>
@ -116,56 +123,10 @@
<int> 4 </int>
<int> 0 </int>
</array>
<string> "times" </string>
<real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://7">
<string name="resource/name"> "crouch" </string>
<real name="length"> 0.01 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 22 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://8">
<string name="resource/name"> "falling" </string>
<real name="length"> 0.01 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 21 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://9">
<resource type="Animation" path="local://11">
<real name="length"> 1.25 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
@ -175,19 +136,19 @@
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
<real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
<string> "transitions" </string>
<real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
<string> "values" </string>
<array len="6" shared="false">
<int> 10 </int>
<int> 11 </int>
<int> 12 </int>
<int> 13 </int>
<int> 14 </int>
<int> 5 </int>
<int> 6 </int>
<int> 7 </int>
<int> 8 </int>
<int> 9 </int>
<int> 5 </int>
</array>
<string> "times" </string>
<real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
</dictionary>
</resource>
@ -202,18 +163,62 @@
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 26 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
<resource type="Animation" path="local://11">
<resource type="Animation" path="local://7">
<string name="resource/name"> "crouch" </string>
<real name="length"> 0.01 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 22 </int>
</array>
</dictionary>
</resource>
<resource type="Animation" path="local://8">
<string name="resource/name"> "falling" </string>
<real name="length"> 0.01 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
<string name="tracks/0/type"> "value" </string>
<node_path name="tracks/0/path"> "sprite:frame" </node_path>
<int name="tracks/0/interp"> 1 </int>
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 21 </int>
</array>
</dictionary>
</resource>
<resource type="Animation" path="local://9">
<real name="length"> 1.25 </real>
<bool name="loop"> True </bool>
<real name="step"> 0.25 </real>
@ -223,19 +228,19 @@
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
<real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
<string> "transitions" </string>
<real_array len="6"> 1, 1, 1, 1, 1, 1 </real_array>
<string> "values" </string>
<array len="6" shared="false">
<int> 5 </int>
<int> 6 </int>
<int> 7 </int>
<int> 8 </int>
<int> 9 </int>
<int> 10 </int>
<int> 11 </int>
<int> 12 </int>
<int> 13 </int>
<int> 14 </int>
<int> 5 </int>
</array>
<string> "times" </string>
<real_array len="6"> 0, 0.25, 0.5, 0.75, 1, 1.25 </real_array>
</dictionary>
</resource>
@ -249,14 +254,14 @@
<dictionary name="tracks/0/keys" shared="false">
<string> "cont" </string>
<bool> False </bool>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
<string> "transitions" </string>
<real_array len="1"> 1 </real_array>
<string> "values" </string>
<array len="1" shared="false">
<int> 26 </int>
</array>
<string> "times" </string>
<real_array len="1"> 0 </real_array>
</dictionary>
</resource>
@ -289,30 +294,28 @@
</resource>
<main_resource>
<dictionary name="_bundled" shared="false">
<string> "conn_count" </string>
<int> 0 </int>
<string> "conns" </string>
<int_array len="0"> </int_array>
<string> "names" </string>
<string_array len="180">
<string_array len="142">
<string> "player" </string>
<string> "RigidBody2D" </string>
<string> "_import_path" </string>
<string> "visibility/visible" </string>
<string> "visibility/opacity" </string>
<string> "visibility/self_opacity" </string>
<string> "visibility/behind_parent" </string>
<string> "transform/pos" </string>
<string> "transform/rot" </string>
<string> "transform/scale" </string>
<string> "shape_count" </string>
<string> "input/pickable" </string>
<string> "shapes/0/shape" </string>
<string> "shapes/0/transform" </string>
<string> "shapes/0/trigger" </string>
<string> "shapes/1/shape" </string>
<string> "shapes/1/transform" </string>
<string> "shapes/1/trigger" </string>
<string> "layers" </string>
<string> "collision/layers" </string>
<string> "collision/mask" </string>
<string> "mode" </string>
<string> "mass" </string>
<string> "friction" </string>
<string> "bounce" </string>
<string> "gravity_scale" </string>
<string> "custom_integrator" </string>
<string> "continuous_cd" </string>
<string> "contacts_reported" </string>
@ -321,39 +324,28 @@
<string> "can_sleep" </string>
<string> "velocity/linear" </string>
<string> "velocity/angular" </string>
<string> "damp_override/linear" </string>
<string> "damp_override/angular" </string>
<string> "script/script" </string>
<string> "__meta__" </string>
<string> "sprite" </string>
<string> "Sprite" </string>
<string> "texture" </string>
<string> "centered" </string>
<string> "offset" </string>
<string> "flip_h" </string>
<string> "flip_v" </string>
<string> "vframes" </string>
<string> "hframes" </string>
<string> "frame" </string>
<string> "modulate" </string>
<string> "region" </string>
<string> "region_rect" </string>
<string> "smoke" </string>
<string> "Particles2D" </string>
<string> "visibility/self_opacity" </string>
<string> "visibility/blend_mode" </string>
<string> "transform/pos" </string>
<string> "transform/rot" </string>
<string> "config/amount" </string>
<string> "config/lifetime" </string>
<string> "config/time_scale" </string>
<string> "config/preprocess" </string>
<string> "config/emit_timeout" </string>
<string> "config/emitting" </string>
<string> "config/offset" </string>
<string> "config/half_extents" </string>
<string> "config/local_space" </string>
<string> "config/explosiveness" </string>
<string> "config/flip_h" </string>
<string> "config/flip_v" </string>
<string> "config/texture" </string>
<string> "config/h_frames" </string>
<string> "config/v_frames" </string>
<string> "params/direction" </string>
<string> "params/spread" </string>
<string> "params/linear_velocity" </string>
@ -370,32 +362,8 @@
<string> "params/hue_variation" </string>
<string> "params/anim_speed_scale" </string>
<string> "params/anim_initial_pos" </string>
<string> "randomness/direction" </string>
<string> "randomness/spread" </string>
<string> "randomness/linear_velocity" </string>
<string> "randomness/spin_velocity" </string>
<string> "randomness/orbit_velocity" </string>
<string> "randomness/gravity_direction" </string>
<string> "randomness/gravity_strength" </string>
<string> "randomness/radial_accel" </string>
<string> "randomness/tangential_accel" </string>
<string> "randomness/damping" </string>
<string> "randomness/initial_angle" </string>
<string> "randomness/initial_size" </string>
<string> "randomness/final_size" </string>
<string> "randomness/hue_variation" </string>
<string> "randomness/anim_speed_scale" </string>
<string> "randomness/anim_initial_pos" </string>
<string> "color_phases/count" </string>
<string> "phase_0/pos" </string>
<string> "phase_0/color" </string>
<string> "phase_1/pos" </string>
<string> "phase_1/color" </string>
<string> "phase_2/pos" </string>
<string> "phase_2/color" </string>
<string> "phase_3/pos" </string>
<string> "phase_3/color" </string>
<string> "emission_points" </string>
<string> "color/color_ramp" </string>
<string> "anim" </string>
<string> "AnimationPlayer" </string>
<string> "playback/process_mode" </string>
@ -405,11 +373,11 @@
<string> "anims/jumping" </string>
<string> "anims/idle_weapon" </string>
<string> "anims/run" </string>
<string> "anims/run_weapon" </string>
<string> "anims/falling_weapon" </string>
<string> "anims/crouch" </string>
<string> "anims/falling" </string>
<string> "anims/standing_weapon_ready" </string>
<string> "anims/falling_weapon" </string>
<string> "anims/run_weapon" </string>
<string> "anims/jumping_weapon" </string>
<string> "playback/active" </string>
<string> "playback/speed" </string>
@ -417,6 +385,7 @@
<string> "autoplay" </string>
<string> "camera" </string>
<string> "Camera2D" </string>
<string> "anchor_mode" </string>
<string> "rotating" </string>
<string> "current" </string>
<string> "smoothing" </string>
@ -434,6 +403,7 @@
<string> "bullet_shoot" </string>
<string> "Position2D" </string>
<string> "CollisionShape2D" </string>
<string> "transform/scale" </string>
<string> "shape" </string>
<string> "trigger" </string>
<string> "sound" </string>
@ -458,6 +428,7 @@
<string> "ui" </string>
<string> "CanvasLayer" </string>
<string> "layer" </string>
<string> "offset" </string>
<string> "rotation" </string>
<string> "scale" </string>
<string> "left" </string>
@ -472,147 +443,149 @@
<string> "jump" </string>
<string> "fire" </string>
</string_array>
<string> "version" </string>
<int> 1 </int>
<string> "conn_count" </string>
<int> 0 </int>
<string> "node_count" </string>
<int> 14 </int>
<string> "nodes" </string>
<int_array len="394"> -1, -1, 1, 0, -1, 26, 2, 0, 3, 1, 4, 2, 5, 0, 6, 3, 7, 4, 8, 0, 9, 5, 10, 5, 11, 6, 12, 7, 13, 8, 14, 8, 15, 9, 16, 10, 17, 11, 18, 12, 19, 0, 20, 0, 21, 10, 22, 13, 23, 8, 24, 14, 25, 14, 26, 15, 27, 16, 0, 0, 0, 29, 28, -1, 3, 30, 17, 31, 6, 32, 18, 0, 1, 0, 34, 33, -1, 29, 35, 19, 36, 5, 37, 20, 38, 21, 39, 22, 40, 23, 41, 23, 42, 0, 43, 0, 44, 24, 45, 25, 46, 8, 47, 26, 48, 27, 49, 9, 50, 8, 51, 8, 52, 28, 53, 8, 54, 8, 55, 8, 56, 8, 57, 29, 58, 29, 59, 8, 60, 9, 61, 8, 62, 29, 63, 30, 0, 0, 0, 65, 64, -1, 17, 66, 5, 67, 8, 68, 31, 69, 32, 70, 33, 71, 34, 72, 35, 73, 36, 74, 37, 75, 38, 76, 39, 77, 40, 78, 41, 79, 10, 80, 29, 81, 42, 82, 43, 0, 0, 0, 84, 83, -1, 15, 85, 5, 86, 0, 87, 10, 88, 8, 89, 44, 90, 11, 91, 11, 92, 45, 93, 45, 94, 10, 95, 10, 96, 46, 97, 46, 98, 46, 99, 46, 0, 0, 0, 101, 100, -1, 1, 37, 47, 0, 0, 0, 102, 102, -1, 4, 37, 48, 103, 49, 104, 1, 105, 0, 0, 0, 0, 107, 106, -1, 14, 108, 12, 109, 50, 110, 8, 111, 9, 112, 8, 113, 8, 114, 8, 115, 51, 116, 51, 117, 51, 118, 51, 119, 6, 120, 8, 121, 8, 0, 0, 0, 122, 122, -1, 3, 123, 11, 124, 52, 105, 0, 0, 0, 0, 126, 125, -1, 4, 127, 11, 128, 13, 129, 8, 130, 44, 0, 9, 0, 132, 131, -1, 8, 37, 53, 103, 54, 133, 55, 134, 56, 135, 56, 136, 10, 137, 57, 138, 5, 0, 9, 0, 132, 139, -1, 8, 37, 58, 103, 54, 133, 59, 134, 56, 135, 56, 136, 10, 137, 60, 138, 5, 0, 9, 0, 132, 140, -1, 8, 37, 61, 103, 54, 133, 62, 134, 56, 135, 56, 136, 0, 137, 63, 138, 5, 0, 9, 0, 132, 141, -1, 8, 37, 64, 103, 54, 133, 65, 134, 56, 135, 56, 136, 0, 137, 66, 138, 5, 0 </int_array>
<string> "variants" </string>
<array len="72" shared="false">
<node_path> "" </node_path>
<bool> True </bool>
<real> 1 </real>
<array len="67" shared="false">
<bool> False </bool>
<vector2> 0, 0 </vector2>
<real> 0 </real>
<vector2> 1, 1 </vector2>
<int> 2 </int>
<resource resource_type="Shape2D" path="local://1"> </resource>
<matrix32> 1, -0, 0, 1.76469, 0.291992, -12.1587 </matrix32>
<resource resource_type="Shape2D" path="local://2"> </resource>
<matrix32> 1, -0, 0, 1, 0, 0 </matrix32>
<int> 1 </int>
<int> 2 </int>
<real> 3 </real>
<real> 0 </real>
<real> 1 </real>
<bool> True </bool>
<int> 0 </int>
<int> 3 </int>
<vector2> 0, 0 </vector2>
<real> -1 </real>
<resource resource_type="Script" path="res://player.gd"> </resource>
<dictionary shared="false">
<string> "__editor_plugin_screen__" </string>
<string> "2D" </string>
<string> "__editor_plugin_states__" </string>
<dictionary shared="false">
<string> "Script" </string>
<dictionary shared="false">
<string> "current" </string>
<int> 0 </int>
<string> "sources" </string>
<array len="1" shared="false">
<string> "res://player.gd" </string>
</array>
</dictionary>
<string> "2D" </string>
<dictionary shared="false">
<string> "pixel_snap" </string>
<bool> False </bool>
<string> "zoom" </string>
<real> 2.272073 </real>
<string> "use_snap" </string>
<bool> False </bool>
<string> "ofs" </string>
<vector2> -181.946, -86.2812 </vector2>
<string> "snap" </string>
<int> 10 </int>
<vector2> -110.795, -101.2 </vector2>
<string> "snap_grid" </string>
<bool> False </bool>
<string> "snap_offset" </string>
<vector2> 0, 0 </vector2>
<string> "snap_pixel" </string>
<bool> False </bool>
<string> "snap_relative" </string>
<bool> False </bool>
<string> "snap_rotation" </string>
<bool> False </bool>
<string> "snap_rotation_offset" </string>
<real> 0 </real>
<string> "snap_rotation_step" </string>
<real> 0.261799 </real>
<string> "snap_show_grid" </string>
<bool> False </bool>
<string> "snap_step" </string>
<vector2> 10, 10 </vector2>
<string> "zoom" </string>
<real> 2.050546 </real>
</dictionary>
<string> "3D" </string>
<dictionary shared="false">
<string> "ambient_light_color" </string>
<color> 0.15, 0.15, 0.15, 1 </color>
<string> "default_light" </string>
<bool> True </bool>
<string> "default_srgb" </string>
<bool> False </bool>
<string> "deflight_rot_x" </string>
<real> 0.942478 </real>
<string> "deflight_rot_y" </string>
<real> 0.628319 </real>
<string> "zfar" </string>
<real> 500 </real>
<string> "fov" </string>
<real> 45 </real>
<string> "show_grid" </string>
<bool> True </bool>
<string> "show_origin" </string>
<bool> True </bool>
<string> "viewport_mode" </string>
<int> 1 </int>
<string> "viewports" </string>
<array len="4" shared="false">
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
<string> "listener" </string>
<bool> True </bool>
<string> "pos" </string>
<vector3> 0, 0, 0 </vector3>
<string> "use_environment" </string>
<bool> False </bool>
<string> "use_orthogonal" </string>
<bool> False </bool>
<string> "pos" </string>
<vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
<string> "listener" </string>
<bool> False </bool>
<string> "use_environment" </string>
<bool> False </bool>
<string> "use_orthogonal" </string>
<bool> False </bool>
<string> "pos" </string>
<vector3> 0, 0, 0 </vector3>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
<string> "listener" </string>
<bool> False </bool>
<string> "pos" </string>
<vector3> 0, 0, 0 </vector3>
<string> "use_environment" </string>
<bool> False </bool>
<string> "use_orthogonal" </string>
<bool> False </bool>
<string> "pos" </string>
<vector3> 0, 0, 0 </vector3>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
<string> "listener" </string>
<bool> False </bool>
<string> "pos" </string>
<vector3> 0, 0, 0 </vector3>
<string> "use_environment" </string>
<bool> False </bool>
<string> "use_orthogonal" </string>
<bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
</dictionary>
<dictionary shared="false">
<string> "distance" </string>
<real> 4 </real>
<string> "listener" </string>
<bool> False </bool>
<string> "pos" </string>
<vector3> 0, 0, 0 </vector3>
<string> "use_environment" </string>
<bool> False </bool>
<string> "use_orthogonal" </string>
<bool> False </bool>
<string> "x_rot" </string>
<real> 0 </real>
<string> "y_rot" </string>
<real> 0 </real>
</dictionary>
</array>
<string> "viewport_mode" </string>
<int> 1 </int>
<string> "default_light" </string>
<bool> True </bool>
<string> "ambient_light_color" </string>
<color> 0.15, 0.15, 0.15, 1 </color>
<string> "show_grid" </string>
<bool> True </bool>
<string> "show_origin" </string>
<bool> True </bool>
<string> "zfar" </string>
<real> 500 </real>
<string> "znear" </string>
<real> 0.1 </real>
<string> "default_srgb" </string>
<bool> False </bool>
<string> "deflight_rot_x" </string>
<real> 0.942478 </real>
</dictionary>
</dictionary>
<string> "__editor_run_settings__" </string>
@ -622,13 +595,9 @@
<string> "run_mode" </string>
<int> 0 </int>
</dictionary>
<string> "__editor_plugin_screen__" </string>
<string> "Script" </string>
</dictionary>
<resource resource_type="Texture" path="res://robot_demo.png"> </resource>
<int> 16 </int>
<color> 1, 1, 1, 1 </color>
<rect2> 0, 0, 0, 0 </rect2>
<real> 0.363636 </real>
<vector2> 20.7312, 3.21187 </vector2>
<real> 83.450417 </real>
@ -640,24 +609,22 @@
<real> 20 </real>
<real> 9.8 </real>
<real> 2 </real>
<color> 0, 0, 0, 0.0442478 </color>
<color> 1, 0, 0, 1 </color>
<color> 0, 0, 0, 1 </color>
<vector2_array len="0"> </vector2_array>
<resource resource_type="ColorRamp" path="local://14"> </resource>
<node_path> ".." </node_path>
<resource resource_type="Animation" path="local://3"> </resource>
<resource resource_type="Animation" path="local://4"> </resource>
<resource resource_type="Animation" path="local://5"> </resource>
<resource resource_type="Animation" path="local://6"> </resource>
<resource resource_type="Animation" path="local://11"> </resource>
<resource resource_type="Animation" path="local://10"> </resource>
<resource resource_type="Animation" path="local://7"> </resource>
<resource resource_type="Animation" path="local://8"> </resource>
<resource resource_type="Animation" path="local://9"> </resource>
<resource resource_type="Animation" path="local://10"> </resource>
<resource resource_type="Animation" path="local://11"> </resource>
<resource resource_type="Animation" path="local://12"> </resource>
<array len="0" shared="false">
</array>
<string> "" </string>
<vector2> 1, 1 </vector2>
<int> 10000000 </int>
<real> 0.2 </real>
<vector2> 31.2428, 4.08784 </vector2>
@ -680,10 +647,8 @@
<resource resource_type="Texture" path="res://osb_fire.png"> </resource>
<string> "shoot" </string>
</array>
<string> "nodes" </string>
<int_array len="618"> -1, -1, 1, 0, -1, 30, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 8, 12, 9, 13, 3, 14, 10, 15, 11, 16, 3, 17, 12, 18, 7, 19, 13, 20, 5, 21, 5, 22, 1, 23, 14, 24, 15, 25, 3, 26, 3, 27, 1, 28, 4, 29, 5, 30, 16, 31, 17, 0, 0, 0, 33, 32, -1, 19, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 34, 18, 35, 1, 36, 4, 37, 3, 38, 3, 39, 7, 40, 19, 41, 14, 42, 20, 43, 3, 44, 21, 0, 1, 0, 46, 45, -1, 66, 2, 0, 3, 1, 4, 2, 5, 22, 6, 3, 47, 12, 7, 23, 8, 24, 9, 6, 48, 25, 49, 26, 50, 2, 51, 5, 52, 26, 53, 3, 54, 4, 55, 4, 56, 3, 57, 27, 58, 3, 59, 3, 60, 28, 61, 12, 62, 12, 63, 5, 64, 29, 65, 30, 66, 2, 67, 5, 68, 5, 69, 31, 70, 5, 71, 5, 72, 5, 73, 5, 74, 32, 75, 32, 76, 5, 77, 2, 78, 5, 79, 5, 80, 5, 81, 5, 82, 32, 83, 5, 84, 5, 85, 5, 86, 5, 87, 5, 88, 5, 89, 5, 90, 5, 91, 5, 92, 5, 93, 5, 94, 5, 95, 7, 96, 5, 97, 20, 98, 2, 99, 33, 100, 2, 101, 34, 102, 2, 103, 35, 104, 36, 0, 0, 0, 106, 105, -1, 18, 2, 0, 107, 12, 108, 5, 109, 37, 110, 38, 111, 39, 112, 40, 113, 41, 114, 42, 115, 43, 116, 44, 117, 45, 118, 46, 119, 47, 120, 1, 121, 32, 122, 48, 123, 49, 0, 0, 0, 125, 124, -1, 23, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 35, 1, 126, 3, 127, 1, 128, 5, 129, 6, 130, 14, 131, 14, 132, 50, 133, 50, 134, 1, 135, 1, 136, 51, 137, 51, 138, 51, 139, 51, 0, 0, 0, 141, 140, -1, 8, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 52, 8, 5, 9, 6, 0, 0, 0, 142, 142, -1, 10, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 53, 8, 5, 9, 54, 143, 8, 144, 3, 0, 0, 0, 146, 145, -1, 15, 2, 0, 147, 15, 148, 55, 149, 5, 150, 2, 151, 5, 152, 5, 153, 5, 154, 56, 155, 56, 156, 56, 157, 56, 158, 7, 159, 5, 160, 5, 0, 0, 0, 161, 161, -1, 10, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 162, 14, 163, 57, 0, 0, 0, 165, 164, -1, 5, 2, 0, 166, 14, 36, 4, 167, 5, 168, 6, 0, 9, 0, 170, 169, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 58, 8, 5, 9, 59, 171, 60, 172, 61, 173, 61, 174, 1, 175, 62, 176, 12, 0, 9, 0, 170, 177, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 63, 8, 5, 9, 59, 171, 64, 172, 61, 173, 61, 174, 1, 175, 65, 176, 12, 0, 9, 0, 170, 178, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 66, 8, 5, 9, 59, 171, 67, 172, 61, 173, 61, 174, 3, 175, 68, 176, 12, 0, 9, 0, 170, 179, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 69, 8, 5, 9, 59, 171, 70, 172, 61, 173, 61, 174, 3, 175, 71, 176, 12, 0 </int_array>
<string> "conns" </string>
<int_array len="0"> </int_array>
<string> "version" </string>
<int> 1 </int>
</dictionary>
</main_resource>

View File

@ -8,12 +8,12 @@ var max_points = 0
func _ready():
var f = File.new()
#load high score
if (f.open("user://highscore",File.READ)==OK):
max_points=f.get_var()
func game_over():
if (points>max_points):
max_points=points

View File

@ -14,7 +14,6 @@ var offset=0
func _process(delta):
offset+=delta*SPEED
set_pos(Vector2(offset,0))

View File

@ -0,0 +1,4 @@
[application]
name="RegEx"
main_scene="res://regex.scn"

22
demos/misc/regex/regex.gd Normal file
View File

@ -0,0 +1,22 @@
extends VBoxContainer
var regex = RegEx.new()
func update_expression():
regex.compile(get_node("Expression").get_text())
update_text()
func update_text():
var text = get_node("Text").get_text()
regex.find(text)
var list = get_node("List")
for child in list.get_children():
child.queue_free()
for res in regex.get_captures():
var label = Label.new()
label.set_text(res)
list.add_child(label)
func _ready():
get_node("Text").set_text("They asked me \"What's going on \\\"in the manor\\\"?\"")
update_expression()

BIN
demos/misc/regex/regex.scn Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@ if (env["openssl"]=="builtin"):
SConscript("rtaudio/SCsub");
SConscript("nedmalloc/SCsub");
SConscript("trex/SCsub");
SConscript("nrex/SCsub");
SConscript("chibi/SCsub");
if (env["vorbis"]=="yes" or env["speex"]=="yes" or env["theora"]=="yes"):
SConscript("ogg/SCsub");

64
drivers/nrex/README.md Normal file
View File

@ -0,0 +1,64 @@
# NREX: Node RegEx
Small node-based regular expression library. It only does text pattern
matchhing, not replacement. To use add the files `nrex.hpp`, `nrex.cpp`
and `nrex_config.h` to your project and follow the example:
nrex regex;
regex.compile("^(fo+)bar$");
nrex_result captures[regex.capture_size()];
if (regex.match("foobar", captures))
{
std::cout << captures[0].start << std::endl;
std::cout << captures[0].length << std::endl;
}
More details about its use is documented in `nrex.hpp`
Currently supported features:
* Capturing `()` and non-capturing `(?:)` groups
* Any character `.`
* Shorthand caracter classes `\w\W\s\S\d\D`
* User-defined character classes such as `[A-Za-z]`
* Simple quantifiers `?`, `*` and `+`
* Range quantifiers `{0,1}`
* Lazy (non-greedy) quantifiers `*?`
* Begining `^` and end `$` anchors
* Alternation `|`
* Backreferences `\1` to `\99`
To do list:
* Unicode `\uFFFF` code points
## License
Copyright (c) 2015, Zher Huei Lee
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -2,8 +2,7 @@
Import('env')
sources = [
'trex.c',
'nrex.cpp',
'regex.cpp',
]
env.add_source_files(env.drivers_sources, sources)

910
drivers/nrex/nrex.cpp Normal file
View File

@ -0,0 +1,910 @@
// NREX: Node RegEx
//
// Copyright (c) 2015, Zher Huei Lee
// All rights reserved.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
#include "nrex.hpp"
#ifdef NREX_UNICODE
#include <wctype.h>
#include <wchar.h>
#define NREX_ISALPHANUM iswalnum
#define NREX_STRLEN wcslen
#else
#include <ctype.h>
#include <string.h>
#define NREX_ISALPHANUM isalnum
#define NREX_STRLEN strlen
#endif
#ifdef NREX_THROW_ERROR
#define NREX_COMPILE_ERROR(M) throw nrex_compile_error(M)
#else
#define NREX_COMPILE_ERROR(M) reset(); return false
#endif
#ifndef NREX_NEW
#define NREX_NEW(X) new X
#define NREX_NEW_ARRAY(X, N) new X[N]
#define NREX_DELETE(X) delete X
#define NREX_DELETE_ARRAY(X) delete[] X
#endif
template<typename T>
class nrex_array
{
private:
T* _data;
unsigned int _reserved;
unsigned int _size;
public:
nrex_array()
: _data(NREX_NEW_ARRAY(T, 2))
, _reserved(2)
, _size(0)
{
}
~nrex_array()
{
NREX_DELETE_ARRAY(_data);
}
unsigned int size() const
{
return _size;
}
void reserve(unsigned int size)
{
T* old = _data;
_data = NREX_NEW_ARRAY(T, size);
_reserved = size;
for (unsigned int i = 0; i < _size; ++i)
{
_data[i] = old[i];
}
NREX_DELETE_ARRAY(old);
}
void push(T item)
{
if (_size == _reserved)
{
reserve(_reserved * 2);
}
_data[_size] = item;
_size++;
}
T& top()
{
return _data[_size - 1];
}
const T& operator[] (unsigned int i) const
{
return _data[i];
}
void pop()
{
if (_size > 0)
{
--_size;
}
}
};
static nrex_char nrex_unescape(nrex_char repr)
{
switch (repr)
{
case '^': return '^';
case '$': return '$';
case '(': return '(';
case ')': return ')';
case '\\': return '\\';
case '.': return '.';
case '+': return '+';
case '*': return '*';
case '?': return '?';
case '-': return '-';
case 'a': return '\a';
case 'e': return '\e';
case 'f': return '\f';
case 'n': return '\n';
case 'r': return '\r';
case 't': return '\t';
case 'v': return '\v';
}
return 0;
}
struct nrex_search
{
public:
const nrex_char* str;
nrex_result* captures;
int end;
bool complete;
nrex_char at(int pos)
{
return str[pos];
}
nrex_search(const nrex_char* str, nrex_result* captures)
: str(str)
, captures(captures)
, end(0)
{
}
};
struct nrex_node
{
nrex_node* next;
nrex_node* previous;
nrex_node* parent;
bool quantifiable;
nrex_node(bool quantify = false)
: next(NULL)
, previous(NULL)
, parent(NULL)
, quantifiable(quantify)
{
}
virtual ~nrex_node()
{
if (next)
{
NREX_DELETE(next);
}
}
virtual int test(nrex_search* s, int pos) const
{
return next ? next->test(s, pos) : -1;
}
virtual int test_parent(nrex_search* s, int pos) const
{
if (next)
{
pos = next->test(s, pos);
}
if (parent && pos >= 0)
{
pos = parent->test_parent(s, pos);
}
if (pos >= 0)
{
s->complete = true;
}
return pos;
}
};
struct nrex_node_group : public nrex_node
{
int capturing;
bool negate;
nrex_array<nrex_node*> childset;
nrex_node* back;
nrex_node_group(int capturing)
: nrex_node(true)
, capturing(capturing)
, negate(false)
, back(NULL)
{
}
virtual ~nrex_node_group()
{
for (unsigned int i = 0; i < childset.size(); ++i)
{
NREX_DELETE(childset[i]);
}
}
int test(nrex_search* s, int pos) const
{
if (capturing >= 0)
{
s->captures[capturing].start = pos;
}
for (unsigned int i = 0; i < childset.size(); ++i)
{
s->complete = false;
int res = childset[i]->test(s, pos);
if (s->complete)
{
return res;
}
if (negate)
{
if (res < 0)
{
res = pos + 1;
}
else
{
return -1;
}
}
if (res >= 0)
{
if (capturing >= 0)
{
s->captures[capturing].length = res - pos;
}
return next ? next->test(s, res) : res;
}
}
return -1;
}
virtual int test_parent(nrex_search* s, int pos) const
{
if (capturing >= 0)
{
s->captures[capturing].length = pos - s->captures[capturing].start;
}
return nrex_node::test_parent(s, pos);
}
void add_childset()
{
back = NULL;
}
void add_child(nrex_node* node)
{
node->parent = this;
node->previous = back;
if (back)
{
back->next = node;
}
else
{
childset.push(node);
}
back = node;
}
nrex_node* swap_back(nrex_node* node)
{
if (!back)
{
add_child(node);
return NULL;
}
nrex_node* old = back;
if (!old->previous)
{
childset.pop();
}
back = old->previous;
add_child(node);
return old;
}
};
struct nrex_node_char : public nrex_node
{
nrex_char ch;
nrex_node_char(nrex_char c)
: nrex_node(true)
, ch(c)
{
}
int test(nrex_search* s, int pos) const
{
if (s->end == pos || s->at(pos) != ch)
{
return -1;
}
return next ? next->test(s, pos + 1) : pos + 1;
}
};
struct nrex_node_range : public nrex_node
{
nrex_char start;
nrex_char end;
nrex_node_range(nrex_char s, nrex_char e)
: nrex_node(true)
, start(s)
, end(e)
{
}
int test(nrex_search* s, int pos) const
{
if (s->end == pos)
{
return -1;
}
nrex_char c = s->at(pos);
if (c < start || end < c)
{
return -1;
}
return next ? next->test(s, pos + 1) : pos + 1;
}
};
static bool nrex_is_whitespace(nrex_char repr)
{
switch (repr)
{
case ' ':
case '\t':
case '\r':
case '\n':
case '\f':
return true;
}
return false;
}
static bool nrex_is_shorthand(nrex_char repr)
{
switch (repr)
{
case 'W':
case 'w':
case 'D':
case 'd':
case 'S':
case 's':
return true;
}
return false;
}
struct nrex_node_shorthand : public nrex_node
{
nrex_char repr;
nrex_node_shorthand(nrex_char c)
: nrex_node(true)
, repr(c)
{
}
int test(nrex_search* s, int pos) const
{
if (s->end == pos)
{
return -1;
}
bool found = false;
bool invert = false;
nrex_char c = s->at(pos);
switch (repr)
{
case '.':
found = true;
break;
case 'W':
invert = true;
case 'w':
if (c == '_' || NREX_ISALPHANUM(c))
{
found = true;
}
break;
case 'D':
invert = true;
case 'd':
if ('0' <= c && c <= '9')
{
found = true;
}
break;
case 'S':
invert = true;
case 's':
if (nrex_is_whitespace(c))
{
found = true;
}
break;
}
if (found == invert)
{
return -1;
}
return next ? next->test(s, pos + 1) : pos + 1;
}
};
static bool nrex_is_quantifier(nrex_char repr)
{
switch (repr)
{
case '?':
case '*':
case '+':
case '{':
return true;
}
return false;
}
struct nrex_node_quantifier : public nrex_node
{
int min;
int max;
bool greedy;
nrex_node* child;
nrex_node_quantifier()
: nrex_node()
, min(0)
, max(0)
, greedy(true)
, child(NULL)
{
}
virtual ~nrex_node_quantifier()
{
if (child)
{
NREX_DELETE(child);
}
}
int test(nrex_search* s, int pos) const
{
nrex_array<int> backtrack;
backtrack.push(pos);
while (backtrack.top() <= s->end)
{
if (max >= 1 && backtrack.size() > (unsigned int)max)
{
break;
}
if (!greedy && (unsigned int)min < backtrack.size())
{
int res = backtrack.top();
if (next)
{
res = next->test(s, res);
}
if (s->complete)
{
return res;
}
if (res >= 0 && parent->test_parent(s, res) >= 0)
{
return res;
}
}
int res = child->test(s, backtrack.top());
if (s->complete)
{
return res;
}
if (res < 0 || res == backtrack.top())
{
break;
}
backtrack.push(res);
}
while (greedy && (unsigned int) min < backtrack.size())
{
int res = backtrack.top();
if (next)
{
res = next->test(s, res);
}
if (res >= 0 && parent->test_parent(s, res) >= 0)
{
return res;
}
if (s->complete)
{
return res;
}
backtrack.pop();
}
return -1;
}
};
struct nrex_node_anchor : public nrex_node
{
bool end;
nrex_node_anchor(bool end)
: nrex_node()
, end(end)
{
}
int test(nrex_search* s, int pos) const
{
if (!end && pos != 0)
{
return -1;
}
else if (end && pos != s->end)
{
return -1;
}
return next ? next->test(s, pos) : pos;
}
};
struct nrex_node_backreference : public nrex_node
{
int ref;
nrex_node_backreference(int ref)
: nrex_node(true)
, ref(ref)
{
}
int test(nrex_search* s, int pos) const
{
nrex_result& r = s->captures[ref];
for (int i = 0; i < r.length; ++i)
{
if (pos + i >= s->end)
{
return -1;
}
if (s->at(r.start + i) != s->at(pos + i))
{
return -1;
}
}
return next ? next->test(s, pos + r.length) : pos + r.length;
}
};
nrex::nrex()
: _capturing(0)
, _root(NULL)
{
}
nrex::~nrex()
{
if (_root)
{
NREX_DELETE(_root);
}
}
bool nrex::valid() const
{
return (_root != NULL);
}
void nrex::reset()
{
_capturing = 0;
if (_root)
{
NREX_DELETE(_root);
}
_root = NULL;
}
int nrex::capture_size() const
{
return _capturing + 1;
}
bool nrex::compile(const nrex_char* pattern)
{
reset();
nrex_node_group* root = NREX_NEW(nrex_node_group(_capturing));
nrex_array<nrex_node_group*> stack;
stack.push(root);
_root = root;
for (const nrex_char* c = pattern; c[0] != '\0'; ++c)
{
if (c[0] == '(')
{
if (c[1] == '?')
{
if (c[2] == ':')
{
c = &c[2];
nrex_node_group* group = NREX_NEW(nrex_node_group(-1));
stack.top()->add_child(group);
stack.push(group);
}
else
{
NREX_COMPILE_ERROR("unrecognised qualifier for parenthesis");
}
}
else if (_capturing < 99)
{
nrex_node_group* group = NREX_NEW(nrex_node_group(++_capturing));
stack.top()->add_child(group);
stack.push(group);
}
else
{
nrex_node_group* group = NREX_NEW(nrex_node_group(-1));
stack.top()->add_child(group);
stack.push(group);
}
}
else if (c[0] == ')')
{
if (stack.size() > 1)
{
stack.pop();
}
else
{
NREX_COMPILE_ERROR("unexpected ')'");
}
}
else if (c[0] == '[')
{
nrex_node_group* group = NREX_NEW(nrex_node_group(-1));
stack.top()->add_child(group);
if (c[1] == '^')
{
group->negate = true;
++c;
}
while (true)
{
group->add_childset();
++c;
if (c[0] == '\0')
{
NREX_COMPILE_ERROR("unclosed character class '[]'");
}
if (c[0] == ']')
{
break;
}
else if (c[0] == '\\')
{
nrex_char unescaped = nrex_unescape(c[1]);
if (unescaped)
{
group->add_child(NREX_NEW(nrex_node_char(unescaped)));
++c;
}
else if (nrex_is_shorthand(c[1]))
{
group->add_child(NREX_NEW(nrex_node_shorthand(c[1])));
++c;
}
else
{
NREX_COMPILE_ERROR("escape token not recognised");
}
}
else
{
if (c[1] == '-' && c[2] != '\0')
{
bool range = false;
if ('A' <= c[0] && c[0] <= 'Z' && 'A' <= c[2] && c[2] <= 'Z')
{
range = true;
}
if ('a' <= c[0] && c[0] <= 'z' && 'a' <= c[2] && c[2] <= 'z')
{
range = true;
}
if ('0' <= c[0] && c[0] <= '9' && '0' <= c[2] && c[2] <= '9')
{
range = true;
}
if (range)
{
group->add_child(NREX_NEW(nrex_node_range(c[0], c[2])));
c = &c[2];
continue;
}
}
group->add_child(NREX_NEW(nrex_node_char(c[0])));
}
}
}
else if (nrex_is_quantifier(c[0]))
{
nrex_node_quantifier* quant = NREX_NEW(nrex_node_quantifier);
quant->child = stack.top()->swap_back(quant);
if (quant->child == NULL || !quant->child->quantifiable)
{
NREX_COMPILE_ERROR("element not quantifiable");
}
quant->child->previous = NULL;
quant->child->next = NULL;
quant->child->parent = quant;
if (c[0] == '?')
{
quant->min = 0;
quant->max = 1;
}
else if (c[0] == '+')
{
quant->min = 1;
quant->max = -1;
}
else if (c[0] == '*')
{
quant->min = 0;
quant->max = -1;
}
else if (c[0] == '{')
{
bool max_set = false;
quant->min = 0;
quant->max = -1;
while (true)
{
++c;
if (c[0] == '\0')
{
NREX_COMPILE_ERROR("unclosed range quantifier '{}'");
}
else if (c[0] == '}')
{
break;
}
else if (c[0] == ',')
{
max_set = true;
continue;
}
else if (c[0] < '0' || '9' < c[0])
{
NREX_COMPILE_ERROR("expected numeric digits, ',' or '}'");
}
if (max_set)
{
if (quant->max < 0)
{
quant->max = int(c[0] - '0');
}
else
{
quant->max = quant->max * 10 + int(c[0] - '0');
}
}
else
{
quant->min = quant->min * 10 + int(c[0] - '0');
}
}
if (!max_set)
{
quant->max = quant->min;
}
}
if (c[1] == '?')
{
quant->greedy = false;
++c;
}
}
else if (c[0] == '|')
{
stack.top()->add_childset();
}
else if (c[0] == '^' || c[0] == '$')
{
stack.top()->add_child(NREX_NEW(nrex_node_anchor((c[0] == '$'))));
}
else if (c[0] == '.')
{
stack.top()->add_child(NREX_NEW(nrex_node_shorthand('.')));
}
else if (c[0] == '\\')
{
nrex_char unescaped = nrex_unescape(c[1]);
if (unescaped)
{
stack.top()->add_child(NREX_NEW(nrex_node_char(unescaped)));
++c;
}
else if (nrex_is_shorthand(c[1]))
{
stack.top()->add_child(NREX_NEW(nrex_node_shorthand(c[1])));
++c;
}
else if ('1' <= c[1] && c[1] <= '9')
{
int ref = 0;
if ('0' <= c[2] && c[2] <= '9')
{
ref = int(c[1] - '0') * 10 + int(c[2] - '0');
c = &c[2];
}
else
{
ref = int(c[1] - '0');
++c;
}
if (ref > _capturing)
{
NREX_COMPILE_ERROR("backreference to non-existent capture");
}
stack.top()->add_child(NREX_NEW(nrex_node_backreference(ref)));
}
else
{
NREX_COMPILE_ERROR("escape token not recognised");
}
}
else
{
stack.top()->add_child(NREX_NEW(nrex_node_char(c[0])));
}
}
return true;
}
bool nrex::match(const nrex_char* str, nrex_result* captures, int offset, int end) const
{
nrex_search s(str, captures);
if (end >= offset)
{
s.end = end;
}
else
{
s.end = NREX_STRLEN(str);
}
for (int i = offset; i < s.end; ++i)
{
for (int c = 0; c <= _capturing; ++c)
{
captures[c].start = 0;
captures[c].length = 0;
}
if (_root->test(&s, i) >= 0)
{
return true;
}
}
return false;
}

144
drivers/nrex/nrex.hpp Normal file
View File

@ -0,0 +1,144 @@
// NREX: Node RegEx
//
// Copyright (c) 2015, Zher Huei Lee
// All rights reserved.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
#ifndef NREX_HPP
#define NREX_HPP
#include "nrex_config.h"
#ifdef NREX_UNICODE
typedef wchar_t nrex_char;
#else
typedef char nrex_char;
#endif
/*!
* \brief Struct to contain the range of a capture result
*
* The range provided is relative to the begining of the searched string.
*
* \see nrex_node::match()
*/
struct nrex_result
{
public:
int start; /*!< Start of text range */
int length; /*!< Length of text range */
};
class nrex_node;
/*!
* \brief Holds the compiled regex pattern
*/
class nrex
{
private:
int _capturing;
nrex_node* _root;
public:
nrex();
~nrex();
/*!
* \brief Removes the compiled regex and frees up the memory
*/
void reset();
/*!
* \brief Checks if there is a compiled regex being stored
* \return True if present, False if not present
*/
bool valid() const;
/*!
* \brief Provides number of captures the compiled regex uses
*
* This is used to provide the array size of the captures needed for
* nrex::match() to work. The size is actually the number of capture
* groups + one for the matching of the entire pattern. The result is
* always capped at 100.
*
* \return The number of captures
*/
int capture_size() const;
/*!
* \brief Compiles the provided regex pattern
*
* This automatically removes the existing compiled regex if already
* present.
*
* If the NREX_THROW_ERROR was defined it would automatically throw a
* runtime error nrex_compile_error if it encounters a problem when
* parsing the pattern.
*
* \param The regex pattern
* \return True if the pattern was succesfully compiled
*/
bool compile(const nrex_char* pattern);
/*!
* \brief Uses the pattern to search through the provided string
* \param str The text to search through. It only needs to be
* null terminated if the end point is not provided.
* This also determines the starting anchor.
* \param captures The array of results to store the capture results.
* The size of that array needs to be the same as the
* size given in nrex::capture_size(). As it matches
* the function fills the array with the results. 0 is
* the result for the entire pattern, 1 and above
* corresponds to the regex capture group if present.
* \param offset The starting point of the search. This does not move
* the starting anchor. Defaults to 0.
* \param end The end point of the search. This also determines
* the ending anchor. If a number less than the offset
* is provided, the search would be done until null
* termination. Defaults to -1.
* \return True if a match was found. False otherwise.
*/
bool match(const nrex_char* str, nrex_result* captures, int offset = 0, int end = -1) const;
};
#ifdef NREX_THROW_ERROR
#include <stdexcept>
class nrex_compile_error : std::runtime_error
{
public:
nrex_compile_error(const char* message)
: std::runtime_error(message)
{
}
~nrex_compile_error() throw()
{
}
};
#endif
#endif // NREX_HPP

View File

@ -0,0 +1,12 @@
// Godot-specific configuration
// To use this, replace nrex_config.h
#include "core/os/memory.h"
#define NREX_UNICODE
//#define NREX_THROW_ERROR
#define NREX_NEW(X) memnew(X)
#define NREX_NEW_ARRAY(X, N) memnew_arr(X, N)
#define NREX_DELETE(X) memdelete(X)
#define NREX_DELETE_ARRAY(X) memdelete_arr(X)

114
drivers/nrex/regex.cpp Normal file
View File

@ -0,0 +1,114 @@
/*************************************************/
/* regex.cpp */
/*************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
#include "regex.h"
#include "nrex.hpp"
#include "core/os/memory.h"
void RegEx::_bind_methods() {
ObjectTypeDB::bind_method(_MD("compile","pattern"),&RegEx::compile);
ObjectTypeDB::bind_method(_MD("find","text","start","end"),&RegEx::find, DEFVAL(0), DEFVAL(-1));
ObjectTypeDB::bind_method(_MD("clear"),&RegEx::clear);
ObjectTypeDB::bind_method(_MD("is_valid"),&RegEx::is_valid);
ObjectTypeDB::bind_method(_MD("get_capture_count"),&RegEx::get_capture_count);
ObjectTypeDB::bind_method(_MD("get_capture","capture"),&RegEx::get_capture);
ObjectTypeDB::bind_method(_MD("get_captures"),&RegEx::_bind_get_captures);
};
StringArray RegEx::_bind_get_captures() const {
StringArray ret;
int count = get_capture_count();
for (int i=0; i<count; i++) {
String c = get_capture(i);
ret.push_back(c);
};
return ret;
};
void RegEx::clear() {
text.clear();
captures.clear();
exp.reset();
};
bool RegEx::is_valid() const {
return exp.valid();
};
int RegEx::get_capture_count() const {
return exp.capture_size();
}
String RegEx::get_capture(int capture) const {
ERR_FAIL_COND_V( get_capture_count() <= capture, String() );
return text.substr(captures[capture].start, captures[capture].length);
}
Error RegEx::compile(const String& p_pattern) {
clear();
exp.compile(p_pattern.c_str());
ERR_FAIL_COND_V( !exp.valid(), FAILED );
captures.resize(exp.capture_size());
return OK;
};
int RegEx::find(const String& p_text, int p_start, int p_end) const {
ERR_FAIL_COND_V( !exp.valid(), -1 );
ERR_FAIL_COND_V( p_text.length() < p_start, -1 );
ERR_FAIL_COND_V( p_text.length() < p_end, -1 );
bool res = exp.match(p_text.c_str(), &captures[0], p_start, p_end);
if (res) {
text = p_text;
return captures[0].start;
}
text.clear();
return -1;
};
RegEx::RegEx(const String& p_pattern) {
compile(p_pattern);
};
RegEx::RegEx() {
};
RegEx::~RegEx() {
clear();
};

View File

@ -13,34 +13,31 @@
#define REGEX_H
#include "ustring.h"
#include "list.h"
#include "vector.h"
#include "core/reference.h"
struct TRex;
#include "nrex.hpp"
class RegEx : public Reference {
OBJ_TYPE(RegEx, Reference);
mutable String text;
TRex *exp;
mutable Vector<nrex_result> captures;
nrex exp;
protected:
static void _bind_methods();
int _bind_find(const String& p_text, int p_start = 0, int p_end = -1) const;
StringArray _bind_get_captures() const;
public:
void clear();
Error compile(const String& p_pattern);
bool is_valid() const;
bool match(const String& p_text, List<String>* p_captures = NULL, int p_start = 0, int p_end = -1) const;
bool find(const String& p_text, int& p_rstart, int &p_rend, List<String>* p_captures = NULL, int p_start = 0, int p_end = -1) const;
int get_capture_count() const;
Error get_capture_limits(int p_capture, int& p_start, int& p_len) const;
String get_capture(int p_idx) const;
String get_capture(int capture) const;
Error compile(const String& p_pattern);
int find(const String& p_text, int p_start = 0, int p_end = -1) const;
RegEx();
RegEx(const String& p_pattern);

View File

@ -27,7 +27,10 @@ if ("neon_enabled" in env and env["neon_enabled"]):
if "S_compiler" in env:
env_neon['CC'] = env['S_compiler']
env_neon.Append(CPPFLAGS=["-DPNG_ARM_NEON"])
png_sources.append(env_neon.Object("#drivers/png/filter_neon.S"))
import os
# Currently .ASM filter_neon.S does not compile on NT.
if (os.name!="nt"):
png_sources.append(env_neon.Object("#drivers/png/filter_neon.S"))
env.drivers_sources+=png_sources

View File

@ -48,7 +48,7 @@
#endif
#include "drivers/trex/regex.h"
#include "drivers/nrex/regex.h"
#ifdef MUSEPACK_ENABLED
#include "mpc/audio_stream_mpc.h"

View File

@ -21,7 +21,7 @@ void AudioStreamSpeex::update() {
//printf("update, loops %i, read ofs %i\n", (int)loops, read_ofs);
//printf("playing %i, paused %i\n", (int)playing, (int)paused);
if (!playing || paused || !data.size())
if (!active || !playing || paused || !data.size())
return;
/*

View File

@ -1,75 +0,0 @@
#ifndef _TREXPP_H_
#define _TREXPP_H_
/***************************************************************
T-Rex a tiny regular expression library
Copyright (C) 2003-2004 Alberto Demichelis
This software is provided 'as-is', without any express
or implied warranty. In no event will the authors be held
liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for
any purpose, including commercial applications, and to alter
it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented;
you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment
in the product documentation would be appreciated but
is not required.
2. Altered source versions must be plainly marked as such,
and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any
source distribution.
****************************************************************/
extern "C" {
#include "trex.h"
}
struct TRexParseException{TRexParseException(const TRexChar *c):desc(c){}const TRexChar *desc;};
class TRexpp {
public:
TRexpp() { _exp = (TRex *)0; }
~TRexpp() { CleanUp(); }
// compiles a regular expression
void Compile(const TRexChar *pattern) {
const TRexChar *error;
CleanUp();
if(!(_exp = trex_compile(pattern,&error)))
throw TRexParseException(error);
}
// return true if the given text match the expression
bool Match(const TRexChar* text) {
return _exp?(trex_match(_exp,text) != 0):false;
}
// Searches for the first match of the expression in a zero terminated string
bool Search(const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end) {
return _exp?(trex_search(_exp,text,out_begin,out_end) != 0):false;
}
// Searches for the first match of the expression in a string sarting at text_begin and ending at text_end
bool SearchRange(const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end) {
return _exp?(trex_searchrange(_exp,text_begin,text_end,out_begin,out_end) != 0):false;
}
bool GetSubExp(int n, const TRexChar** out_begin, int *out_len)
{
TRexMatch match;
TRexBool res = _exp?(trex_getsubexp(_exp,n,&match)):TRex_False;
if(res) {
*out_begin = match.begin;
*out_len = match.len;
return true;
}
return false;
}
int GetSubExpCount() { return _exp?trex_getsubexpcount(_exp):0; }
private:
void CleanUp() { if(_exp) trex_free(_exp); _exp = (TRex *)0; }
TRex *_exp;
};
#endif //_TREXPP_H_

View File

@ -1,15 +0,0 @@
===version 1.3
-fixed a bug for GCC users(thx Brendan)
===version 1.2
-added word boundary match \b and \B
-added vertical tab escape \v
-\w now also matches '_' (underscore)
-fixed greediness for * and +
===version 1.1 , April 1, 2004
-fixed some minor bug
-added predefined character classes(\w,\W,\s,\S etc...)
===version 1.0 , February 23, 2004
-first public realase

View File

@ -1,171 +0,0 @@
T-REX 1.3 http://tiny-rex.sourceforge.net
----------------------------------------------------------------------
T-Rex a tiny regular expression library
Copyright (C) 2003-2006 Alberto Demichelis
This software is provided 'as-is', without any express
or implied warranty. In no event will the authors be held
liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for
any purpose, including commercial applications, and to alter
it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented;
you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment
in the product documentation would be appreciated but
is not required.
2. Altered source versions must be plainly marked as such,
and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any
source distribution.
----------------------------------------------------------------------
TRex implements the following expressions
\ Quote the next metacharacter
^ Match the beginning of the string
. Match any character
$ Match the end of the string
| Alternation
() Grouping (creates a capture)
[] Character class
==GREEDY CLOSURES==
* Match 0 or more times
+ Match 1 or more times
? Match 1 or 0 times
{n} Match exactly n times
{n,} Match at least n times
{n,m} Match at least n but not more than m times
==ESCAPE CHARACTERS==
\t tab (HT, TAB)
\n newline (LF, NL)
\r return (CR)
\f form feed (FF)
==PREDEFINED CLASSES==
\l lowercase next char
\u uppercase next char
\a letters
\A non letters
\w alphanimeric [0-9a-zA-Z]
\W non alphanimeric
\s space
\S non space
\d digits
\D non nondigits
\x exadecimal digits
\X non exadecimal digits
\c control charactrs
\C non control charactrs
\p punctation
\P non punctation
\b word boundary
\B non word boundary
----------------------------------------------------------------------
API DOC
----------------------------------------------------------------------
TRex *trex_compile(const TRexChar *pattern,const TRexChar **error);
compiles an expression and returns a pointer to the compiled version.
in case of failure returns NULL.The returned object has to be deleted
through the function trex_free().
pattern
a pointer to a zero terminated string containing the pattern that
has to be compiled.
error
apointer to a string pointer that will be set with an error string
in case of failure.
----------------------------------------------------------------------
void trex_free(TRex *exp)
deletes a expression structure created with trex_compile()
exp
the expression structure that has to be deleted
----------------------------------------------------------------------
TRexBool trex_match(TRex* exp,const TRexChar* text)
returns TRex_True if the string specified in the parameter text is an
exact match of the expression, otherwise returns TRex_False.
exp
the compiled expression
text
the string that has to be tested
----------------------------------------------------------------------
TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end)
searches the first match of the expressin in the string specified in the parameter text.
if the match is found returns TRex_True and the sets out_begin to the beginning of the
match and out_end at the end of the match; otherwise returns TRex_False.
exp
the compiled expression
text
the string that has to be tested
out_begin
a pointer to a string pointer that will be set with the beginning of the match
out_end
a pointer to a string pointer that will be set with the end of the match
----------------------------------------------------------------------
TREX_API TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end)
searches the first match of the expressin in the string delimited
by the parameter text_begin and text_end.
if the match is found returns TRex_True and the sets out_begin to the beginning of the
match and out_end at the end of the match; otherwise returns TRex_False.
exp
the compiled expression
text_begin
a pointer to the beginnning of the string that has to be tested
text_end
a pointer to the end of the string that has to be tested
out_begin
a pointer to a string pointer that will be set with the beginning of the match
out_end
a pointer to a string pointer that will be set with the end of the match
----------------------------------------------------------------------
int trex_getsubexpcount(TRex* exp)
returns the number of sub expressions matched by the expression
exp
the compiled expression
---------------------------------------------------------------------
TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *submatch)
retrieve the begin and and pointer to the length of the sub expression indexed
by n. The result is passed trhough the struct TRexMatch:
typedef struct {
const TRexChar *begin;
int len;
} TRexMatch;
the function returns TRex_True if n is valid index otherwise TRex_False.
exp
the compiled expression
n
the index of the submatch
submatch
a pointer to structure that will store the result
this function works also after a match operation has been performend.

View File

@ -1,163 +0,0 @@
/*************************************************/
/* regex.cpp */
/*************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/*************************************************/
/* Source code within this file is: */
/* (c) 2007-2010 Juan Linietsky, Ariel Manzur */
/* All Rights Reserved. */
/*************************************************/
#include "regex.h"
extern "C" {
#define _UNICODE
#include "trex.h"
};
void RegEx::_bind_methods() {
ObjectTypeDB::bind_method(_MD("compile","pattern"),&RegEx::compile);
ObjectTypeDB::bind_method(_MD("find","text", "start","end"),&RegEx::_bind_find, DEFVAL(0), DEFVAL(-1));
ObjectTypeDB::bind_method(_MD("get_captures"),&RegEx::_bind_get_captures);
};
Error RegEx::compile(const String& p_pattern) {
clear();
const TRexChar* error;
exp = trex_compile(p_pattern.c_str(), &error);
ERR_FAIL_COND_V(!exp, FAILED);
return OK;
};
int RegEx::_bind_find(const String& p_text, int p_start, int p_end) const {
int start, end;
bool ret = find(p_text, start, end, NULL, p_start, p_end);
return ret?start:-1;
};
bool RegEx::find(const String& p_text, int& p_rstart, int &p_rend, List<String>* p_captures, int p_start, int p_end) const {
ERR_FAIL_COND_V( !exp, false );
text=p_text;
const CharType* str = p_text.c_str();
const CharType* start = str + p_start;
const CharType* end = str + (p_end == -1?p_text.size():p_end);
const CharType* out_begin;
const CharType* out_end;
bool ret = trex_searchrange(exp, start, end, &out_begin, &out_end);
if (ret) {
p_rstart = out_begin - str;
p_rend = out_end - str;
if (p_captures) {
int count = get_capture_count();
for (int i=0; i<count; i++) {
int start, len;
get_capture_limits(i, start, len);
p_captures->push_back(p_text.substr(start, len));
};
};
} else {
p_rstart = -1;
};
return ret;
};
bool RegEx::match(const String& p_text, List<String>* p_captures, int p_start, int p_end) const {
ERR_FAIL_COND_V( !exp, false );
int start, end;
return find(p_text, start, end, p_captures, p_start, p_end);
};
int RegEx::get_capture_count() const {
ERR_FAIL_COND_V( exp == NULL, -1 );
return trex_getsubexpcount(exp);
};
Error RegEx::get_capture_limits(int p_capture, int& p_start, int& p_len) const {
ERR_FAIL_COND_V( exp == NULL, ERR_UNCONFIGURED );
TRexMatch match;
TRexBool res = trex_getsubexp(exp, p_capture, &match);
ERR_FAIL_COND_V( !res, FAILED );
p_start = (int)(match.begin - text.c_str());
p_len = match.len;
return OK;
};
String RegEx::get_capture(int p_idx) const {
ERR_FAIL_COND_V( exp == NULL, "" );
int start, len;
Error ret = get_capture_limits(p_idx, start, len);
ERR_FAIL_COND_V(ret != OK, "");
if (len == 0)
return "";
return text.substr(start, len);
};
StringArray RegEx::_bind_get_captures() const {
StringArray ret;
int count = get_capture_count();
for (int i=0; i<count; i++) {
String c = get_capture(i);
ret.push_back(c);
};
return ret;
};
bool RegEx::is_valid() const {
return exp != NULL;
};
void RegEx::clear() {
if (exp) {
trex_free(exp);
exp = NULL;
};
};
RegEx::RegEx(const String& p_pattern) {
exp = NULL;
compile(p_pattern);
};
RegEx::RegEx() {
exp = NULL;
};
RegEx::~RegEx() {
clear();
};

View File

@ -1,41 +0,0 @@
#include "trex.h"
#include <stdio.h>
#include <string.h>
#ifdef _UNICODE
#define trex_sprintf swprintf
#else
#define trex_sprintf sprintf
#endif
int main(int argc, char* argv[])
{
const TRexChar *begin,*end;
TRexChar sTemp[200];
const TRexChar *error = NULL;
TRex *x = trex_compile(_TREXC("(x{1,5})xx"),&error);
if(x) {
trex_sprintf(sTemp,_TREXC("xxxxxxx"));
if(trex_search(x,sTemp,&begin,&end))
{
int i,n = trex_getsubexpcount(x);
TRexMatch match;
for(i = 0; i < n; i++)
{
TRexChar t[200];
trex_getsubexp(x,i,&match);
trex_sprintf(t,_TREXC("[%%d]%%.%ds\n"),match.len);
trex_printf(t,i,match.begin);
}
trex_printf(_TREXC("match! %d sub matches\n"),trex_getsubexpcount(x));
}
else {
trex_printf(_TREXC("no match!\n"));
}
trex_free(x);
}
else {
trex_printf(_TREXC("compilation error [%s]!\n"),error?error:_TREXC("undefined"));
}
return 0;
}

View File

@ -1,643 +0,0 @@
/* see copyright notice in trex.h */
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <setjmp.h>
#include "trex.h"
#ifdef _UINCODE
#define scisprint iswprint
#define scstrlen wcslen
#define scprintf wprintf
#define _SC(x) L##c
#else
#define scisprint isprint
#define scstrlen strlen
#define scprintf printf
#define _SC(x) (x)
#endif
#ifdef _DEBUG
#include <stdio.h>
static const TRexChar *g_nnames[] =
{
_SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"),
_SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"),
_SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"),
_SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB")
};
#endif
#define OP_GREEDY (MAX_CHAR+1) // * + ? {n}
#define OP_OR (MAX_CHAR+2)
#define OP_EXPR (MAX_CHAR+3) //parentesis ()
#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:)
#define OP_DOT (MAX_CHAR+5)
#define OP_CLASS (MAX_CHAR+6)
#define OP_CCLASS (MAX_CHAR+7)
#define OP_NCLASS (MAX_CHAR+8) //negates class the [^
#define OP_RANGE (MAX_CHAR+9)
#define OP_CHAR (MAX_CHAR+10)
#define OP_EOL (MAX_CHAR+11)
#define OP_BOL (MAX_CHAR+12)
#define OP_WB (MAX_CHAR+13)
#define TREX_SYMBOL_ANY_CHAR ('.')
#define TREX_SYMBOL_GREEDY_ONE_OR_MORE ('+')
#define TREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*')
#define TREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?')
#define TREX_SYMBOL_BRANCH ('|')
#define TREX_SYMBOL_END_OF_STRING ('$')
#define TREX_SYMBOL_BEGINNING_OF_STRING ('^')
#define TREX_SYMBOL_ESCAPE_CHAR ('\\')
typedef int TRexNodeType;
typedef struct tagTRexNode{
TRexNodeType type;
int left;
int right;
int next;
}TRexNode;
struct TRex{
const TRexChar *_eol;
const TRexChar *_bol;
const TRexChar *_p;
int _first;
int _op;
TRexNode *_nodes;
int _nallocated;
int _nsize;
int _nsubexpr;
TRexMatch *_matches;
int _currsubexp;
void *_jmpbuf;
const TRexChar **_error;
};
static int trex_list(TRex *exp);
static int trex_newnode(TRex *exp, TRexNodeType type)
{
TRexNode n;
int newid;
n.type = type;
n.next = n.right = n.left = -1;
if(type == OP_EXPR)
n.right = exp->_nsubexpr++;
if(exp->_nallocated < (exp->_nsize + 1)) {
//int oldsize = exp->_nallocated;
exp->_nallocated *= 2;
exp->_nodes = (TRexNode *)realloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode));
}
exp->_nodes[exp->_nsize++] = n;
newid = exp->_nsize - 1;
return (int)newid;
}
static void trex_error(TRex *exp,const TRexChar *error)
{
if(exp->_error) *exp->_error = error;
longjmp(*((jmp_buf*)exp->_jmpbuf),-1);
}
static void trex_expect(TRex *exp, int n){
if((*exp->_p) != n)
trex_error(exp, _SC("expected paren"));
exp->_p++;
}
static TRexChar trex_escapechar(TRex *exp)
{
if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR){
exp->_p++;
switch(*exp->_p) {
case 'v': exp->_p++; return '\v';
case 'n': exp->_p++; return '\n';
case 't': exp->_p++; return '\t';
case 'r': exp->_p++; return '\r';
case 'f': exp->_p++; return '\f';
default: return (*exp->_p++);
}
} else if(!scisprint(*exp->_p)) trex_error(exp,_SC("letter expected"));
return (*exp->_p++);
}
static int trex_charclass(TRex *exp,int classid)
{
int n = trex_newnode(exp,OP_CCLASS);
exp->_nodes[n].left = classid;
return n;
}
static int trex_charnode(TRex *exp,TRexBool isclass)
{
TRexChar t;
if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) {
exp->_p++;
switch(*exp->_p) {
case 'n': exp->_p++; return trex_newnode(exp,'\n');
case 't': exp->_p++; return trex_newnode(exp,'\t');
case 'r': exp->_p++; return trex_newnode(exp,'\r');
case 'f': exp->_p++; return trex_newnode(exp,'\f');
case 'v': exp->_p++; return trex_newnode(exp,'\v');
case 'a': case 'A': case 'w': case 'W': case 's': case 'S':
case 'd': case 'D': case 'x': case 'X': case 'c': case 'C':
case 'p': case 'P': case 'l': case 'u':
{
t = *exp->_p; exp->_p++;
return trex_charclass(exp,t);
}
case 'b':
case 'B':
if(!isclass) {
int node = trex_newnode(exp,OP_WB);
exp->_nodes[node].left = *exp->_p;
exp->_p++;
return node;
} //else default
default:
t = *exp->_p; exp->_p++;
return trex_newnode(exp,t);
}
}
else if(!scisprint(*exp->_p)) {
trex_error(exp,_SC("letter expected"));
}
t = *exp->_p; exp->_p++;
return trex_newnode(exp,t);
}
static int trex_class(TRex *exp)
{
int ret = -1;
int first = -1,chain;
if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING){
ret = trex_newnode(exp,OP_NCLASS);
exp->_p++;
}else ret = trex_newnode(exp,OP_CLASS);
if(*exp->_p == ']') trex_error(exp,_SC("empty class"));
chain = ret;
while(*exp->_p != ']' && exp->_p != exp->_eol) {
if(*exp->_p == '-' && first != -1){
int r,t;
if(*exp->_p++ == ']') trex_error(exp,_SC("unfinished range"));
r = trex_newnode(exp,OP_RANGE);
if(first>*exp->_p) trex_error(exp,_SC("invalid range"));
if(exp->_nodes[first].type == OP_CCLASS) trex_error(exp,_SC("cannot use character classes in ranges"));
exp->_nodes[r].left = exp->_nodes[first].type;
t = trex_escapechar(exp);
exp->_nodes[r].right = t;
exp->_nodes[chain].next = r;
chain = r;
first = -1;
}
else{
if(first!=-1){
int c = first;
exp->_nodes[chain].next = c;
chain = c;
first = trex_charnode(exp,TRex_True);
}
else{
first = trex_charnode(exp,TRex_True);
}
}
}
if(first!=-1){
int c = first;
exp->_nodes[chain].next = c;
chain = c;
first = -1;
}
/* hack? */
exp->_nodes[ret].left = exp->_nodes[ret].next;
exp->_nodes[ret].next = -1;
return ret;
}
static int trex_parsenumber(TRex *exp)
{
int ret = *exp->_p-'0';
int positions = 10;
exp->_p++;
while(isdigit(*exp->_p)) {
ret = ret*10+(*exp->_p++-'0');
if(positions==1000000000) trex_error(exp,_SC("overflow in numeric constant"));
positions *= 10;
};
return ret;
}
static int trex_element(TRex *exp)
{
int ret = -1;
switch(*exp->_p)
{
case '(': {
int expr,newn;
exp->_p++;
if(*exp->_p =='?') {
exp->_p++;
trex_expect(exp,':');
expr = trex_newnode(exp,OP_NOCAPEXPR);
}
else
expr = trex_newnode(exp,OP_EXPR);
newn = trex_list(exp);
exp->_nodes[expr].left = newn;
ret = expr;
trex_expect(exp,')');
}
break;
case '[':
exp->_p++;
ret = trex_class(exp);
trex_expect(exp,']');
break;
case TREX_SYMBOL_END_OF_STRING: exp->_p++; ret = trex_newnode(exp,OP_EOL);break;
case TREX_SYMBOL_ANY_CHAR: exp->_p++; ret = trex_newnode(exp,OP_DOT);break;
default:
ret = trex_charnode(exp,TRex_False);
break;
}
{
int op;
TRexBool isgreedy = TRex_False;
unsigned short p0 = 0, p1 = 0;
switch(*exp->_p){
case TREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break;
case TREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break;
case TREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = TRex_True; break;
case '{':
exp->_p++;
if(!isdigit(*exp->_p)) trex_error(exp,_SC("number expected"));
p0 = (unsigned short)trex_parsenumber(exp);
/*******************************/
switch(*exp->_p) {
case '}':
p1 = p0; exp->_p++;
break;
case ',':
exp->_p++;
p1 = 0xFFFF;
if(isdigit(*exp->_p)){
p1 = (unsigned short)trex_parsenumber(exp);
}
trex_expect(exp,'}');
break;
default:
trex_error(exp,_SC(", or } expected"));
}
/*******************************/
isgreedy = TRex_True;
break;
}
if(isgreedy) {
int nnode = trex_newnode(exp,OP_GREEDY);
op = OP_GREEDY;
exp->_nodes[nnode].left = ret;
exp->_nodes[nnode].right = ((p0)<<16)|p1;
ret = nnode;
}
}
if((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) {
int nnode = trex_element(exp);
exp->_nodes[ret].next = nnode;
}
return ret;
}
static int trex_list(TRex *exp)
{
int ret=-1,e;
if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) {
exp->_p++;
ret = trex_newnode(exp,OP_BOL);
}
e = trex_element(exp);
if(ret != -1) {
exp->_nodes[ret].next = e;
}
else ret = e;
if(*exp->_p == TREX_SYMBOL_BRANCH) {
int temp,tright;
exp->_p++;
temp = trex_newnode(exp,OP_OR);
exp->_nodes[temp].left = ret;
tright = trex_list(exp);
exp->_nodes[temp].right = tright;
ret = temp;
}
return ret;
}
static TRexBool trex_matchcclass(int cclass,TRexChar c)
{
switch(cclass) {
case 'a': return isalpha(c)?TRex_True:TRex_False;
case 'A': return !isalpha(c)?TRex_True:TRex_False;
case 'w': return (isalnum(c) || c == '_')?TRex_True:TRex_False;
case 'W': return (!isalnum(c) && c != '_')?TRex_True:TRex_False;
case 's': return isspace(c)?TRex_True:TRex_False;
case 'S': return !isspace(c)?TRex_True:TRex_False;
case 'd': return isdigit(c)?TRex_True:TRex_False;
case 'D': return !isdigit(c)?TRex_True:TRex_False;
case 'x': return isxdigit(c)?TRex_True:TRex_False;
case 'X': return !isxdigit(c)?TRex_True:TRex_False;
case 'c': return iscntrl(c)?TRex_True:TRex_False;
case 'C': return !iscntrl(c)?TRex_True:TRex_False;
case 'p': return ispunct(c)?TRex_True:TRex_False;
case 'P': return !ispunct(c)?TRex_True:TRex_False;
case 'l': return islower(c)?TRex_True:TRex_False;
case 'u': return isupper(c)?TRex_True:TRex_False;
}
return TRex_False; /*cannot happen*/
}
static TRexBool trex_matchclass(TRex* exp,TRexNode *node,TRexChar c)
{
do {
switch(node->type) {
case OP_RANGE:
if(c >= node->left && c <= node->right) return TRex_True;
break;
case OP_CCLASS:
if(trex_matchcclass(node->left,c)) return TRex_True;
break;
default:
if(c == node->type)return TRex_True;
}
} while((node->next != -1) && (node = &exp->_nodes[node->next]));
return TRex_False;
}
static const TRexChar *trex_matchnode(TRex* exp,TRexNode *node,const TRexChar *str,TRexNode *next)
{
TRexNodeType type = node->type;
switch(type) {
case OP_GREEDY: {
//TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL;
TRexNode *greedystop = NULL;
int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;
const TRexChar *s=str, *good = str;
if(node->next != -1) {
greedystop = &exp->_nodes[node->next];
}
else {
greedystop = next;
}
while((nmaches == 0xFFFF || nmaches < p1)) {
const TRexChar *stop;
if(!(s = trex_matchnode(exp,&exp->_nodes[node->left],s,greedystop)))
break;
nmaches++;
good=s;
if(greedystop) {
//checks that 0 matches satisfy the expression(if so skips)
//if not would always stop(for instance if is a '?')
if(greedystop->type != OP_GREEDY ||
(greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0))
{
TRexNode *gnext = NULL;
if(greedystop->next != -1) {
gnext = &exp->_nodes[greedystop->next];
}else if(next && next->next != -1){
gnext = &exp->_nodes[next->next];
}
stop = trex_matchnode(exp,greedystop,s,gnext);
if(stop) {
//if satisfied stop it
if(p0 == p1 && p0 == nmaches) break;
else if(nmaches >= p0 && p1 == 0xFFFF) break;
else if(nmaches >= p0 && nmaches <= p1) break;
}
}
}
if(s >= exp->_eol)
break;
}
if(p0 == p1 && p0 == nmaches) return good;
else if(nmaches >= p0 && p1 == 0xFFFF) return good;
else if(nmaches >= p0 && nmaches <= p1) return good;
return NULL;
}
case OP_OR: {
const TRexChar *asd = str;
TRexNode *temp=&exp->_nodes[node->left];
while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) {
if(temp->next != -1)
temp = &exp->_nodes[temp->next];
else
return asd;
}
asd = str;
temp = &exp->_nodes[node->right];
while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) {
if(temp->next != -1)
temp = &exp->_nodes[temp->next];
else
return asd;
}
return NULL;
break;
}
case OP_EXPR:
case OP_NOCAPEXPR:{
TRexNode *n = &exp->_nodes[node->left];
const TRexChar *cur = str;
int capture = -1;
if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {
capture = exp->_currsubexp;
exp->_matches[capture].begin = cur;
exp->_currsubexp++;
}
do {
TRexNode *subnext = NULL;
if(n->next != -1) {
subnext = &exp->_nodes[n->next];
}else {
subnext = next;
}
if(!(cur = trex_matchnode(exp,n,cur,subnext))) {
if(capture != -1){
exp->_matches[capture].begin = 0;
exp->_matches[capture].len = 0;
}
return NULL;
}
} while((n->next != -1) && (n = &exp->_nodes[n->next]));
if(capture != -1)
exp->_matches[capture].len = cur - exp->_matches[capture].begin;
return cur;
}
case OP_WB:
if((str == exp->_bol && !isspace(*str))
|| (str == exp->_eol && !isspace(*(str-1)))
|| (!isspace(*str) && isspace(*(str+1)))
|| (isspace(*str) && !isspace(*(str+1))) ) {
return (node->left == 'b')?str:NULL;
}
return (node->left == 'b')?NULL:str;
case OP_BOL:
if(str == exp->_bol) return str;
return NULL;
case OP_EOL:
if(str == exp->_eol) return str;
return NULL;
case OP_DOT:{
*str++;
}
return str;
case OP_NCLASS:
case OP_CLASS:
if(trex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?TRex_True:TRex_False):(type == OP_NCLASS?TRex_True:TRex_False)) {
*str++;
return str;
}
return NULL;
case OP_CCLASS:
if(trex_matchcclass(node->left,*str)) {
*str++;
return str;
}
return NULL;
default: /* char */
if(*str != node->type) return NULL;
*str++;
return str;
}
return NULL;
}
/* public api */
TRex *trex_compile(const TRexChar *pattern,const TRexChar **error)
{
TRex *exp = (TRex *)malloc(sizeof(TRex));
exp->_eol = exp->_bol = NULL;
exp->_p = pattern;
exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar);
exp->_nodes = (TRexNode *)malloc(exp->_nallocated * sizeof(TRexNode));
exp->_nsize = 0;
exp->_matches = 0;
exp->_nsubexpr = 0;
exp->_first = trex_newnode(exp,OP_EXPR);
exp->_error = error;
exp->_jmpbuf = malloc(sizeof(jmp_buf));
if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) {
int res = trex_list(exp);
exp->_nodes[exp->_first].left = res;
if(*exp->_p!='\0')
trex_error(exp,_SC("unexpected character"));
#ifdef _DEBUG
{
int nsize,i;
TRexNode *t;
nsize = exp->_nsize;
t = &exp->_nodes[0];
scprintf(_SC("\n"));
for(i = 0;i < nsize; i++) {
if(exp->_nodes[i].type>MAX_CHAR)
scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]);
else
scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type);
scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next);
}
scprintf(_SC("\n"));
}
#endif
exp->_matches = (TRexMatch *) malloc(exp->_nsubexpr * sizeof(TRexMatch));
memset(exp->_matches,0,exp->_nsubexpr * sizeof(TRexMatch));
}
else{
trex_free(exp);
return NULL;
}
return exp;
}
void trex_free(TRex *exp)
{
if(exp) {
if(exp->_nodes) free(exp->_nodes);
if(exp->_jmpbuf) free(exp->_jmpbuf);
if(exp->_matches) free(exp->_matches);
free(exp);
}
}
TRexBool trex_match(TRex* exp,const TRexChar* text)
{
const TRexChar* res = NULL;
exp->_bol = text;
exp->_eol = text + scstrlen(text);
exp->_currsubexp = 0;
res = trex_matchnode(exp,exp->_nodes,text,NULL);
if(res == NULL || res != exp->_eol)
return TRex_False;
return TRex_True;
}
TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end)
{
const TRexChar *cur = NULL;
int node = exp->_first;
if(text_begin >= text_end) return TRex_False;
exp->_bol = text_begin;
exp->_eol = text_end;
do {
cur = text_begin;
while(node != -1) {
exp->_currsubexp = 0;
cur = trex_matchnode(exp,&exp->_nodes[node],cur,NULL);
if(!cur)
break;
node = exp->_nodes[node].next;
}
*text_begin++;
} while(cur == NULL && text_begin != text_end);
if(cur == NULL)
return TRex_False;
--text_begin;
if(out_begin) *out_begin = text_begin;
if(out_end) *out_end = cur;
return TRex_True;
}
TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end)
{
return trex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end);
}
int trex_getsubexpcount(TRex* exp)
{
return exp->_nsubexpr;
}
TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp)
{
if( n<0 || n >= exp->_nsubexpr) return TRex_False;
*subexp = exp->_matches[n];
return TRex_True;
}

View File

@ -1,70 +0,0 @@
#ifndef _TREX_H_
#define _TREX_H_
/***************************************************************
T-Rex a tiny regular expression library
Copyright (C) 2003-2006 Alberto Demichelis
This software is provided 'as-is', without any express
or implied warranty. In no event will the authors be held
liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for
any purpose, including commercial applications, and to alter
it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented;
you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment
in the product documentation would be appreciated but
is not required.
2. Altered source versions must be plainly marked as such,
and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any
source distribution.
****************************************************************/
#define _UNICODE
#ifdef _UNICODE
#define TRexChar wchar_t
#define MAX_CHAR 0xFFFF
#define _TREXC(c) L##c
#define trex_strlen wcslen
#define trex_printf wprintf
#else
#define TRexChar char
#define MAX_CHAR 0xFF
#define _TREXC(c) (c)
#define trex_strlen strlen
#define trex_printf printf
#endif
#ifndef TREX_API
#define TREX_API extern
#endif
#define TRex_True 1
#define TRex_False 0
typedef unsigned int TRexBool;
typedef struct TRex TRex;
typedef struct {
const TRexChar *begin;
int len;
} TRexMatch;
TREX_API TRex *trex_compile(const TRexChar *pattern,const TRexChar **error);
TREX_API void trex_free(TRex *exp);
TREX_API TRexBool trex_match(TRex* exp,const TRexChar* text);
TREX_API TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end);
TREX_API TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end);
TREX_API int trex_getsubexpcount(TRex* exp);
TREX_API TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp);
#endif

View File

@ -57,8 +57,14 @@
#include <errno.h>
#include <assert.h>
#include "globals.h"
extern bool _print_error_enabled;
void OS_Unix::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) {
if (!_print_error_enabled)
return;
if (p_rationale && p_rationale[0]) {
print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
@ -217,6 +223,14 @@ uint64_t OS_Unix::get_unix_time() const {
return time(NULL);
};
uint64_t OS_Unix::get_system_time_msec() const {
struct timeval tv_now;
gettimeofday(&tv_now, NULL);
localtime(&tv_now.tv_usec);
uint64_t msec = tv_now.tv_usec/1000;
return msec;
}
OS::Date OS_Unix::get_date(bool utc) const {

View File

@ -93,6 +93,7 @@ public:
virtual TimeZoneInfo get_time_zone_info() const;
virtual uint64_t get_unix_time() const;
virtual uint64_t get_system_time_msec() const;
virtual void delay_usec(uint32_t p_usec) const;
virtual uint64_t get_ticks_usec() const;

View File

@ -232,7 +232,7 @@ void AudioStreamOGGVorbis::seek_pos(float p_time) {
if (!playing)
return;
bool ok = ov_time_seek(&vf,p_time*1000)==0;
bool ok = ov_time_seek(&vf,p_time)==0;
ERR_FAIL_COND(!ok);
frames_mixed=stream_srate*p_time;
}

View File

@ -518,14 +518,14 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
}
GLOBAL_DEF("debug/max_remote_stdout_chars_per_second",2048);
if (debug_mode == "remote") {
ScriptDebuggerRemote *sdr = memnew( ScriptDebuggerRemote );
uint16_t debug_port = GLOBAL_DEF("debug/remote_port",6007);
if (debug_host.find(":")!=-1) {
debug_port=debug_host.get_slice(":",1).to_int();
debug_host=debug_host.get_slice(":",0);
debug_port=debug_host.get_slicec(':',1).to_int();
debug_host=debug_host.get_slicec(':',0);
}
Error derr = sdr->connect_to_host(debug_host,debug_port);
@ -546,8 +546,8 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
file_access_network_client=memnew(FileAccessNetworkClient);
int port;
if (remotefs.find(":")!=-1) {
port=remotefs.get_slice(":",1).to_int();
remotefs=remotefs.get_slice(":",0);
port=remotefs.get_slicec(':',1).to_int();
remotefs=remotefs.get_slicec(':',0);
} else {
port=6010;
}
@ -605,6 +605,9 @@ Error Main::setup(const char *execpath,int argc, char *argv[],bool p_second_phas
if (bool(Globals::get_singleton()->get("application/disable_stdout"))) {
quiet_stdout=true;
}
if (bool(Globals::get_singleton()->get("application/disable_stderr"))) {
_print_error_enabled = false;
};
if (quiet_stdout)
_print_line_enabled=false;
@ -1219,7 +1222,7 @@ bool Main::start() {
String s = E->get().name;
if (!s.begins_with("autoload/"))
continue;
String name = s.get_slice("/",1);
String name = s.get_slicec('/',1);
String path = Globals::get_singleton()->get(s);
RES res = ResourceLoader::load(path);
ERR_EXPLAIN("Can't autoload: "+path);

View File

@ -29,6 +29,7 @@
#include "gd_script.h"
#include "gd_compiler.h"
#include "globals.h"
#include "os/file_access.h"
void GDScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const {
@ -238,26 +239,26 @@ void GDScriptLanguage::debug_get_stack_level_members(int p_level,List<String> *p
if (_debug_parse_err_line>=0)
return;
ERR_FAIL_INDEX(p_level,_debug_call_stack_pos);
int l = _debug_call_stack_pos - p_level -1;
ERR_FAIL_INDEX(p_level,_debug_call_stack_pos);
int l = _debug_call_stack_pos - p_level -1;
GDInstance *instance = _call_stack[l].instance;
GDInstance *instance = _call_stack[l].instance;
if (!instance)
return;
if (!instance)
return;
Ref<GDScript> script = instance->get_script();
ERR_FAIL_COND( script.is_null() );
Ref<GDScript> script = instance->get_script();
ERR_FAIL_COND( script.is_null() );
const Map<StringName,GDScript::MemberInfo>& mi = script->debug_get_member_indices();
const Map<StringName,GDScript::MemberInfo>& mi = script->debug_get_member_indices();
for(const Map<StringName,GDScript::MemberInfo>::Element *E=mi.front();E;E=E->next()) {
for(const Map<StringName,GDScript::MemberInfo>::Element *E=mi.front();E;E=E->next()) {
p_members->push_back(E->key());
p_values->push_back( instance->debug_get_member_by_index(E->get().index));
}
p_members->push_back(E->key());
p_values->push_back( instance->debug_get_member_by_index(E->get().index));
}
}
void GDScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems,int p_max_depth) {
@ -317,6 +318,7 @@ String GDScriptLanguage::make_function(const String& p_class,const String& p_nam
struct GDCompletionIdentifier {
StringName obj_type;
Ref<GDScript> script;
Variant::Type type;
Variant value; //im case there is a value, also return it
};
@ -446,7 +448,7 @@ static Ref<Reference> _get_parent_class(GDCompletionContext& context) {
base_class=base_class->subclasses[subclass];
} else {
print_line("Could not find subclass: "+subclass);
//print_line("Could not find subclass: "+subclass);
return _get_type_from_class(context); //fail please
}
}
@ -631,7 +633,9 @@ static bool _guess_expression_type(GDCompletionContext& context,const GDParser::
//try calling the function if constant and all args are constant, should not crash..
Object *baseptr = base.value;
if (baseptr && mb->is_const() && pi.type==Variant::OBJECT) {
if (mb->is_const() && pi.type==Variant::OBJECT) {
bool all_valid=true;
Vector<Variant> args;
for(int i=2;i<op->arguments.size();i++) {
@ -648,25 +652,88 @@ static bool _guess_expression_type(GDCompletionContext& context,const GDParser::
all_valid=false;
}
}
if (all_valid) {
Vector<const Variant*> argptr;
for(int i=0;i<args.size();i++) {
argptr.push_back(&args[i]);
}
Variant::CallError ce;
Variant ret=mb->call(baseptr,argptr.ptr(),argptr.size(),ce);
if (all_valid && String(id)=="get_node" && ObjectTypeDB::is_type(base.obj_type,"Node") && args.size()) {
String arg1=args[0];
if (arg1.begins_with("/root/")) {
String which = arg1.get_slice("/",2);
if (which!="") {
List<PropertyInfo> props;
Globals::get_singleton()->get_property_list(&props);
//print_line("find singleton");
for(List<PropertyInfo>::Element *E=props.front();E;E=E->next()) {
String s = E->get().name;
if (!s.begins_with("autoload/"))
continue;
//print_line("found "+s);
String name = s.get_slice("/",1);
//print_line("name: "+name+", which: "+which);
if (name==which) {
String script = Globals::get_singleton()->get(s);
if (!script.begins_with("res://")) {
script="res://"+script;
}
if (!script.ends_with(".gd")) {
//not a script, try find the script anyway,
//may have some success
script=script.basename()+".gd";
}
if (FileAccess::exists(script)) {
//print_line("is a script");
if (ce.error==Variant::CallError::CALL_OK && ret.get_type()!=Variant::NIL) {
Ref<Script> scr;
if (ScriptCodeCompletionCache::get_sigleton())
scr = ScriptCodeCompletionCache::get_sigleton()->get_cached_resource(script);
else
scr = ResourceLoader::load(script);
if (ret.get_type()!=Variant::OBJECT || ret.operator Object*()!=NULL) {
r_type=_get_type_from_variant(ret);
return true;
r_type.obj_type="Node";
r_type.type=Variant::OBJECT;
r_type.script=scr;
r_type.value=Variant();
return true;
}
}
}
}
}
}
if (baseptr) {
if (all_valid) {
Vector<const Variant*> argptr;
for(int i=0;i<args.size();i++) {
argptr.push_back(&args[i]);
}
Variant::CallError ce;
Variant ret=mb->call(baseptr,argptr.ptr(),argptr.size(),ce);
if (ce.error==Variant::CallError::CALL_OK && ret.get_type()!=Variant::NIL) {
if (ret.get_type()!=Variant::OBJECT || ret.operator Object*()!=NULL) {
r_type=_get_type_from_variant(ret);
return true;
}
}
}
}
}
@ -1281,6 +1348,7 @@ static void _make_function_hint(const GDParser::FunctionNode* p_func,int p_argid
static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const StringName& p_method,const GDCompletionIdentifier& id, int p_argidx, Set<String>& result, String& arghint) {
//print_line("find type arguments?");
if (id.type==Variant::INPUT_EVENT && String(p_method)=="is_action" && p_argidx==0) {
List<PropertyInfo> pinfo;
@ -1301,33 +1369,233 @@ static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const St
MethodBind *m = ObjectTypeDB::get_method(id.obj_type,p_method);
if (!m)
return;
if (!m) {
//not in static method, see script
if (p_method.operator String()=="connect") {
//print_line("not in static: "+String(p_method));
Ref<GDScript> on_script;
if (id.value.get_type()) {
Object *obj=id.value;
if (p_argidx==0) {
List<MethodInfo> sigs;
ObjectTypeDB::get_signal_list(id.obj_type,&sigs);
for (List<MethodInfo>::Element *E=sigs.front();E;E=E->next()) {
result.insert("\""+E->get().name+"\"");
if (obj) {
GDScript *scr = obj->cast_to<GDScript>();
if (scr) {
while (scr) {
for (const Map<StringName,GDFunction>::Element *E=scr->get_member_functions().front();E;E=E->next()) {
if (E->get().is_static() && p_method==E->get().get_name()) {
arghint="static func "+String(p_method)+"(";
for(int i=0;i<E->get().get_argument_count();i++) {
if (i>0)
arghint+=", ";
else
arghint+=" ";
if (i==p_argidx) {
arghint+=String::chr(0xFFFF);
}
arghint+="var "+E->get().get_argument_name(i);
int deffrom = E->get().get_argument_count()-E->get().get_default_argument_count();
if (i>=deffrom) {
int defidx = deffrom-i;
if (defidx>=0 && defidx<E->get().get_default_argument_count()) {
arghint+="="+E->get().get_default_argument(defidx).get_construct_string();
}
}
if (i==p_argidx) {
arghint+=String::chr(0xFFFF);
}
}
arghint+=")";
return; //found
}
}
if (scr->get_base().is_valid())
scr=scr->get_base().ptr();
else
scr=NULL;
}
} else {
on_script=obj->get_script();
}
}
}
//print_line("but it has a script?");
if (!on_script.is_valid() && id.script.is_valid()) {
//print_line("yes");
on_script=id.script;
}
if (on_script.is_valid()) {
GDScript *scr = on_script.ptr();
if (scr) {
while (scr) {
String code = scr->get_source_code();
//print_line("has source code!");
if (code!="") {
//if there is code, parse it. This way is slower but updates in real-time
GDParser p;
//Error parse(const String& p_code, const String& p_base_path="", bool p_just_validate=false,const String& p_self_path="",bool p_for_completion=false);
Error err = p.parse(scr->get_source_code(),scr->get_path().get_base_dir(),true,"",false);
if (err==OK) {
//print_line("checking the functions...");
//only if ok, otherwise use what is cached on the script
//GDParser::ClassNode *base = p.
const GDParser::Node *root = p.get_parse_tree();
ERR_FAIL_COND(root->type!=GDParser::Node::TYPE_CLASS);
const GDParser::ClassNode *cl = static_cast<const GDParser::ClassNode*>(root);
const GDParser::FunctionNode* func=NULL;
bool st=false;
for(int i=0;i<cl->functions.size();i++) {
//print_line(String(cl->functions[i]->name)+" vs "+String(p_method));
if (cl->functions[i]->name==p_method) {
func=cl->functions[i];
}
}
for(int i=0;i<cl->static_functions.size();i++) {
//print_line(String(cl->static_functions[i]->name)+" vs "+String(p_method));
if (cl->static_functions[i]->name==p_method) {
func=cl->static_functions[i];
st=true;
}
}
if (func) {
arghint="func "+String(p_method)+"(";
if (st)
arghint="static "+arghint;
for(int i=0;i<func->arguments.size();i++) {
if (i>0)
arghint+=", ";
else
arghint+=" ";
if (i==p_argidx) {
arghint+=String::chr(0xFFFF);
}
arghint+="var "+String(func->arguments[i]);
int deffrom = func->arguments.size()-func->default_values.size();
if (i>=deffrom) {
int defidx = deffrom-i;
if (defidx>=0 && defidx<func->default_values.size() && func->default_values[defidx]->type==GDParser::Node::TYPE_OPERATOR) {
const GDParser::OperatorNode *op=static_cast<const GDParser::OperatorNode *>(func->default_values[defidx]);
if (op->op==GDParser::OperatorNode::OP_ASSIGN) {
const GDParser::ConstantNode *cn=static_cast<const GDParser::ConstantNode *>(op->arguments[1]);
arghint+="="+cn->value.get_construct_string();
}
}
}
if (i==p_argidx) {
arghint+=String::chr(0xFFFF);
}
}
arghint+=" )";
return;
}
} else {
//print_line("failed parsing?");
code="";
}
}
if (code=="") {
for (const Map<StringName,GDFunction>::Element *E=scr->get_member_functions().front();E;E=E->next()) {
if (p_method==E->get().get_name()) {
arghint="func "+String(p_method)+"(";
for(int i=0;i<E->get().get_argument_count();i++) {
if (i>0)
arghint+=", ";
else
arghint+=" ";
if (i==p_argidx) {
arghint+=String::chr(0xFFFF);
}
arghint+="var "+E->get().get_argument_name(i);
int deffrom = E->get().get_argument_count()-E->get().get_default_argument_count();
if (i>=deffrom) {
int defidx = deffrom-i;
if (defidx>=0 && defidx<E->get().get_default_argument_count()) {
arghint+="="+E->get().get_default_argument(defidx).get_construct_string();
}
}
if (i==p_argidx) {
arghint+=String::chr(0xFFFF);
}
}
arghint+=")";
return; //found
}
}
#if 0
//use class directly, no code was found
if (!isfunction) {
for (const Map<StringName,Variant>::Element *E=scr->get_constants().front();E;E=E->next()) {
options.insert(E->key());
}
}
for (const Map<StringName,GDFunction>::Element *E=scr->get_member_functions().front();E;E=E->next()) {
options.insert(String(E->key())+"(");
}
for (const Set<StringName>::Element *E=scr->get_members().front();E;E=E->next()) {
options.insert(E->get());
}
#endif
}
if (scr->get_base().is_valid())
scr=scr->get_base().ptr();
else
scr=NULL;
}
}
}
/*if (p_argidx==2) {
ERR_FAIL_COND(p_node->type!=GDParser::Node::TYPE_OPERATOR);
const GDParser::OperatorNode *op=static_cast<const GDParser::OperatorNode *>(p_node);
if (op->arguments.size()>)
}*/
} else {
//regular method
Object *obj=id.value;
if (obj) {
List<String> options;
obj->get_argument_options(p_method,p_argidx,&options);
if (obj->is_type("Node") && p_argidx==0 && (String(p_method)=="get_node" || String(p_method)=="has_node")) {
if (p_method.operator String()=="connect") {
if (p_argidx==0) {
List<MethodInfo> sigs;
ObjectTypeDB::get_signal_list(id.obj_type,&sigs);
for (List<MethodInfo>::Element *E=sigs.front();E;E=E->next()) {
result.insert("\""+E->get().name+"\"");
}
}
/*if (p_argidx==2) {
ERR_FAIL_COND(p_node->type!=GDParser::Node::TYPE_OPERATOR);
const GDParser::OperatorNode *op=static_cast<const GDParser::OperatorNode *>(p_node);
if (op->arguments.size()>)
}*/
} else {
if (p_argidx==0 && (String(p_method)=="get_node" || String(p_method)=="has_node") && ObjectTypeDB::is_type(id.obj_type,"Node")) {
List<PropertyInfo> props;
Globals::get_singleton()->get_property_list(&props);
@ -1339,55 +1607,62 @@ static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const St
continue;
// print_line("found "+s);
String name = s.get_slice("/",1);
options.push_back("\"/root/"+name+"\"");
result.insert("\"/root/"+name+"\"");
}
}
for(List<String>::Element *E=options.front();E;E=E->next()) {
result.insert(E->get());
Object *obj=id.value;
if (obj) {
List<String> options;
obj->get_argument_options(p_method,p_argidx,&options);
for(List<String>::Element *E=options.front();E;E=E->next()) {
result.insert(E->get());
}
}
}
}
arghint = _get_visual_datatype(m->get_argument_info(-1),false)+" "+p_method.operator String()+String("(");
arghint = _get_visual_datatype(m->get_argument_info(-1),false)+" "+p_method.operator String()+String("(");
for(int i=0;i<m->get_argument_count();i++) {
if (i>0)
arghint+=", ";
else
arghint+=" ";
for(int i=0;i<m->get_argument_count();i++) {
if (i>0)
arghint+=", ";
else
if (i==p_argidx) {
arghint+=String::chr(0xFFFF);
}
String n = m->get_argument_info(i).name;
int dp = n.find(":");
if (dp!=-1)
n=n.substr(0,dp);
arghint+=_get_visual_datatype(m->get_argument_info(i))+" "+n;
int deffrom = m->get_argument_count()-m->get_default_argument_count();
if (i>=deffrom) {
int defidx = i-deffrom;
if (defidx>=0 && defidx<m->get_default_argument_count()) {
Variant v= m->get_default_argument(i);
arghint+="="+v.get_construct_string();
}
}
if (i==p_argidx) {
arghint+=String::chr(0xFFFF);
}
}
if (m->get_argument_count()>0)
arghint+=" ";
if (i==p_argidx) {
arghint+=String::chr(0xFFFF);
}
String n = m->get_argument_info(i).name;
int dp = n.find(":");
if (dp!=-1)
n=n.substr(0,dp);
arghint+=_get_visual_datatype(m->get_argument_info(i))+" "+n;
int deffrom = m->get_argument_count()-m->get_default_argument_count();
if (i>=deffrom) {
int defidx = i-deffrom;
if (defidx>=0 && defidx<m->get_default_argument_count()) {
Variant v= m->get_default_argument(i);
arghint+="="+v.get_construct_string();
}
}
if (i==p_argidx) {
arghint+=String::chr(0xFFFF);
}
arghint+=")";
}
if (m->get_argument_count()>0)
arghint+=" ";
arghint+=")";
}
}
@ -1434,7 +1709,7 @@ static void _find_call_arguments(GDCompletionContext& context,const GDParser::No
arghint+=")";
} else if (op->arguments[0]->type==GDParser::Node::TYPE_TYPE) {
//complete built-in function
//complete constructor
const GDParser::TypeNode *tn = static_cast<const GDParser::TypeNode*>(op->arguments[0]);
List<MethodInfo> mil;
@ -1569,7 +1844,7 @@ static void _find_call_arguments(GDCompletionContext& context,const GDParser::No
}
} else {
//indexed lookup
GDCompletionIdentifier ci;
if (_guess_expression_type(context,op->arguments[0],p_line,ci)) {
@ -1735,20 +2010,123 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base
if (t.type==Variant::OBJECT && t.obj_type!=StringName()) {
Ref<GDScript> on_script;
if (t.value.get_type()) {
Object *obj=t.value;
if (obj) {
GDScript *scr = obj->cast_to<GDScript>();
if (scr) {
while (scr) {
if (!isfunction) {
for (const Map<StringName,Variant>::Element *E=scr->get_constants().front();E;E=E->next()) {
options.insert(E->key());
}
}
for (const Map<StringName,GDFunction>::Element *E=scr->get_member_functions().front();E;E=E->next()) {
if (E->get().is_static())
options.insert(E->key());
}
if (scr->get_base().is_valid())
scr=scr->get_base().ptr();
else
scr=NULL;
}
} else {
on_script=obj->get_script();
}
}
}
if (!on_script.is_valid() && t.script.is_valid()) {
on_script=t.script;
}
if (on_script.is_valid()) {
GDScript *scr = on_script.ptr();
if (scr) {
while (scr) {
if (!isfunction) {
for (const Map<StringName,Variant>::Element *E=scr->get_constants().front();E;E=E->next()) {
options.insert(E->key());
String code = scr->get_source_code();
if (code!="") {
//if there is code, parse it. This way is slower but updates in real-time
GDParser p;
//Error parse(const String& p_code, const String& p_base_path="", bool p_just_validate=false,const String& p_self_path="",bool p_for_completion=false);
Error err = p.parse(scr->get_source_code(),scr->get_path().get_base_dir(),true,"",false);
if (err==OK) {
//only if ok, otherwise use what is cached on the script
//GDParser::ClassNode *base = p.
const GDParser::Node *root = p.get_parse_tree();
ERR_FAIL_COND_V(root->type!=GDParser::Node::TYPE_CLASS,ERR_PARSE_ERROR);
const GDParser::ClassNode *cl = static_cast<const GDParser::ClassNode*>(root);
for(int i=0;i<cl->functions.size();i++) {
if (cl->functions[i]->arguments.size())
options.insert(String(cl->functions[i]->name)+"(");
else
options.insert(String(cl->functions[i]->name)+"()");
}
for(int i=0;i<cl->static_functions.size();i++) {
if (cl->static_functions[i]->arguments.size())
options.insert(String(cl->static_functions[i]->name)+"(");
else
options.insert(String(cl->static_functions[i]->name)+"()");
}
if (!isfunction) {
for(int i=0;i<cl->variables.size();i++) {
options.insert(String(cl->variables[i].identifier));
}
for(int i=0;i<cl->constant_expressions.size();i++) {
options.insert(String(cl->constant_expressions[i].identifier));
}
}
} else {
code=""; //well, then no code
}
}
for (const Map<StringName,GDFunction>::Element *E=scr->get_member_functions().front();E;E=E->next()) {
options.insert(E->key());
if (code=="") {
//use class directly, no code was found
if (!isfunction) {
for (const Map<StringName,Variant>::Element *E=scr->get_constants().front();E;E=E->next()) {
options.insert(E->key());
}
}
for (const Map<StringName,GDFunction>::Element *E=scr->get_member_functions().front();E;E=E->next()) {
if (E->get().get_argument_count())
options.insert(String(E->key())+"()");
else
options.insert(String(E->key())+"(");
}
for (const Set<StringName>::Element *E=scr->get_members().front();E;E=E->next()) {
options.insert(E->get());
}
}
if (scr->get_base().is_valid())
@ -1760,6 +2138,10 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base
}
if (!isfunction) {
ObjectTypeDB::get_integer_constant_list(t.obj_type,r_options);
}

View File

@ -2315,6 +2315,17 @@ void GDParser::_parse_class(ClassNode *p_class) {
case Variant::INT: {
if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER && tokenizer->get_token_identifier()=="FLAGS") {
current_export.hint=PROPERTY_HINT_ALL_FLAGS;
tokenizer->advance();
if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_CLOSE) {
_set_error("Expected ')' in hint.");
return;
}
break;
}
if (tokenizer->get_token()==GDTokenizer::TK_CONSTANT && tokenizer->get_token_constant().get_type()==Variant::STRING) {
//enumeration
current_export.hint=PROPERTY_HINT_ENUM;
@ -2542,16 +2553,23 @@ void GDParser::_parse_class(ClassNode *p_class) {
} else if (tokenizer->get_token()==GDTokenizer::TK_IDENTIFIER) {
String identifier = tokenizer->get_token_identifier();
if (!ObjectTypeDB::is_type(identifier,"Resource")) {
current_export=PropertyInfo();
_set_error("Export hint not a type or resource.");
if (identifier == "flag") {
current_export.type=Variant::INT;
current_export.hint=PROPERTY_HINT_ALL_FLAGS;
}else if (identifier == "multiline"){
current_export.type=Variant::STRING;
current_export.hint=PROPERTY_HINT_MULTILINE_TEXT;
} else {
if (!ObjectTypeDB::is_type(identifier,"Resource")) {
current_export=PropertyInfo();
_set_error("Export hint not a type or resource.");
}
current_export.type=Variant::OBJECT;
current_export.hint=PROPERTY_HINT_RESOURCE_TYPE;
current_export.hint_string=identifier;
}
current_export.type=Variant::OBJECT;
current_export.hint=PROPERTY_HINT_RESOURCE_TYPE;
current_export.hint_string=identifier;
tokenizer->advance();
}

View File

@ -1977,9 +1977,17 @@ void GDScript::_bind_methods() {
ObjectTypeDB::bind_native_method(METHOD_FLAGS_DEFAULT,"new",&GDScript::_new,MethodInfo("new"));
ObjectTypeDB::bind_method(_MD("get_as_byte_code"),&GDScript::get_as_byte_code);
}
Vector<uint8_t> GDScript::get_as_byte_code() const {
GDTokenizerBuffer tokenizer;
return tokenizer.parse_code_string(source);
};
Error GDScript::load_byte_code(const String& p_path) {
@ -2556,9 +2564,9 @@ void GDScriptLanguage::init() {
//populate native classes
List<String> class_list;
List<StringName> class_list;
ObjectTypeDB::get_type_list(&class_list);
for(List<String>::Element *E=class_list.front();E;E=E->next()) {
for(List<StringName>::Element *E=class_list.front();E;E=E->next()) {
StringName n = E->get();
String s = String(n);

View File

@ -349,6 +349,8 @@ public:
Error load_source_code(const String& p_path);
Error load_byte_code(const String& p_path);
Vector<uint8_t> get_as_byte_code() const;
virtual ScriptLanguage *get_language() const;
GDScript();
@ -473,6 +475,19 @@ public:
}
virtual Vector<StackInfo> debug_get_current_stack_info() {
if (Thread::get_main_ID()!=Thread::get_caller_ID())
return Vector<StackInfo>();
Vector<StackInfo> csi;
csi.resize(_debug_call_stack_pos);
for(int i=0;i<_debug_call_stack_pos;i++) {
csi[_debug_call_stack_pos-i-1].line=_call_stack[i].line?*_call_stack[i].line:0;
csi[_debug_call_stack_pos-i-1].script=Ref<GDScript>(_call_stack[i].function->get_script());
}
return csi;
}
struct {
StringName _init;

View File

@ -97,6 +97,7 @@ const char* GDTokenizer::token_names[TK_MAX]={
"preload",
"assert",
"yield",
"signal",
"'['",
"']'",
"'{'",
@ -642,6 +643,11 @@ void GDTokenizerText::_advance() {
str+=res;
} else {
if (CharType(GETCHAR(i))=='\n') {
line++;
column=0;
}
str+=CharType(GETCHAR(i));
}
i++;
@ -1040,7 +1046,7 @@ void GDTokenizerText::advance(int p_amount) {
//////////////////////////////////////////////////////////////////////////////////////////////////////
#define BYTECODE_VERSION 4
#define BYTECODE_VERSION 5
Error GDTokenizerBuffer::set_code_buffer(const Vector<uint8_t> & p_buffer) {

View File

@ -130,8 +130,8 @@ bool GridMap::_set(const StringName& p_name, const Variant& p_value) {
} else if (name.begins_with("areas/")) {
int which = name.get_slice("/",1).to_int();
String what=name.get_slice("/",2);
int which = name.get_slicec('/',1).to_int();
String what=name.get_slicec('/',2);
if (what=="bounds") {
ERR_FAIL_COND_V(area_map.has(which),false);
create_area(which,p_value);
@ -215,8 +215,8 @@ bool GridMap::_get(const StringName& p_name,Variant &r_ret) const {
r_ret= d;
} else if (name.begins_with("areas/")) {
int which = name.get_slice("/",1).to_int();
String what=name.get_slice("/",2);
int which = name.get_slicec('/',1).to_int();
String what=name.get_slicec('/',2);
if (what=="bounds")
r_ret= area_get_bounds(which);
else if (what=="name")

View File

@ -54,13 +54,53 @@ def create(env):
def configure(env):
# Workaround for MinGW. See:
# http://www.scons.org/wiki/LongCmdLinesOnWin32
import os
if (os.name=="nt"):
import subprocess
def mySubProcess(cmdline,env):
#print "SPAWNED : " + cmdline
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False, env = env)
data, err = proc.communicate()
rv = proc.wait()
if rv:
print "====="
print err
print "====="
return rv
def mySpawn(sh, escape, cmd, args, env):
newargs = ' '.join(args[1:])
cmdline = cmd + " " + newargs
rv=0
if len(cmdline) > 32000 and cmd.endswith("ar") :
cmdline = cmd + " " + args[1] + " " + args[2] + " "
for i in range(3,len(args)) :
rv = mySubProcess( cmdline + args[i], env )
if rv :
break
else:
rv = mySubProcess( cmdline, env )
return rv
env['SPAWN'] = mySpawn
if env['x86']=='yes':
env['NDK_TARGET']='x86-4.8'
if env['PLATFORM'] == 'win32':
import methods
env.Tool('gcc')
env['SPAWN'] = methods.win32_spawn
#env['SPAWN'] = methods.win32_spawn
env['SHLIBSUFFIX'] = '.so'
# env.android_source_modules.append("../libs/apk_expansion")

View File

@ -228,7 +228,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
String get_package_name();
String get_project_name() const;
void _fix_manifest(Vector<uint8_t>& p_manifest);
void _fix_manifest(Vector<uint8_t>& p_manifest, bool p_give_internet);
void _fix_resources(Vector<uint8_t>& p_manifest);
static Error save_apk_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total);
@ -249,11 +249,11 @@ public:
virtual int get_device_count() const;
virtual String get_device_name(int p_device) const;
virtual String get_device_info(int p_device) const;
virtual Error run(int p_device,bool p_dumb=false);
virtual Error run(int p_device,bool p_dumb=false,bool p_remote_debug=false);
virtual bool requieres_password(bool p_debug) const { return !p_debug; }
virtual String get_binary_extension() const { return "apk"; }
virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
virtual Error export_project(const String& p_path, bool p_debug, bool p_dumb=false, bool p_remote_debug=false);
virtual bool can_export(String *r_error=NULL) const;
@ -317,7 +317,7 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant&
apk_expansion_pkey=p_value;
else if (n.begins_with("permissions/")) {
String what = n.get_slice("/",1).to_upper();
String what = n.get_slicec('/',1).to_upper();
bool state = p_value;
if (state)
perms.insert(what);
@ -325,7 +325,7 @@ bool EditorExportPlatformAndroid::_set(const StringName& p_name, const Variant&
perms.erase(what);
} else if (n.begins_with("user_permissions/")) {
int which = n.get_slice("/",1).to_int();
int which = n.get_slicec('/',1).to_int();
ERR_FAIL_INDEX_V(which,MAX_USER_PERMISSIONS,false);
user_perms[which]=p_value;
@ -390,11 +390,11 @@ bool EditorExportPlatformAndroid::_get(const StringName& p_name,Variant &r_ret)
r_ret=apk_expansion_pkey;
else if (n.begins_with("permissions/")) {
String what = n.get_slice("/",1).to_upper();
String what = n.get_slicec('/',1).to_upper();
r_ret = perms.has(what);
} else if (n.begins_with("user_permissions/")) {
int which = n.get_slice("/",1).to_int();
int which = n.get_slicec('/',1).to_int();
ERR_FAIL_INDEX_V(which,MAX_USER_PERMISSIONS,false);
r_ret=user_perms[which];
} else
@ -608,7 +608,7 @@ String EditorExportPlatformAndroid::get_project_name() const {
}
void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest) {
void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest,bool p_give_internet) {
const int CHUNK_AXML_FILE = 0x00080003;
@ -838,7 +838,10 @@ void EditorExportPlatformAndroid::_fix_manifest(Vector<uint8_t>& p_manifest) {
} else if (value.begins_with("godot.")) {
String perm = value.get_slice(".",1);
if (perms.has(perm)) {
print_line("PERM: "+perm+" HAS: "+itos(perms.has(perm)));
if (perms.has(perm) || (p_give_internet && perm=="INTERNET")) {
string_table[attr_value]="android.permission."+perm;
}
@ -1011,7 +1014,7 @@ Error EditorExportPlatformAndroid::save_apk_file(void *p_userdata,const String&
Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_debug, bool p_dumb) {
Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_debug, bool p_dumb,bool p_remote_debug) {
String src_apk;
@ -1075,7 +1078,7 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
if (file=="AndroidManifest.xml") {
_fix_manifest(data);
_fix_manifest(data,p_dumb || p_remote_debug);
}
if (file=="resources.arsc") {
@ -1153,9 +1156,11 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
}
}
gen_export_flags(cl,p_dumb,p_remote_debug);
if (p_dumb) {
String host = EditorSettings::get_singleton()->get("file_server/host");
/*String host = EditorSettings::get_singleton()->get("file_server/host");
int port = EditorSettings::get_singleton()->get("file_server/post");
String passwd = EditorSettings::get_singleton()->get("file_server/password");
cl.push_back("-rfs");
@ -1163,7 +1168,7 @@ Error EditorExportPlatformAndroid::export_project(const String& p_path, bool p_d
if (passwd!="") {
cl.push_back("-rfs_pass");
cl.push_back(passwd);
}
}*/
} else {
@ -1480,7 +1485,7 @@ void EditorExportPlatformAndroid::_device_poll_thread(void *ud) {
}
Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) {
Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb, bool p_remote_debug) {
ERR_FAIL_INDEX_V(p_device,devices.size(),ERR_INVALID_PARAMETER);
device_lock->lock();
@ -1499,7 +1504,7 @@ Error EditorExportPlatformAndroid::run(int p_device, bool p_dumb) {
ep.step("Exporting APK",0);
String export_to=EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmpexport.apk";
Error err = export_project(export_to,true,p_dumb);
Error err = export_project(export_to,true,p_dumb,p_remote_debug);
if (err) {
device_lock->unlock();
return err;

View File

@ -67,11 +67,11 @@ public:
virtual int get_device_count() const;
virtual String get_device_name(int p_device) const;
virtual String get_device_info(int p_device) const;
virtual Error run(int p_device,bool p_dumb=false);
virtual Error run(int p_device,bool p_dumb=false,bool p_remote_debug=false);
virtual bool requieres_password(bool p_debug) const { return !p_debug; }
virtual String get_binary_extension() const { return "bar"; }
virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false,bool p_remote_debug=false);
virtual bool can_export(String *r_error=NULL) const;
@ -270,7 +270,7 @@ void EditorExportPlatformBB10::_fix_descriptor(Vector<uint8_t>& p_descriptor) {
Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debug, bool p_dumb) {
Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debug, bool p_dumb, bool p_remote_debug) {
EditorProgress ep("export","Exporting for BlackBerry 10",104);
@ -619,7 +619,7 @@ void EditorExportPlatformBB10::_device_poll_thread(void *ud) {
}
Error EditorExportPlatformBB10::run(int p_device, bool p_dumb) {
Error EditorExportPlatformBB10::run(int p_device, bool p_dumb, bool p_remote_debug) {
ERR_FAIL_INDEX_V(p_device,devices.size(),ERR_INVALID_PARAMETER);

View File

@ -138,6 +138,29 @@ static int frame_count = 0;
Main::setup2();
++frame_count;
// this might be necessary before here
for (NSString* key in [[NSBundle mainBundle] infoDictionary]) {
NSObject* value = [[[NSBundle mainBundle] infoDictionary] objectForKey:key];
String ukey = String::utf8([key UTF8String]);
// we need a NSObject to Variant conversor
if ([value isKindOfClass:[NSString class]]) {
NSString* str = (NSString*)value;
String uval = String::utf8([str UTF8String]);
Globals::get_singleton()->set("Info.plist/"+ukey, uval);
} else if ([value isKindOfClass:[NSNumber class]]) {
NSNumber* n = (NSNumber*)value;
double dval = [n doubleValue];
Globals::get_singleton()->set("Info.plist/"+ukey, dval);
};
// do stuff
}
} break;
/*
case 3: {

View File

@ -77,11 +77,11 @@ public:
virtual int get_device_count() const { return show_run?1:0; };
virtual String get_device_name(int p_device) const { return "Run in Browser"; }
virtual String get_device_info(int p_device) const { return "Run exported HTML in the system's default browser."; }
virtual Error run(int p_device,bool p_dumb=false);
virtual Error run(int p_device,bool p_dumb=false,bool p_remote_debug=false);
virtual bool requieres_password(bool p_debug) const { return false; }
virtual String get_binary_extension() const { return "html"; }
virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false,bool p_remote_debug=false);
virtual bool can_export(String *r_error=NULL) const;
@ -194,7 +194,7 @@ struct JSExportData {
Error EditorExportPlatformJavaScript::export_project(const String& p_path, bool p_debug, bool p_dumb) {
Error EditorExportPlatformJavaScript::export_project(const String& p_path, bool p_debug, bool p_dumb, bool p_remote_debug) {
String src_template;
@ -299,7 +299,7 @@ Error EditorExportPlatformJavaScript::export_project(const String& p_path, bool
}
Error EditorExportPlatformJavaScript::run(int p_device, bool p_dumb) {
Error EditorExportPlatformJavaScript::run(int p_device, bool p_dumb, bool p_remote_debug) {
String path = EditorSettings::get_singleton()->get_settings_path()+"/tmp/tmp_export.html";
Error err = export_project(path,true,"");

View File

@ -57,11 +57,11 @@ public:
virtual int get_device_count() const { return 0; };
virtual String get_device_name(int p_device) const { return String(); }
virtual String get_device_info(int p_device) const { return String(); }
virtual Error run(int p_device,bool p_dumb=false);
virtual Error run(int p_device,bool p_dumb=false,bool p_remote_debug=false);
virtual bool requieres_password(bool p_debug) const { return false; }
virtual String get_binary_extension() const { return "zip"; }
virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false);
virtual Error export_project(const String& p_path,bool p_debug,bool p_dumb=false,bool p_remote_debug=false);
virtual bool can_export(String *r_error=NULL) const;
@ -245,7 +245,7 @@ void EditorExportPlatformOSX::_fix_plist(Vector<uint8_t>& plist,const String& p_
}
}
Error EditorExportPlatformOSX::export_project(const String& p_path, bool p_debug, bool p_dumb) {
Error EditorExportPlatformOSX::export_project(const String& p_path, bool p_debug, bool p_dumb, bool p_remote_debug) {
String src_pkg;
@ -437,7 +437,7 @@ Error EditorExportPlatformOSX::export_project(const String& p_path, bool p_debug
}
Error EditorExportPlatformOSX::run(int p_device, bool p_dumb) {
Error EditorExportPlatformOSX::run(int p_device, bool p_dumb, bool p_remote_debug) {
return OK;
}

View File

@ -1899,6 +1899,12 @@ uint64_t OS_Windows::get_unix_time() const {
return (*(uint64_t*)&ft - *(uint64_t*)&fep) / 10000000;
};
uint64_t OS_Windows::get_system_time_msec() const {
SYSTEMTIME st;
GetSystemTime(&st);
return st.wMilliseconds;
}
void OS_Windows::delay_usec(uint32_t p_usec) const {
if (p_usec < 1000)

View File

@ -263,6 +263,7 @@ public:
virtual Time get_time(bool utc) const;
virtual TimeZoneInfo get_time_zone_info() const;
virtual uint64_t get_unix_time() const;
virtual uint64_t get_system_time_msec() const;
virtual bool can_draw() const;
virtual Error set_cwd(const String& p_cwd);
@ -272,7 +273,7 @@ public:
virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL);
virtual Error kill(const ProcessID& p_pid);
virtual bool has_environment(const String& p_var) const;
virtual String get_environment(const String& p_var) const;

View File

@ -267,6 +267,7 @@ void OS_X11::initialize(const VideoMode& p_desired,int p_video_driver,int p_audi
for(int i=0;i<AudioDriverManagerSW::get_driver_count();i++) {
if (i==p_audio_driver)
continue;
AudioDriverManagerSW::get_driver(i)->set_singleton();
if (AudioDriverManagerSW::get_driver(i)->init()==OK) {
success=true;
print_line("Audio Driver Failed: "+String(AudioDriverManagerSW::get_driver(p_audio_driver)->get_name()));

View File

@ -330,11 +330,11 @@ void AnimatedSprite::_bind_methods() {
ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "frames",PROPERTY_HINT_RESOURCE_TYPE,"SpriteFrames"), _SCS("set_sprite_frames"),_SCS("get_sprite_frames"));
ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v"));
ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v"));
ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
}

View File

@ -428,8 +428,9 @@ void Area2D::set_enable_monitoring(bool p_enable) {
if (monitoring) {
Physics2DServer::get_singleton()->area_set_monitor_callback(get_rid(),this,"_body_inout");
Physics2DServer::get_singleton()->area_set_area_monitor_callback(get_rid(),this,"_area_inout");
Physics2DServer::get_singleton()->area_set_monitor_callback(get_rid(),this,SceneStringNames::get_singleton()->_body_inout);
Physics2DServer::get_singleton()->area_set_area_monitor_callback(get_rid(),this,SceneStringNames::get_singleton()->_area_inout);
} else {
Physics2DServer::get_singleton()->area_set_monitor_callback(get_rid(),NULL,StringName());
Physics2DServer::get_singleton()->area_set_area_monitor_callback(get_rid(),NULL,StringName());
@ -652,17 +653,17 @@ void Area2D::_bind_methods() {
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"space_override",PROPERTY_HINT_ENUM,"Disabled,Combine,Replace"),_SCS("set_space_override_mode"),_SCS("get_space_override_mode"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gravity_point"),_SCS("set_gravity_is_point"),_SCS("is_gravity_a_point"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity_distance_scale", PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_gravity_distance_scale"),_SCS("get_gravity_distance_scale"));
ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"gravity_point"),_SCS("set_gravity_is_point"),_SCS("is_gravity_a_point"));
ADD_PROPERTYNZ( PropertyInfo(Variant::REAL,"gravity_distance_scale", PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_gravity_distance_scale"),_SCS("get_gravity_distance_scale"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"gravity_vec"),_SCS("set_gravity_vector"),_SCS("get_gravity_vector"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"gravity",PROPERTY_HINT_RANGE,"-1024,1024,0.01"),_SCS("set_gravity"),_SCS("get_gravity"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"linear_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_linear_damp"),_SCS("get_linear_damp"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"angular_damp",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_angular_damp"),_SCS("get_angular_damp"));
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitorable"),_SCS("set_monitorable"),_SCS("is_monitorable"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_layer_mask"),_SCS("get_layer_mask"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_mask"),_SCS("get_collision_mask"));
ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled"));
ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"monitorable"),_SCS("set_monitorable"),_SCS("is_monitorable"));
ADD_PROPERTYNO( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_layer_mask"),_SCS("get_layer_mask"));
ADD_PROPERTYNO( PropertyInfo(Variant::INT,"collision/mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_mask"),_SCS("get_collision_mask"));
}

View File

@ -1071,8 +1071,8 @@ void CanvasItem::_bind_methods() {
ObjectTypeDB::bind_method(_MD("draw_rect","rect","color"),&CanvasItem::draw_rect);
ObjectTypeDB::bind_method(_MD("draw_circle","pos","radius","color"),&CanvasItem::draw_circle);
ObjectTypeDB::bind_method(_MD("draw_texture","texture:Texture","pos"),&CanvasItem::draw_texture);
ObjectTypeDB::bind_method(_MD("draw_texture_rect","texture:Texture","rect","tile","modulate"),&CanvasItem::draw_texture_rect,DEFVAL(false),DEFVAL(Color(1,1,1)));
ObjectTypeDB::bind_method(_MD("draw_texture_rect_region","texture:Texture","rect","src_rect","modulate"),&CanvasItem::draw_texture_rect_region,DEFVAL(Color(1,1,1)));
ObjectTypeDB::bind_method(_MD("draw_texture_rect","texture:Texture","rect","tile","modulate","transpose"),&CanvasItem::draw_texture_rect,DEFVAL(Color(1,1,1)),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("draw_texture_rect_region","texture:Texture","rect","src_rect","modulate","transpose"),&CanvasItem::draw_texture_rect_region,DEFVAL(Color(1,1,1)),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("draw_style_box","style_box:StyleBox","rect"),&CanvasItem::draw_style_box);
ObjectTypeDB::bind_method(_MD("draw_primitive","points","colors","uvs","texture:Texture","width"),&CanvasItem::draw_primitive,DEFVAL(Array()),DEFVAL(Ref<Texture>()),DEFVAL(1.0));
ObjectTypeDB::bind_method(_MD("draw_polygon","points","colors","uvs","texture:Texture"),&CanvasItem::draw_polygon,DEFVAL(Array()),DEFVAL(Ref<Texture>()));
@ -1103,14 +1103,14 @@ void CanvasItem::_bind_methods() {
BIND_VMETHOD(MethodInfo("_draw"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/visible"), _SCS("_set_visible_"),_SCS("_is_visible_") );
ADD_PROPERTY( PropertyInfo(Variant::REAL,"visibility/opacity",PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_opacity"),_SCS("get_opacity") );
ADD_PROPERTY( PropertyInfo(Variant::REAL,"visibility/self_opacity",PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_self_opacity"),_SCS("get_self_opacity") );
ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"visibility/visible"), _SCS("_set_visible_"),_SCS("_is_visible_") );
ADD_PROPERTYNO( PropertyInfo(Variant::REAL,"visibility/opacity",PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_opacity"),_SCS("get_opacity") );
ADD_PROPERTYNO( PropertyInfo(Variant::REAL,"visibility/self_opacity",PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_self_opacity"),_SCS("get_self_opacity") );
ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"visibility/behind_parent"), _SCS("set_draw_behind_parent"),_SCS("is_draw_behind_parent_enabled") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/on_top",PROPERTY_HINT_NONE,"",0), _SCS("_set_on_top"),_SCS("_is_on_top") ); //compatibility
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,PMAlpha"), _SCS("set_blend_mode"),_SCS("get_blend_mode") );
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/light_mask",PROPERTY_HINT_ALL_FLAGS), _SCS("set_light_mask"),_SCS("get_light_mask") );
ADD_PROPERTYNO( PropertyInfo(Variant::INT,"visibility/light_mask",PROPERTY_HINT_ALL_FLAGS), _SCS("set_light_mask"),_SCS("get_light_mask") );
ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"material/material",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial"), _SCS("set_material"),_SCS("get_material") );
ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"material/use_parent"), _SCS("set_use_parent_material"),_SCS("get_use_parent_material") );
//exporting these two things doesn't really make much sense i think

View File

@ -115,19 +115,16 @@ void CollisionObject2D::_update_shapes() {
bool CollisionObject2D::_set(const StringName& p_name, const Variant& p_value) {
String name=p_name;
if (name=="shape_count") {
if (name.begins_with("shapes/")) {
shapes.resize(p_value);
_update_shapes();
_change_notify();
} else if (name.begins_with("shapes/")) {
int idx=name.get_slice("/",1).to_int();
String what=name.get_slice("/",2);
if (what=="shape")
set_shape(idx,RefPtr(p_value));
else if (what=="transform")
int idx=name.get_slicec('/',1).to_int();
String what=name.get_slicec('/',2);
if (what=="shape") {
if (idx>=shapes.size())
add_shape(RefPtr(p_value));
else
set_shape(idx,RefPtr(p_value));
} else if (what=="transform")
set_shape_transform(idx,p_value);
else if (what=="trigger")
set_shape_as_trigger(idx,p_value);
@ -143,12 +140,10 @@ bool CollisionObject2D::_get(const StringName& p_name,Variant &r_ret) const {
String name=p_name;
if (name=="shape_count") {
r_ret= shapes.size();
} else if (name.begins_with("shapes/")) {
if (name.begins_with("shapes/")) {
int idx=name.get_slice("/",1).to_int();
String what=name.get_slice("/",2);
int idx=name.get_slicec('/',1).to_int();
String what=name.get_slicec('/',2);
if (what=="shape")
r_ret= get_shape(idx);
else if (what=="transform")
@ -163,7 +158,7 @@ bool CollisionObject2D::_get(const StringName& p_name,Variant &r_ret) const {
void CollisionObject2D::_get_property_list( List<PropertyInfo> *p_list) const {
p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) );
//p_list->push_back( PropertyInfo(Variant::INT,"shape_count",PROPERTY_HINT_RANGE,"0,256,1",PROPERTY_USAGE_NOEDITOR|PROPERTY_USAGE_NO_INSTANCE_STATE) );
for(int i=0;i<shapes.size();i++) {
String path="shapes/"+itos(i)+"/";
@ -254,12 +249,19 @@ void CollisionObject2D::_bind_methods() {
void CollisionObject2D::add_shape(const Ref<Shape2D>& p_shape, const Matrix32& p_transform) {
ERR_FAIL_COND(p_shape.is_null());
ShapeData sdata;
sdata.shape=p_shape;
sdata.xform=p_transform;
sdata.trigger=false;
shapes.push_back(sdata);
_update_shapes();
if (area)
Physics2DServer::get_singleton()->area_add_shape(get_rid(),p_shape->get_rid(),p_transform);
else
Physics2DServer::get_singleton()->body_add_shape(get_rid(),p_shape->get_rid(),p_transform);
shapes.push_back(sdata);
}
int CollisionObject2D::get_shape_count() const {
@ -270,8 +272,15 @@ int CollisionObject2D::get_shape_count() const {
void CollisionObject2D::set_shape(int p_shape_idx, const Ref<Shape2D>& p_shape) {
ERR_FAIL_INDEX(p_shape_idx,shapes.size());
ERR_FAIL_COND(p_shape.is_null());
shapes[p_shape_idx].shape=p_shape;
_update_shapes();
if (area)
Physics2DServer::get_singleton()->area_set_shape(get_rid(),p_shape_idx,p_shape->get_rid());
else
Physics2DServer::get_singleton()->body_set_shape(get_rid(),p_shape_idx,p_shape->get_rid());
// _update_shapes();
}
void CollisionObject2D::set_shape_transform(int p_shape_idx, const Matrix32& p_transform) {
@ -279,7 +288,12 @@ void CollisionObject2D::set_shape_transform(int p_shape_idx, const Matrix32& p_t
ERR_FAIL_INDEX(p_shape_idx,shapes.size());
shapes[p_shape_idx].xform=p_transform;
_update_shapes();
if (area)
Physics2DServer::get_singleton()->area_set_shape_transform(get_rid(),p_shape_idx,p_transform);
else
Physics2DServer::get_singleton()->body_set_shape_transform(get_rid(),p_shape_idx,p_transform);
// _update_shapes();
}
Ref<Shape2D> CollisionObject2D::get_shape(int p_shape_idx) const {

View File

@ -398,11 +398,11 @@ void Node2D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_relative_transform"),&Node2D::get_relative_transform);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"transform/pos"),_SCS("set_pos"),_SCS("get_pos"));
ADD_PROPERTY(PropertyInfo(Variant::REAL,"transform/rot",PROPERTY_HINT_RANGE,"-1440,1440,0.1"),_SCS("_set_rotd"),_SCS("_get_rotd"));
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"transform/scale"),_SCS("set_scale"),_SCS("get_scale"));
ADD_PROPERTY(PropertyInfo(Variant::INT,"z/z",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z"),_SCS("get_z"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"z/relative"),_SCS("set_z_as_relative"),_SCS("is_z_relative"));
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"transform/pos"),_SCS("set_pos"),_SCS("get_pos"));
ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"transform/rot",PROPERTY_HINT_RANGE,"-1440,1440,0.1"),_SCS("_set_rotd"),_SCS("_get_rotd"));
ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2,"transform/scale"),_SCS("set_scale"),_SCS("get_scale"));
ADD_PROPERTYNZ(PropertyInfo(Variant::INT,"z/z",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z"),_SCS("get_z"));
ADD_PROPERTYNO(PropertyInfo(Variant::BOOL,"z/relative"),_SCS("set_z_as_relative"),_SCS("is_z_relative"));
}

View File

@ -1072,19 +1072,19 @@ void Particles2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT,"config/amount",PROPERTY_HINT_EXP_RANGE,"1,1024"),_SCS("set_amount"),_SCS("get_amount") );
ADD_PROPERTY(PropertyInfo(Variant::REAL,"config/lifetime",PROPERTY_HINT_EXP_RANGE,"0.1,3600,0.1"),_SCS("set_lifetime"),_SCS("get_lifetime") );
ADD_PROPERTY(PropertyInfo(Variant::REAL,"config/time_scale",PROPERTY_HINT_EXP_RANGE,"0.01,128,0.01"),_SCS("set_time_scale"),_SCS("get_time_scale") );
ADD_PROPERTY(PropertyInfo(Variant::REAL,"config/preprocess",PROPERTY_HINT_EXP_RANGE,"0.1,3600,0.1"),_SCS("set_pre_process_time"),_SCS("get_pre_process_time") );
ADD_PROPERTY(PropertyInfo(Variant::REAL,"config/emit_timeout",PROPERTY_HINT_RANGE,"0,3600,0.1"),_SCS("set_emit_timeout"),_SCS("get_emit_timeout") );
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"config/emitting"),_SCS("set_emitting"),_SCS("is_emitting") );
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"config/offset"),_SCS("set_emissor_offset"),_SCS("get_emissor_offset"));
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"config/half_extents"),_SCS("set_emission_half_extents"),_SCS("get_emission_half_extents"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"config/local_space"),_SCS("set_use_local_space"),_SCS("is_using_local_space"));
ADD_PROPERTY(PropertyInfo(Variant::REAL,"config/explosiveness",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_explosiveness"),_SCS("get_explosiveness"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"config/flip_h"),_SCS("set_flip_h"),_SCS("is_flipped_h"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"config/flip_v"),_SCS("set_flip_v"),_SCS("is_flipped_v"));
ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"config/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"));
ADD_PROPERTY(PropertyInfo(Variant::INT,"config/h_frames",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_h_frames"),_SCS("get_h_frames"));
ADD_PROPERTY(PropertyInfo(Variant::INT,"config/v_frames",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_v_frames"),_SCS("get_v_frames"));
ADD_PROPERTYNO(PropertyInfo(Variant::REAL,"config/time_scale",PROPERTY_HINT_EXP_RANGE,"0.01,128,0.01"),_SCS("set_time_scale"),_SCS("get_time_scale") );
ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"config/preprocess",PROPERTY_HINT_EXP_RANGE,"0.1,3600,0.1"),_SCS("set_pre_process_time"),_SCS("get_pre_process_time") );
ADD_PROPERTYNZ(PropertyInfo(Variant::REAL,"config/emit_timeout",PROPERTY_HINT_RANGE,"0,3600,0.1"),_SCS("set_emit_timeout"),_SCS("get_emit_timeout") );
ADD_PROPERTYNO(PropertyInfo(Variant::BOOL,"config/emitting"),_SCS("set_emitting"),_SCS("is_emitting") );
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"config/offset"),_SCS("set_emissor_offset"),_SCS("get_emissor_offset"));
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2,"config/half_extents"),_SCS("set_emission_half_extents"),_SCS("get_emission_half_extents"));
ADD_PROPERTYNO(PropertyInfo(Variant::BOOL,"config/local_space"),_SCS("set_use_local_space"),_SCS("is_using_local_space"));
ADD_PROPERTYNO(PropertyInfo(Variant::REAL,"config/explosiveness",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_explosiveness"),_SCS("get_explosiveness"));
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL,"config/flip_h"),_SCS("set_flip_h"),_SCS("is_flipped_h"));
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL,"config/flip_v"),_SCS("set_flip_v"),_SCS("is_flipped_v"));
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"config/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"));
ADD_PROPERTYNO(PropertyInfo(Variant::INT,"config/h_frames",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_h_frames"),_SCS("get_h_frames"));
ADD_PROPERTYNO(PropertyInfo(Variant::INT,"config/v_frames",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_v_frames"),_SCS("get_v_frames"));
for(int i=0;i<PARAM_MAX;i++) {
@ -1092,10 +1092,10 @@ void Particles2D::_bind_methods() {
}
for(int i=0;i<PARAM_MAX;i++) {
ADD_PROPERTYI(PropertyInfo(Variant::REAL,_particlesframe_property_rnames[i],PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_randomness"),_SCS("get_randomness"),i);
ADD_PROPERTYINZ(PropertyInfo(Variant::REAL,_particlesframe_property_rnames[i],PROPERTY_HINT_RANGE,"-1,1,0.01"),_SCS("set_randomness"),_SCS("get_randomness"),i);
}
ADD_PROPERTY( PropertyInfo( Variant::INT, "color_phases/count",PROPERTY_HINT_RANGE,"0,4,1", 0), _SCS("set_color_phases"), _SCS("get_color_phases"));
ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "color_phases/count",PROPERTY_HINT_RANGE,"0,4,1", 0), _SCS("set_color_phases"), _SCS("get_color_phases"));
//Backward compatibility. They will be converted to color ramp
for(int i=0;i<MAX_COLOR_PHASES;i++) {
@ -1104,10 +1104,10 @@ void Particles2D::_bind_methods() {
ADD_PROPERTYI( PropertyInfo( Variant::COLOR, phase+"color", PROPERTY_HINT_NONE, "", 0),_SCS("set_color_phase_color"),_SCS("get_color_phase_color"),i );
}
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color/color"),_SCS("set_color"),_SCS("get_color"));
ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"color/color_ramp",PROPERTY_HINT_RESOURCE_TYPE,"ColorRamp"),_SCS("set_color_ramp"),_SCS("get_color_ramp"));
ADD_PROPERTYNO(PropertyInfo(Variant::COLOR, "color/color"),_SCS("set_color"),_SCS("get_color"));
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT,"color/color_ramp",PROPERTY_HINT_RESOURCE_TYPE,"ColorRamp"),_SCS("set_color_ramp"),_SCS("get_color_ramp"));
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2_ARRAY,"emission_points",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_emission_points"),_SCS("get_emission_points"));
ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2_ARRAY,"emission_points",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_emission_points"),_SCS("get_emission_points"));
BIND_CONSTANT( PARAM_DIRECTION );
BIND_CONSTANT( PARAM_SPREAD );

View File

@ -103,14 +103,18 @@ void Sprite::set_texture(const Ref<Texture>& p_texture) {
if (p_texture==texture)
return;
#ifdef DEBUG_ENABLED
if (texture.is_valid()) {
texture->disconnect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->update);
}
#endif
texture=p_texture;
#ifdef DEBUG_ENABLED
if (texture.is_valid()) {
texture->set_flags(texture->get_flags()); //remove repeat from texture, it looks bad in sprites
texture->connect(CoreStringNames::get_singleton()->changed,this,SceneStringNames::get_singleton()->update);
}
#endif
update();
item_rect_changed();
}
@ -313,17 +317,17 @@ void Sprite::_bind_methods() {
ADD_SIGNAL(MethodInfo("frame_changed"));
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame"));
ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region"));
ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect"));
ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture"));
ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v"));
ADD_PROPERTYNO( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes"));
ADD_PROPERTYNO( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes"));
ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame"));
ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region"));
ADD_PROPERTYNZ( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect"));
}
@ -530,10 +534,10 @@ void ViewportSprite::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_modulate","modulate"),&ViewportSprite::set_modulate);
ObjectTypeDB::bind_method(_MD("get_modulate"),&ViewportSprite::get_modulate);
ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "viewport"), _SCS("set_viewport_path"),_SCS("get_viewport_path"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
ADD_PROPERTY( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
ADD_PROPERTY( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
ADD_PROPERTYNZ( PropertyInfo( Variant::NODE_PATH, "viewport"), _SCS("set_viewport_path"),_SCS("get_viewport_path"));
ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "centered"), _SCS("set_centered"),_SCS("is_centered"));
ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
}

View File

@ -579,6 +579,10 @@ void TileMap::_make_quadrant_dirty(Map<PosKey,Quadrant>::Element *Q) {
call_deferred("_update_dirty_quadrants");
}
void TileMap::set_cellv(const Vector2& p_pos,int p_tile,bool p_flip_x,bool p_flip_y,bool p_transpose) {
set_cell(p_pos.x,p_pos.y,p_tile,p_flip_x,p_flip_y,p_transpose);
}
void TileMap::set_cell(int p_x,int p_y,int p_tile,bool p_flip_x,bool p_flip_y,bool p_transpose) {
@ -1106,6 +1110,7 @@ void TileMap::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_collision_bounce"),&TileMap::get_collision_bounce);
ObjectTypeDB::bind_method(_MD("set_cell","x","y","tile","flip_x","flip_y","transpose"),&TileMap::set_cell,DEFVAL(false),DEFVAL(false),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("set_cellv","pos","tile","flip_x","flip_y","transpose"),&TileMap::set_cellv,DEFVAL(false),DEFVAL(false),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_cell","x","y"),&TileMap::get_cell);
ObjectTypeDB::bind_method(_MD("is_cell_x_flipped","x","y"),&TileMap::is_cell_x_flipped);
ObjectTypeDB::bind_method(_MD("is_cell_y_flipped","x","y"),&TileMap::is_cell_y_flipped);

View File

@ -207,6 +207,8 @@ public:
bool is_cell_y_flipped(int p_x,int p_y) const;
bool is_cell_transposed(int p_x,int p_y) const;
void set_cellv(const Vector2& p_pos,int p_tile,bool p_flip_x=false,bool p_flip_y=false,bool p_transpose=false);
Rect2 get_item_rect() const;
void set_collision_layer(uint32_t p_layer);

View File

@ -299,8 +299,8 @@ void Area::set_enable_monitoring(bool p_enable) {
if (monitoring) {
PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(),this,"_body_inout");
PhysicsServer::get_singleton()->area_set_area_monitor_callback(get_rid(),this,"_area_inout");
PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(),this,SceneStringNames::get_singleton()->_body_inout);
PhysicsServer::get_singleton()->area_set_area_monitor_callback(get_rid(),this,SceneStringNames::get_singleton()->_area_inout);
} else {
PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(),NULL,StringName());
PhysicsServer::get_singleton()->area_set_area_monitor_callback(get_rid(),NULL,StringName());

View File

@ -122,8 +122,8 @@ bool CollisionObject::_set(const StringName& p_name, const Variant& p_value) {
} else if (name.begins_with("shapes/")) {
int idx=name.get_slice("/",1).to_int();
String what=name.get_slice("/",2);
int idx=name.get_slicec('/',1).to_int();
String what=name.get_slicec('/',2);
if (what=="shape")
set_shape(idx,RefPtr(p_value));
else if (what=="transform")
@ -148,8 +148,8 @@ bool CollisionObject::_get(const StringName& p_name,Variant &r_ret) const {
r_ret= shapes.size();
} else if (name.begins_with("shapes/")) {
int idx=name.get_slice("/",1).to_int();
String what=name.get_slice("/",2);
int idx=name.get_slicec('/',1).to_int();
String what=name.get_slicec('/',2);
if (what=="shape")
r_ret= get_shape(idx);
else if (what=="transform")

View File

@ -41,8 +41,8 @@ bool Skeleton::_set(const StringName& p_path, const Variant& p_value) {
if (!path.begins_with("bones/"))
return false;
int which=path.get_slice("/",1).to_int();
String what=path.get_slice("/",2);
int which=path.get_slicec('/',1).to_int();
String what=path.get_slicec('/',2);
if (which==bones.size() && what=="name") {
@ -88,8 +88,8 @@ bool Skeleton::_get(const StringName& p_name,Variant &r_ret) const {
if (!path.begins_with("bones/"))
return false;
int which=path.get_slice("/",1).to_int();
String what=path.get_slice("/",2);
int which=path.get_slicec('/',1).to_int();
String what=path.get_slicec('/',2);
ERR_FAIL_INDEX_V( which, bones.size(), false );

View File

@ -758,7 +758,7 @@ void Spatial::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"transform/rotation",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), _SCS("_set_rotation_deg"), _SCS("_get_rotation_deg") );
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"transform/rotation_rad",PROPERTY_HINT_NONE,"",0), _SCS("set_rotation"), _SCS("get_rotation") );
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"transform/scale",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_EDITOR), _SCS("set_scale"), _SCS("get_scale") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/visible"), _SCS("_set_visible_"), _SCS("_is_visible_") );
ADD_PROPERTYNO( PropertyInfo(Variant::BOOL,"visibility/visible"), _SCS("_set_visible_"), _SCS("_is_visible_") );
//ADD_PROPERTY( PropertyInfo(Variant::TRANSFORM,"transform/local"), _SCS("set_transform"), _SCS("get_transform") );
ADD_SIGNAL( MethodInfo("visibility_changed" ) );

View File

@ -35,10 +35,10 @@ bool AnimationPlayer::_set(const StringName& p_name, const Variant& p_value) {
String name=p_name;
if (name=="playback/speed" || name=="speed") { //bw compatibility
if (p_name==SceneStringNames::get_singleton()->playback_speed || p_name==SceneStringNames::get_singleton()->speed) { //bw compatibility
set_speed(p_value);
} else if (name=="playback/active") {
} else if (p_name==SceneStringNames::get_singleton()->playback_active) {
set_active(p_value);
} else if (name.begins_with("playback/play")) {
@ -52,16 +52,16 @@ bool AnimationPlayer::_set(const StringName& p_name, const Variant& p_value) {
} else if (name.begins_with("anims/")) {
String which=name.get_slice("/",1);
String which=name.get_slicec('/',1);
add_animation(which,p_value);
} else if (name.begins_with("next/")) {
String which=name.get_slice("/",1);
String which=name.get_slicec('/',1);
animation_set_next(which,p_value);
} else if (name=="blend_times") {
} else if (p_name==SceneStringNames::get_singleton()->blend_times) {
Array array=p_value;
int len = array.size();
@ -77,7 +77,7 @@ bool AnimationPlayer::_set(const StringName& p_name, const Variant& p_value) {
set_blend_time(from,to,time);
}
} else if (name=="autoplay") {
} else if (p_name==SceneStringNames::get_singleton()->autoplay) {
autoplay=p_value;
} else
@ -106,12 +106,12 @@ bool AnimationPlayer::_get(const StringName& p_name,Variant &r_ret) const {
} else if (name.begins_with("anims/")) {
String which=name.get_slice("/",1);
String which=name.get_slicec('/',1);
r_ret= get_animation(which).get_ref_ptr();
} else if (name.begins_with("next/")) {
String which=name.get_slice("/",1);
String which=name.get_slicec('/',1);
r_ret= animation_get_next(which);
@ -661,8 +661,11 @@ void AnimationPlayer::_animation_process(float p_delta) {
Error AnimationPlayer::add_animation(const StringName& p_name, const Ref<Animation>& p_animation) {
#ifdef DEBUG_ENABLED
ERR_EXPLAIN("Invalid animation name: "+String(p_name));
ERR_FAIL_COND_V( String(p_name).find("/")!=-1 || String(p_name).find(":")!=-1 || String(p_name).find(",")!=-1 || String(p_name).find("[")!=-1, ERR_INVALID_PARAMETER );
#endif
ERR_FAIL_COND_V( p_animation.is_null() , ERR_INVALID_PARAMETER );
//print_line("Add anim: "+String(p_name)+" name: "+p_animation->get_name());
@ -1271,7 +1274,7 @@ AnimationPlayer::AnimationPlayer() {
animation_process_mode=ANIMATION_PROCESS_IDLE;
processing=false;
default_blend_time=0;
root=NodePath("..");
root=SceneStringNames::get_singleton()->path_pp;
playing = false;
active=true;
}

View File

@ -102,7 +102,7 @@ bool SamplePlayer::_get(const StringName& p_name,Variant &r_ret) const {
r_ret= get_sample_library();
} else if (name.begins_with("default/")) {
String what=name.get_slice("/",1);
String what=name.get_slicec('/',1);
if (what=="volume_db")
r_ret= get_default_volume_db();

View File

@ -390,10 +390,10 @@ void BaseButton::_bind_methods() {
ADD_SIGNAL( MethodInfo("pressed" ) );
ADD_SIGNAL( MethodInfo("released" ) );
ADD_SIGNAL( MethodInfo("toggled", PropertyInfo( Variant::BOOL,"pressed") ) );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "disabled"), _SCS("set_disabled"), _SCS("is_disabled"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "disabled"), _SCS("set_disabled"), _SCS("is_disabled"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "toggle_mode"), _SCS("set_toggle_mode"), _SCS("is_toggle_mode"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "is_pressed"), _SCS("set_pressed"), _SCS("is_pressed"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "click_on_press"), _SCS("set_click_on_press"), _SCS("get_click_on_press"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "is_pressed"), _SCS("set_pressed"), _SCS("is_pressed"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "click_on_press"), _SCS("set_click_on_press"), _SCS("get_click_on_press"));
BIND_CONSTANT( DRAW_NORMAL );

View File

@ -225,11 +225,11 @@ void Button::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_text_align"),&Button::get_text_align);
ObjectTypeDB::bind_method(_MD("is_flat"),&Button::is_flat);
ADD_PROPERTY( PropertyInfo( Variant::STRING, "text", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT_INTL ), _SCS("set_text"),_SCS("get_text") );
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture" ), _SCS("set_button_icon"),_SCS("get_button_icon") );
ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "text", PROPERTY_HINT_NONE,"",PROPERTY_USAGE_DEFAULT_INTL ), _SCS("set_text"),_SCS("get_text") );
ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture" ), _SCS("set_button_icon"),_SCS("get_button_icon") );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "flat" ), _SCS("set_flat"),_SCS("is_flat") );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "clip_text" ), _SCS("set_clip_text"),_SCS("get_clip_text") );
ADD_PROPERTY( PropertyInfo( Variant::INT, "align",PROPERTY_HINT_ENUM,"Left,Center,Right" ), _SCS("set_text_align"),_SCS("get_text_align") );
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "clip_text" ), _SCS("set_clip_text"),_SCS("get_clip_text") );
ADD_PROPERTYNO( PropertyInfo( Variant::INT, "align",PROPERTY_HINT_ENUM,"Left,Center,Right" ), _SCS("set_text_align"),_SCS("get_text_align") );
}

View File

@ -34,7 +34,7 @@ bool ButtonArray::_set(const StringName& p_name, const Variant& p_value) {
String n=String(p_name);
if (n.begins_with("button/")) {
String what = n.get_slice("/",1);
String what = n.get_slicec('/',1);
if (what=="count") {
int new_size=p_value;
if (new_size>0 && buttons.size()==0) {
@ -57,7 +57,7 @@ bool ButtonArray::_set(const StringName& p_name, const Variant& p_value) {
} else {
int idx=what.to_int();
ERR_FAIL_INDEX_V(idx,buttons.size(),false);
String f = n.get_slice("/",2);
String f = n.get_slicec('/',2);
if (f=="text")
buttons[idx].text=p_value;
else if (f=="icon")
@ -80,7 +80,7 @@ bool ButtonArray::_get(const StringName& p_name,Variant &r_ret) const {
String n=String(p_name);
if (n.begins_with("button/")) {
String what = n.get_slice("/",1);
String what = n.get_slicec('/',1);
if (what=="count") {
r_ret=buttons.size();
} else if (what=="align") {
@ -92,7 +92,7 @@ bool ButtonArray::_get(const StringName& p_name,Variant &r_ret) const {
} else {
int idx=what.to_int();
ERR_FAIL_INDEX_V(idx,buttons.size(),false);
String f = n.get_slice("/",2);
String f = n.get_slicec('/',2);
if (f=="text")
r_ret=buttons[idx].text;
else if (f=="icon")

View File

@ -136,27 +136,27 @@ bool Control::_set(const StringName& p_name, const Variant& p_value) {
if (p_value.get_type()==Variant::NIL) {
if (name.begins_with("custom_icons/")) {
String dname = name.get_slice("/",1);
String dname = name.get_slicec('/',1);
data.icon_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
update();
} else if (name.begins_with("custom_styles/")) {
String dname = name.get_slice("/",1);
String dname = name.get_slicec('/',1);
data.style_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
update();
} else if (name.begins_with("custom_fonts/")) {
String dname = name.get_slice("/",1);
String dname = name.get_slicec('/',1);
data.font_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
update();
} else if (name.begins_with("custom_colors/")) {
String dname = name.get_slice("/",1);
String dname = name.get_slicec('/',1);
data.color_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
update();
} else if (name.begins_with("custom_constants/")) {
String dname = name.get_slice("/",1);
String dname = name.get_slicec('/',1);
data.constant_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
update();
@ -165,23 +165,23 @@ bool Control::_set(const StringName& p_name, const Variant& p_value) {
} else {
if (name.begins_with("custom_icons/")) {
String dname = name.get_slice("/",1);
String dname = name.get_slicec('/',1);
notification(NOTIFICATION_THEME_CHANGED);
add_icon_override(dname,p_value);
} else if (name.begins_with("custom_styles/")) {
String dname = name.get_slice("/",1);
String dname = name.get_slicec('/',1);
add_style_override(dname,p_value);
notification(NOTIFICATION_THEME_CHANGED);
} else if (name.begins_with("custom_fonts/")) {
String dname = name.get_slice("/",1);
String dname = name.get_slicec('/',1);
add_font_override(dname,p_value);
notification(NOTIFICATION_THEME_CHANGED);
} else if (name.begins_with("custom_colors/")) {
String dname = name.get_slice("/",1);
String dname = name.get_slicec('/',1);
add_color_override(dname,p_value);
notification(NOTIFICATION_THEME_CHANGED);
} else if (name.begins_with("custom_constants/")) {
String dname = name.get_slice("/",1);
String dname = name.get_slicec('/',1);
add_constant_override(dname,p_value);
notification(NOTIFICATION_THEME_CHANGED);
} else
@ -217,22 +217,22 @@ bool Control::_get(const StringName& p_name,Variant &r_ret) const {
return false;
if (sname.begins_with("custom_icons/")) {
String name = sname.get_slice("/",1);
String name = sname.get_slicec('/',1);
r_ret= data.icon_override.has(name)?Variant(data.icon_override[name]):Variant();
} else if (sname.begins_with("custom_styles/")) {
String name = sname.get_slice("/",1);
String name = sname.get_slicec('/',1);
r_ret= data.style_override.has(name)?Variant(data.style_override[name]):Variant();
} else if (sname.begins_with("custom_fonts/")) {
String name = sname.get_slice("/",1);
String name = sname.get_slicec('/',1);
r_ret= data.font_override.has(name)?Variant(data.font_override[name]):Variant();
} else if (sname.begins_with("custom_colors/")) {
String name = sname.get_slice("/",1);
String name = sname.get_slicec('/',1);
r_ret= data.color_override.has(name)?Variant(data.color_override[name]):Variant();
} else if (sname.begins_with("custom_constants/")) {
String name = sname.get_slice("/",1);
String name = sname.get_slicec('/',1);
r_ret= data.constant_override.has(name)?Variant(data.constant_override[name]):Variant();
} else
@ -2832,16 +2832,16 @@ void Control::_bind_methods() {
ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect/size", PROPERTY_HINT_NONE, "",PROPERTY_USAGE_EDITOR), _SCS("set_size"),_SCS("get_size") );
ADD_PROPERTYNZ( PropertyInfo(Variant::VECTOR2,"rect/min_size"), _SCS("set_custom_minimum_size"),_SCS("get_custom_minimum_size") );
ADD_PROPERTYNZ( PropertyInfo(Variant::STRING,"hint/tooltip", PROPERTY_HINT_MULTILINE_TEXT), _SCS("set_tooltip"),_SCS("_get_tooltip") );
ADD_PROPERTYI( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/left" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_LEFT );
ADD_PROPERTYI( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/top" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_TOP );
ADD_PROPERTYI( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/right" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_RIGHT );
ADD_PROPERTYI( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/bottom" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_BOTTOM );
ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/left" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_LEFT );
ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/top" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_TOP );
ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/right" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_RIGHT );
ADD_PROPERTYINZ( PropertyInfo(Variant::NODE_PATH,"focus_neighbour/bottom" ), _SCS("set_focus_neighbour"),_SCS("get_focus_neighbour"),MARGIN_BOTTOM );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"focus/ignore_mouse"), _SCS("set_ignore_mouse"),_SCS("is_ignoring_mouse") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"focus/stop_mouse"), _SCS("set_stop_mouse"),_SCS("is_stopping_mouse") );
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"size_flags/horizontal", PROPERTY_HINT_FLAGS, "Expand,Fill"), _SCS("set_h_size_flags"),_SCS("get_h_size_flags") );
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"size_flags/vertical", PROPERTY_HINT_FLAGS, "Expand,Fill"), _SCS("set_v_size_flags"),_SCS("get_v_size_flags") );
ADD_PROPERTY( PropertyInfo(Variant::INT,"size_flags/stretch_ratio", PROPERTY_HINT_RANGE, "1,128,0.01"), _SCS("set_stretch_ratio"),_SCS("get_stretch_ratio") );
ADD_PROPERTYNO( PropertyInfo(Variant::INT,"size_flags/stretch_ratio", PROPERTY_HINT_RANGE, "1,128,0.01"), _SCS("set_stretch_ratio"),_SCS("get_stretch_ratio") );
ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"theme/theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), _SCS("set_theme"),_SCS("get_theme") );
BIND_CONSTANT( ANCHOR_BEGIN );

View File

@ -613,11 +613,11 @@ void Label::_bind_methods() {
BIND_CONSTANT( VALIGN_BOTTOM );
BIND_CONSTANT( VALIGN_FILL );
ADD_PROPERTY( PropertyInfo( Variant::STRING, "text",PROPERTY_HINT_MULTILINE_TEXT,"",PROPERTY_USAGE_DEFAULT_INTL), _SCS("set_text"),_SCS("get_text") );
ADD_PROPERTY( PropertyInfo( Variant::INT, "align", PROPERTY_HINT_ENUM,"Left,Center,Right,Fill" ),_SCS("set_align"),_SCS("get_align") );
ADD_PROPERTY( PropertyInfo( Variant::INT, "valign", PROPERTY_HINT_ENUM,"Top,Center,Bottom,Fill" ),_SCS("set_valign"),_SCS("get_valign") );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "autowrap"),_SCS("set_autowrap"),_SCS("has_autowrap") );
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "uppercase"),_SCS("set_uppercase"),_SCS("is_uppercase") );
ADD_PROPERTYNZ( PropertyInfo( Variant::STRING, "text",PROPERTY_HINT_MULTILINE_TEXT,"",PROPERTY_USAGE_DEFAULT_INTL), _SCS("set_text"),_SCS("get_text") );
ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "align", PROPERTY_HINT_ENUM,"Left,Center,Right,Fill" ),_SCS("set_align"),_SCS("get_align") );
ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "valign", PROPERTY_HINT_ENUM,"Top,Center,Bottom,Fill" ),_SCS("set_valign"),_SCS("get_valign") );
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "autowrap"),_SCS("set_autowrap"),_SCS("has_autowrap") );
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "uppercase"),_SCS("set_uppercase"),_SCS("is_uppercase") );
ADD_PROPERTY( PropertyInfo( Variant::REAL, "percent_visible", PROPERTY_HINT_RANGE,"0,1,0.001"),_SCS("set_percent_visible"),_SCS("get_percent_visible") );
}

View File

@ -56,7 +56,14 @@ Size2 Tabs::get_minimum_size() const {
else
ms.width+=tab_bg->get_minimum_size().width;
if (tabs[i].right_button.is_valid()) {
Ref<Texture> rb=tabs[i].right_button;
Size2 bms = rb->get_size()+get_stylebox("button")->get_minimum_size();
bms.width+=get_constant("hseparation");
ms.width+=bms.width;
ms.height=MAX(bms.height+tab_bg->get_minimum_size().height,ms.height);
}
}
return ms;
@ -66,6 +73,39 @@ Size2 Tabs::get_minimum_size() const {
void Tabs::_input_event(const InputEvent& p_event) {
if (p_event.type==InputEvent::MOUSE_MOTION) {
Point2 pos( p_event.mouse_motion.x, p_event.mouse_motion.y );
int hover=-1;
for(int i=0;i<tabs.size();i++) {
if (tabs[i].rb_rect.has_point(pos)) {
hover=i;
break;
}
}
if (hover!=rb_hover) {
rb_hover=hover;
update();
}
return;
}
if (rb_pressing && p_event.type==InputEvent::MOUSE_BUTTON &&
!p_event.mouse_button.pressed &&
p_event.mouse_button.button_index==BUTTON_LEFT) {
if (rb_hover!=-1) {
//pressed
emit_signal("right_button_pressed",rb_hover);
}
rb_pressing=false;
update();
}
if (p_event.type==InputEvent::MOUSE_BUTTON &&
p_event.mouse_button.pressed &&
p_event.mouse_button.button_index==BUTTON_LEFT) {
@ -76,6 +116,12 @@ void Tabs::_input_event(const InputEvent& p_event) {
int found=-1;
for(int i=0;i<tabs.size();i++) {
if (tabs[i].rb_rect.has_point(pos)) {
rb_pressing=true;
update();
return;
}
int ofs=tabs[i].ofs_cache;
int size = tabs[i].ofs_cache;
if (pos.x >=tabs[i].ofs_cache && pos.x<tabs[i].ofs_cache+tabs[i].size_cache) {
@ -100,7 +146,10 @@ void Tabs::_notification(int p_what) {
switch(p_what) {
case NOTIFICATION_MOUSE_EXIT: {
rb_hover=-1;
update();
} break;
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
@ -142,7 +191,7 @@ void Tabs::_notification(int p_what) {
Ref<Texture> icon;
if (tabs[i].icon.is_valid()) {
Ref<Texture> icon = tabs[i].icon;
icon = tabs[i].icon;
if (icon.is_valid()) {
lsize+=icon->get_width();
if (s!="")
@ -151,6 +200,16 @@ void Tabs::_notification(int p_what) {
}
}
if (tabs[i].right_button.is_valid()) {
Ref<StyleBox> style = get_stylebox("button");
Ref<Texture> rb=tabs[i].right_button;
lsize+=get_constant("hseparation");
lsize+=style->get_margin(MARGIN_LEFT);
lsize+=rb->get_width();
lsize+=style->get_margin(MARGIN_RIGHT);
}
Ref<StyleBox> sb;
int va;
@ -184,7 +243,37 @@ void Tabs::_notification(int p_what) {
font->draw(ci, Point2i( w, sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-font->get_height())/2+font->get_ascent() ), s, col );
w+=slen+sb->get_margin(MARGIN_RIGHT);
w+=slen;
if (tabs[i].right_button.is_valid()) {
Ref<StyleBox> style = get_stylebox("button");
Ref<Texture> rb=tabs[i].right_button;
w+=get_constant("hseparation");
Rect2 rb_rect;
rb_rect.size=style->get_minimum_size()+rb->get_size();
rb_rect.pos.x=w;
rb_rect.pos.y=sb->get_margin(MARGIN_TOP)+((sb_rect.size.y-sb_ms.y)-(rb_rect.size.y))/2;
if (rb_hover==i) {
if (rb_pressing)
get_stylebox("button_pressed")->draw(ci,rb_rect);
else
style->draw(ci,rb_rect);
}
w+=style->get_margin(MARGIN_LEFT);
rb->draw(ci,Point2i( w,rb_rect.pos.y+style->get_margin(MARGIN_TOP) ));
w+=rb->get_width();
w+=style->get_margin(MARGIN_RIGHT);
tabs[i].rb_rect=rb_rect;
}
w+=sb->get_margin(MARGIN_RIGHT);
tabs[i].size_cache=w-tabs[i].ofs_cache;
@ -252,6 +341,23 @@ Ref<Texture> Tabs::get_tab_icon(int p_tab) const{
}
void Tabs::set_tab_right_button(int p_tab,const Ref<Texture>& p_right_button){
ERR_FAIL_INDEX(p_tab,tabs.size());
tabs[p_tab].right_button=p_right_button;
update();
minimum_size_changed();
}
Ref<Texture> Tabs::get_tab_right_button(int p_tab) const{
ERR_FAIL_INDEX_V(p_tab,tabs.size(),Ref<Texture>());
return tabs[p_tab].right_button;
}
void Tabs::add_tab(const String& p_str,const Ref<Texture>& p_icon) {
Tab t;
@ -316,6 +422,7 @@ void Tabs::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_tab_align"),&Tabs::get_tab_align);
ADD_SIGNAL(MethodInfo("tab_changed",PropertyInfo(Variant::INT,"tab")));
ADD_SIGNAL(MethodInfo("right_button_pressed",PropertyInfo(Variant::INT,"tab")));
ADD_PROPERTY( PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE,"-1,4096,1",PROPERTY_USAGE_EDITOR), _SCS("set_current_tab"), _SCS("get_current_tab") );
@ -328,5 +435,7 @@ Tabs::Tabs() {
current=0;
tab_align=ALIGN_CENTER;
rb_hover=-1;
rb_pressing=false;
}

Some files were not shown because too many files have changed in this diff Show More