This commit is contained in:
Mariano Javier Suligoy 2015-08-03 17:28:33 -03:00
commit c88038228a
50 changed files with 2988 additions and 1459 deletions

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

@ -1678,12 +1678,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);
};

View file

@ -436,6 +436,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

@ -127,7 +127,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 +150,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 +243,8 @@ void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) {
if (request_scene_tree)
request_scene_tree(request_scene_tree_ud);
} else {
_parse_live_edit(cmd);
}
@ -301,6 +303,105 @@ void ScriptDebuggerRemote::line_poll() {
}
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 +422,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 +432,8 @@ void ScriptDebuggerRemote::_poll_events() {
if (request_scene_tree)
request_scene_tree(request_scene_tree_ud);
} else {
_parse_live_edit(cmd);
}
}
@ -413,6 +516,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,6 +537,7 @@ ScriptDebuggerRemote::ScriptDebuggerRemote() {
last_perf_time=0;
poll_every=0;
request_scene_tree=NULL;
live_edit_funcs=NULL;
}

View file

@ -62,9 +62,12 @@ 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;
public:
@ -79,6 +82,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

@ -238,6 +238,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 +278,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 +293,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

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

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

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

View file

@ -29,7 +29,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

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

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

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

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

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

View file

@ -51,6 +51,8 @@ private:
Ref<Texture> icon;
int ofs_cache;
int size_cache;
Ref<Texture> right_button;
Rect2 rb_rect;
};
Vector<Tab> tabs;
@ -58,6 +60,8 @@ private:
Control *_get_tab(int idx) const;
int _get_top_margin() const;
TabAlign tab_align;
int rb_hover;
bool rb_pressing;
protected:
@ -75,6 +79,9 @@ public:
void set_tab_icon(int p_tab,const Ref<Texture>& p_icon);
Ref<Texture> get_tab_icon(int p_tab) const;
void set_tab_right_button(int p_tab,const Ref<Texture>& p_right_button);
Ref<Texture> get_tab_right_button(int p_tab) const;
void set_tab_align(TabAlign p_align);
TabAlign get_tab_align() const;

View file

@ -196,6 +196,14 @@ void Node::_propagate_enter_tree() {
}
data.blocked--;
#ifdef DEBUG_ENABLED
if (ScriptDebugger::get_singleton() && data.filename!=String()) {
//used for live edit
data.tree->live_scene_edit_cache[data.filename].insert(this);
}
#endif
// enter groups
}
@ -205,6 +213,28 @@ void Node::_propagate_exit_tree() {
//block while removing children
#ifdef DEBUG_ENABLED
if (ScriptDebugger::get_singleton() && data.filename!=String()) {
//used for live edit
Map<String,Set<Node*> >::Element *E=data.tree->live_scene_edit_cache.find(data.filename);
if (E) {
E->get().erase(this);
if (E->get().size()==0) {
data.tree->live_scene_edit_cache.erase(E);
}
}
Map<Node*,Map<ObjectID,Node*> >::Element *F=data.tree->live_edit_remove_list.find(this);
if (F) {
for (Map<ObjectID,Node*>::Element*G=F->get().front();G;G=G->next()) {
memdelete(G->get());
}
data.tree->live_edit_remove_list.erase(F);
}
}
#endif
data.blocked++;
for (int i=data.children.size()-1;i>=0;i--) {
@ -552,6 +582,52 @@ void Node::set_human_readable_collision_renaming(bool p_enabled) {
}
String Node::validate_child_name(const String& p_name) const {
//this approach to autoset node names is human readable but very slow
//it's turned on while running in the editor
String basename = p_name;
if (basename==String()) {
return String();
}
int val=1;
for(;;) {
String attempted = val > 1 ? (basename + " " +itos(val) ) : basename;
bool found=false;
for (int i=0;i<data.children.size();i++) {
//if (data.children[i]==p_child)
// continue;
if (data.children[i]->get_name() == attempted) {
found=true;
break;
}
}
if (found) {
val++;
continue;
}
return attempted;
break;
}
return basename;
}
void Node::_validate_child_name(Node *p_child) {
/* Make sure the name is unique */
@ -1323,18 +1399,31 @@ int Node::get_position_in_parent() const {
Node *Node::duplicate() const {
Node *Node::duplicate(bool p_use_instancing) const {
Node *node=NULL;
Object *obj = ObjectTypeDB::instance(get_type());
ERR_FAIL_COND_V(!obj,NULL);
node = obj->cast_to<Node>();
if (!node)
memdelete(obj);
ERR_FAIL_COND_V(!node,NULL);
bool instanced=false;
if (p_use_instancing && get_filename()!=String()) {
Ref<PackedScene> res = ResourceLoader::load(get_filename());
ERR_FAIL_COND_V(res.is_null(),NULL);
node=res->instance();
ERR_FAIL_COND_V(!node,NULL);
instanced=true;
} else {
Object *obj = ObjectTypeDB::instance(get_type());
ERR_FAIL_COND_V(!obj,NULL);
node = obj->cast_to<Node>();
if (!node)
memdelete(obj);
ERR_FAIL_COND_V(!node,NULL);
}
if (get_filename()!="") { //an instance
@ -1360,7 +1449,10 @@ Node *Node::duplicate() const {
if (get_child(i)->data.parent_owned)
continue;
Node *dup = get_child(i)->duplicate();
if (instanced && get_child(i)->data.owner==this)
continue; //part of instance
Node *dup = get_child(i)->duplicate(p_use_instancing);
if (!dup) {
memdelete(node);
@ -1882,7 +1974,7 @@ void Node::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_tree:SceneTree"),&Node::get_tree);
ObjectTypeDB::bind_method(_MD("duplicate:Node"),&Node::duplicate);
ObjectTypeDB::bind_method(_MD("duplicate:Node","use_instancing"),&Node::duplicate,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("replace_by","node:Node","keep_data"),&Node::replace_by,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("get_viewport"),&Node::get_viewport);

View file

@ -255,8 +255,9 @@ public:
int get_position_in_parent() const;
Node *duplicate() const;
Node *duplicate(bool p_use_instancing=false) const;
Node *duplicate_and_reown(const Map<Node*,Node*>& p_reown_map) const;
//Node *clone_tree() const;
// used by editors, to save what has changed only
@ -275,6 +276,8 @@ public:
static void print_stray_nodes();
String validate_child_name(const String& p_name) const;
void queue_delete();
//shitty hacks for speed

View file

@ -1044,7 +1044,371 @@ void SceneTree::add_current_scene(Node * p_current) {
current_scene=p_current;
root->add_child(p_current);
}
#ifdef DEBUG_ENABLED
void SceneTree::_live_edit_node_path_func(const NodePath &p_path,int p_id) {
live_edit_node_path_cache[p_id]=p_path;
}
void SceneTree::_live_edit_res_path_func(const String &p_path,int p_id) {
live_edit_resource_cache[p_id]=p_path;
}
void SceneTree::_live_edit_node_set_func(int p_id,const StringName& p_prop,const Variant& p_value) {
if (!live_edit_node_path_cache.has(p_id))
return;
NodePath np = live_edit_node_path_cache[p_id];
Node *base = NULL;
if (root->has_node(live_edit_root))
base = root->get_node(live_edit_root);
Map<String,Set<Node*> >::Element *E=live_scene_edit_cache.find(live_edit_scene);
if (!E)
return; //scene not editable
for(Set<Node*>::Element *F=E->get().front();F;F=F->next()) {
Node *n=F->get();
if (base && !base->is_a_parent_of(n))
continue;
if (!n->has_node(np))
continue;
Node *n2 = n->get_node(np);
n2->set(p_prop,p_value);
}
}
void SceneTree::_live_edit_node_set_res_func(int p_id,const StringName& p_prop,const String& p_value) {
RES r = ResourceLoader::load(p_value);
if (!r.is_valid())
return;
_live_edit_node_set_func(p_id,p_prop,r);
}
void SceneTree::_live_edit_node_call_func(int p_id,const StringName& p_method,VARIANT_ARG_DECLARE) {
if (!live_edit_node_path_cache.has(p_id))
return;
NodePath np = live_edit_node_path_cache[p_id];
Node *base = NULL;
if (root->has_node(live_edit_root))
base = root->get_node(live_edit_root);
Map<String,Set<Node*> >::Element *E=live_scene_edit_cache.find(live_edit_scene);
if (!E)
return; //scene not editable
for(Set<Node*>::Element *F=E->get().front();F;F=F->next()) {
Node *n=F->get();
if (base && !base->is_a_parent_of(n))
continue;
if (!n->has_node(np))
continue;
Node *n2 = n->get_node(np);
n2->call(p_method,VARIANT_ARG_PASS);
}
}
void SceneTree::_live_edit_res_set_func(int p_id,const StringName& p_prop,const Variant& p_value) {
if (!live_edit_resource_cache.has(p_id))
return;
String resp = live_edit_resource_cache[p_id];
if (!ResourceCache::has(resp))
return;
RES r = ResourceCache::get(resp);
if (!r.is_valid())
return;
r->set(p_prop,p_value);
}
void SceneTree::_live_edit_res_set_res_func(int p_id,const StringName& p_prop,const String& p_value) {
RES r = ResourceLoader::load(p_value);
if (!r.is_valid())
return;
_live_edit_res_set_func(p_id,p_prop,r);
}
void SceneTree::_live_edit_res_call_func(int p_id,const StringName& p_method,VARIANT_ARG_DECLARE) {
if (!live_edit_resource_cache.has(p_id))
return;
String resp = live_edit_resource_cache[p_id];
if (!ResourceCache::has(resp))
return;
RES r = ResourceCache::get(resp);
if (!r.is_valid())
return;
r->call(p_method,VARIANT_ARG_PASS);
}
void SceneTree::_live_edit_root_func(const NodePath& p_scene_path,const String& p_scene_from) {
live_edit_root=p_scene_path;
live_edit_scene=p_scene_from;
}
void SceneTree::_live_edit_create_node_func(const NodePath& p_parent,const String& p_type,const String& p_name) {
Node *base = NULL;
if (root->has_node(live_edit_root))
base = root->get_node(live_edit_root);
Map<String,Set<Node*> >::Element *E=live_scene_edit_cache.find(live_edit_scene);
if (!E)
return; //scene not editable
for(Set<Node*>::Element *F=E->get().front();F;F=F->next()) {
Node *n=F->get();
if (base && !base->is_a_parent_of(n))
continue;
if (!n->has_node(p_parent))
continue;
Node *n2 = n->get_node(p_parent);
Object *o = ObjectTypeDB::instance(p_type);
if (!o)
continue;
Node *no=o->cast_to<Node>();
no->set_name(p_name);
n2->add_child(no);
}
}
void SceneTree::_live_edit_instance_node_func(const NodePath& p_parent,const String& p_path,const String& p_name){
Ref<PackedScene> ps = ResourceLoader::load(p_path);
if (!ps.is_valid())
return;
Node *base = NULL;
if (root->has_node(live_edit_root))
base = root->get_node(live_edit_root);
Map<String,Set<Node*> >::Element *E=live_scene_edit_cache.find(live_edit_scene);
if (!E)
return; //scene not editable
for(Set<Node*>::Element *F=E->get().front();F;F=F->next()) {
Node *n=F->get();
if (base && !base->is_a_parent_of(n))
continue;
if (!n->has_node(p_parent))
continue;
Node *n2 = n->get_node(p_parent);
Node *no=ps->instance();
no->set_name(p_name);
n2->add_child(no);
}
}
void SceneTree::_live_edit_remove_node_func(const NodePath& p_at){
Node *base = NULL;
if (root->has_node(live_edit_root))
base = root->get_node(live_edit_root);
Map<String,Set<Node*> >::Element *E=live_scene_edit_cache.find(live_edit_scene);
if (!E)
return; //scene not editable
for(Set<Node*>::Element *F=E->get().front();F;) {
Set<Node*>::Element *N=F->next();
Node *n=F->get();
if (base && !base->is_a_parent_of(n))
continue;
if (!n->has_node(p_at))
continue;
Node *n2 = n->get_node(p_at);
memdelete(n2);
F=N;
}
}
void SceneTree::_live_edit_remove_and_keep_node_func(const NodePath& p_at,ObjectID p_keep_id){
Node *base = NULL;
if (root->has_node(live_edit_root))
base = root->get_node(live_edit_root);
Map<String,Set<Node*> >::Element *E=live_scene_edit_cache.find(live_edit_scene);
if (!E)
return; //scene not editable
for(Set<Node*>::Element *F=E->get().front();F;) {
Set<Node*>::Element *N=F->next();
Node *n=F->get();
if (base && !base->is_a_parent_of(n))
continue;
if (!n->has_node(p_at))
continue;
Node *n2 = n->get_node(p_at);
n2->get_parent()->remove_child(n2);
live_edit_remove_list[n][p_keep_id]=n2;
F=N;
}
}
void SceneTree::_live_edit_restore_node_func(ObjectID p_id,const NodePath& p_at,int p_at_pos){
Node *base = NULL;
if (root->has_node(live_edit_root))
base = root->get_node(live_edit_root);
Map<String,Set<Node*> >::Element *E=live_scene_edit_cache.find(live_edit_scene);
if (!E)
return; //scene not editable
for(Set<Node*>::Element *F=E->get().front();F;) {
Set<Node*>::Element *N=F->next();
Node *n=F->get();
if (base && !base->is_a_parent_of(n))
continue;
if (!n->has_node(p_at))
continue;
Node *n2 = n->get_node(p_at);
Map<Node*,Map<ObjectID,Node*> >::Element *EN=live_edit_remove_list.find(n);
if (!EN)
continue;
Map<ObjectID,Node*>::Element *FN=EN->get().find(p_id);
if (!FN)
continue;
n2->add_child(FN->get());
EN->get().erase(FN);
if (EN->get().size()==0) {
live_edit_remove_list.erase(EN);
}
F=N;
}
}
void SceneTree::_live_edit_duplicate_node_func(const NodePath& p_at,const String& p_new_name){
Node *base = NULL;
if (root->has_node(live_edit_root))
base = root->get_node(live_edit_root);
Map<String,Set<Node*> >::Element *E=live_scene_edit_cache.find(live_edit_scene);
if (!E)
return; //scene not editable
for(Set<Node*>::Element *F=E->get().front();F;F=F->next()) {
Node *n=F->get();
if (base && !base->is_a_parent_of(n))
continue;
if (!n->has_node(p_at))
continue;
Node *n2 = n->get_node(p_at);
Node *dup = n2->duplicate(true);
if (!dup)
continue;
dup->set_name(p_new_name);
n2->get_parent()->add_child(dup);
}
}
void SceneTree::_live_edit_reparent_node_func(const NodePath& p_at,const NodePath& p_new_place,const String& p_new_name,int p_at_pos){
Node *base = NULL;
if (root->has_node(live_edit_root))
base = root->get_node(live_edit_root);
Map<String,Set<Node*> >::Element *E=live_scene_edit_cache.find(live_edit_scene);
if (!E)
return; //scene not editable
for(Set<Node*>::Element *F=E->get().front();F;F=F->next()) {
Node *n=F->get();
if (base && !base->is_a_parent_of(n))
continue;
if (!n->has_node(p_at))
continue;
Node *nfrom = n->get_node(p_at);
if (!n->has_node(p_new_place))
continue;
Node *nto = n->get_node(p_new_place);
nfrom->get_parent()->remove_child(nfrom);
nfrom->set_name(p_new_name);
nto->add_child(nfrom);
if (p_at_pos>=0)
nto->move_child(nfrom,p_at_pos);
}
}
#endif
void SceneTree::_bind_methods() {
@ -1169,6 +1533,35 @@ SceneTree::SceneTree() {
edited_scene_root=NULL;
#endif
#ifdef DEBUG_ENABLED
live_edit_funcs.udata=this;
live_edit_funcs.node_path_func=_live_edit_node_path_funcs;
live_edit_funcs.res_path_func=_live_edit_res_path_funcs;
live_edit_funcs.node_set_func=_live_edit_node_set_funcs;
live_edit_funcs.node_set_res_func=_live_edit_node_set_res_funcs;
live_edit_funcs.node_call_func=_live_edit_node_call_funcs;
live_edit_funcs.res_set_func=_live_edit_res_set_funcs;
live_edit_funcs.res_set_res_func=_live_edit_res_set_res_funcs;
live_edit_funcs.res_call_func=_live_edit_res_call_funcs;
live_edit_funcs.root_func=_live_edit_root_funcs;
live_edit_funcs.tree_create_node_func=_live_edit_create_node_funcs;
live_edit_funcs.tree_instance_node_func=_live_edit_instance_node_funcs;
live_edit_funcs.tree_remove_node_func=_live_edit_remove_node_funcs;
live_edit_funcs.tree_remove_and_keep_node_func=_live_edit_remove_and_keep_node_funcs;
live_edit_funcs.tree_restore_node_func=_live_edit_restore_node_funcs;
live_edit_funcs.tree_duplicate_node_func=_live_edit_duplicate_node_funcs;
live_edit_funcs.tree_reparent_node_func=_live_edit_reparent_node_funcs;
if (ScriptDebugger::get_singleton()) {
ScriptDebugger::get_singleton()->set_live_edit_funcs(&live_edit_funcs);
}
live_edit_root=NodePath("/root");
#endif
}

View file

@ -164,6 +164,58 @@ friend class Viewport;
SelfList<Node>::List xform_change_list;
#ifdef DEBUG_ENABLED
Map<int,NodePath> live_edit_node_path_cache;
Map<int,String> live_edit_resource_cache;
NodePath live_edit_root;
String live_edit_scene;
Map<String,Set<Node*> > live_scene_edit_cache;
Map<Node*,Map<ObjectID,Node*> > live_edit_remove_list;
ScriptDebugger::LiveEditFuncs live_edit_funcs;
void _live_edit_node_path_func(const NodePath &p_path,int p_id) ;
void _live_edit_res_path_func(const String &p_path,int p_id) ;
void _live_edit_node_set_func(int p_id,const StringName& p_prop,const Variant& p_value) ;
void _live_edit_node_set_res_func(int p_id,const StringName& p_prop,const String& p_value) ;
void _live_edit_node_call_func(int p_id,const StringName& p_method,VARIANT_ARG_DECLARE) ;
void _live_edit_res_set_func(int p_id,const StringName& p_prop,const Variant& p_value) ;
void _live_edit_res_set_res_func(int p_id,const StringName& p_prop,const String& p_value) ;
void _live_edit_res_call_func(int p_id,const StringName& p_method,VARIANT_ARG_DECLARE) ;
void _live_edit_root_func(const NodePath& p_scene_path,const String& p_scene_from) ;
void _live_edit_create_node_func(const NodePath& p_parent,const String& p_type,const String& p_name);
void _live_edit_instance_node_func(const NodePath& p_parent,const String& p_path,const String& p_name);
void _live_edit_remove_node_func(const NodePath& p_at);
void _live_edit_remove_and_keep_node_func(const NodePath& p_at,ObjectID p_keep_id);
void _live_edit_restore_node_func(ObjectID p_id,const NodePath& p_at,int p_at_pos);
void _live_edit_duplicate_node_func(const NodePath& p_at,const String& p_new_name);
void _live_edit_reparent_node_func(const NodePath& p_at,const NodePath& p_new_place,const String& p_new_name,int p_at_pos);
static void _live_edit_node_path_funcs(void *self,const NodePath &p_path,int p_id) { reinterpret_cast<SceneTree*>(self)->_live_edit_node_path_func(p_path,p_id); }
static void _live_edit_res_path_funcs(void *self,const String &p_path,int p_id) { reinterpret_cast<SceneTree*>(self)->_live_edit_res_path_func(p_path,p_id); }
static void _live_edit_node_set_funcs(void *self,int p_id,const StringName& p_prop,const Variant& p_value) { reinterpret_cast<SceneTree*>(self)->_live_edit_node_set_func(p_id,p_prop,p_value); }
static void _live_edit_node_set_res_funcs(void *self,int p_id,const StringName& p_prop,const String& p_value) { reinterpret_cast<SceneTree*>(self)->_live_edit_node_set_res_func(p_id,p_prop,p_value); }
static void _live_edit_node_call_funcs(void *self,int p_id,const StringName& p_method,VARIANT_ARG_DECLARE) { reinterpret_cast<SceneTree*>(self)->_live_edit_node_call_func(p_id,p_method,VARIANT_ARG_PASS); }
static void _live_edit_res_set_funcs(void *self,int p_id,const StringName& p_prop,const Variant& p_value) { reinterpret_cast<SceneTree*>(self)->_live_edit_res_set_func(p_id,p_prop,p_value); }
static void _live_edit_res_set_res_funcs(void *self,int p_id,const StringName& p_prop,const String& p_value) { reinterpret_cast<SceneTree*>(self)->_live_edit_res_set_res_func(p_id,p_prop,p_value); }
static void _live_edit_res_call_funcs(void *self,int p_id,const StringName& p_method,VARIANT_ARG_DECLARE) { reinterpret_cast<SceneTree*>(self)->_live_edit_res_call_func(p_id,p_method,VARIANT_ARG_PASS); }
static void _live_edit_root_funcs(void *self, const NodePath& p_scene_path,const String& p_scene_from) { reinterpret_cast<SceneTree*>(self)->_live_edit_root_func(p_scene_path,p_scene_from); }
static void _live_edit_create_node_funcs(void* self,const NodePath& p_parent,const String& p_type,const String& p_name) { reinterpret_cast<SceneTree*>(self)->_live_edit_create_node_func(p_parent,p_type,p_name); }
static void _live_edit_instance_node_funcs(void* self,const NodePath& p_parent,const String& p_path,const String& p_name) { reinterpret_cast<SceneTree*>(self)->_live_edit_instance_node_func(p_parent,p_path,p_name); }
static void _live_edit_remove_node_funcs(void* self,const NodePath& p_at) { reinterpret_cast<SceneTree*>(self)->_live_edit_remove_node_func(p_at); }
static void _live_edit_remove_and_keep_node_funcs(void* self,const NodePath& p_at,ObjectID p_keep_id) { reinterpret_cast<SceneTree*>(self)->_live_edit_remove_and_keep_node_func(p_at,p_keep_id); }
static void _live_edit_restore_node_funcs(void* self,ObjectID p_id,const NodePath& p_at,int p_at_pos) { reinterpret_cast<SceneTree*>(self)->_live_edit_restore_node_func(p_id,p_at,p_at_pos); }
static void _live_edit_duplicate_node_funcs(void* self,const NodePath& p_at,const String& p_new_name) { reinterpret_cast<SceneTree*>(self)->_live_edit_duplicate_node_func(p_at,p_new_name); }
static void _live_edit_reparent_node_funcs(void* self,const NodePath& p_at,const NodePath& p_new_place,const String& p_new_name,int p_at_pos) { reinterpret_cast<SceneTree*>(self)->_live_edit_reparent_node_func(p_at,p_new_place,p_new_name,p_at_pos); }
#endif
protected:
void _notification(int p_notification);

View file

@ -250,7 +250,6 @@ void make_default_theme() {
t->set_stylebox("hover","ToolButton", make_stylebox( button_normal_png,4,4,4,4) );
t->set_stylebox("disabled","ToolButton", make_empty_stylebox(4,4,4,4) );
t->set_stylebox("focus","ToolButton", focus );
t->set_font("font","ToolButton", default_font );
t->set_color("font_color","ToolButton", control_font_color );
@ -678,6 +677,9 @@ void make_default_theme() {
t->set_stylebox("tab_fg","Tabs", make_stylebox( tab_current_png,4,4,4,4,16,4,16,4) );
t->set_stylebox("tab_bg","Tabs", make_stylebox( tab_behind_png,4,4,4,4,16,6,16,4) );
t->set_stylebox("panel","Tabs", make_stylebox( tab_container_bg_png,4,4,4,4) );
t->set_stylebox("button_pressed","Tabs", make_stylebox( button_pressed_png,4,4,4,4) );
t->set_stylebox("button","Tabs", make_stylebox( button_normal_png,4,4,4,4) );
t->set_font("font","Tabs", default_font );

View file

@ -432,6 +432,7 @@ int EditorData::add_edited_scene(int p_at_pos) {
es.root=NULL;
es.history_current=-1;
es.version=0;
es.live_edit_root=NodePath(String("/root"));
if (p_at_pos==edited_scene.size())
edited_scene.push_back(es);
@ -507,6 +508,31 @@ uint64_t EditorData::get_scene_version(int p_idx) const{
return edited_scene[p_idx].version;
}
String EditorData::get_scene_type(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),String());
if (!edited_scene[p_idx].root)
return "";
return edited_scene[p_idx].root->get_type();
}
Ref<Script> EditorData::get_scene_root_script(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),Ref<Script>());
if (!edited_scene[p_idx].root)
return Ref<Script>();
Ref<Script> s=edited_scene[p_idx].root->get_script();
if (!s.is_valid()) {
Node *n = edited_scene[p_idx].root->get_child(0);
while(!s.is_valid() && n && n->get_filename()==String()) {
s=n->get_script();
n=n->get_parent();
}
}
return s;
}
String EditorData::get_scene_title(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx,edited_scene.size(),String());
if (!edited_scene[p_idx].root)
@ -527,6 +553,23 @@ String EditorData::get_scene_path(int p_idx) const {
}
void EditorData::set_edited_scene_live_edit_root(const NodePath& p_root) {
ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());
edited_scene[current_edited_scene].live_edit_root=p_root;
}
NodePath EditorData::get_edited_scene_live_edit_root() {
ERR_FAIL_INDEX_V(current_edited_scene,edited_scene.size(),String());
return edited_scene[current_edited_scene].live_edit_root;
}
void EditorData::save_edited_scene_state(EditorSelection *p_selection, EditorHistory *p_history, const Dictionary& p_custom) {
ERR_FAIL_INDEX(current_edited_scene,edited_scene.size());

View file

@ -129,6 +129,7 @@ private:
int history_current;
Dictionary custom_state;
uint64_t version;
NodePath live_edit_root;
};
@ -177,10 +178,14 @@ public:
int get_edited_scene_count() const;
String get_scene_title(int p_idx) const;
String get_scene_path(int p_idx) const;
String get_scene_type(int p_idx) const;
Ref<Script> get_scene_root_script(int p_idx) const;
void set_edited_scene_version(uint64_t version);
uint64_t get_edited_scene_version() const;
uint64_t get_scene_version(int p_idx) const;
void clear_edited_scenes();
void set_edited_scene_live_edit_root(const NodePath& p_root);
NodePath get_edited_scene_live_edit_root();
void set_plugin_window_layout(Ref<ConfigFile> p_layout);

View file

@ -93,6 +93,7 @@
#include "plugins/light_occluder_2d_editor_plugin.h"
#include "plugins/color_ramp_editor_plugin.h"
#include "plugins/collision_shape_2d_editor_plugin.h"
// end
#include "tools/editor/io_plugins/editor_texture_import_plugin.h"
#include "tools/editor/io_plugins/editor_scene_import_plugin.h"
@ -103,16 +104,38 @@
#include "plugins/editor_preview_plugins.h"
#include "script_editor_debugger.h"
EditorNode *EditorNode::singleton=NULL;
void EditorNode::_update_scene_tabs() {
scene_tabs->clear_tabs();
Ref<Texture> script_icon = gui_base->get_icon("Script","EditorIcons");
for(int i=0;i<editor_data.get_edited_scene_count();i++) {
String type=editor_data.get_scene_type(i);
Ref<Texture> icon;
if (type!=String()) {
if (!gui_base->has_icon(type,"EditorIcons")) {
type="Node";
}
icon=gui_base->get_icon(type,"EditorIcons");
}
int current = editor_data.get_edited_scene();
bool unsaved = (i==current)?saved_version!=editor_data.get_undo_redo().get_version():editor_data.get_scene_version(i)!=0;
scene_tabs->add_tab(editor_data.get_scene_title(i)+(unsaved?"(*)":""));
scene_tabs->add_tab(editor_data.get_scene_title(i)+(unsaved?"(*)":""),icon);
if (editor_data.get_scene_root_script(i).is_valid()) {
scene_tabs->set_tab_right_button(i,script_icon);
}
}
scene_tabs->set_current_tab(editor_data.get_edited_scene());
@ -206,7 +229,7 @@ void EditorNode::_notification(int p_what) {
circle_step=0;
circle_step_msec=tick;
circle_step_frame=frame+1;
circle_step_frame=frame+1;
update_menu->set_icon(gui_base->get_icon("Progress"+itos(circle_step+1),"EditorIcons"));
@ -2389,6 +2412,11 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
fileserver_menu->get_popup()->set_item_checked( fileserver_menu->get_popup()->get_item_index(RUN_FILE_SERVER),!ischecked);
} break;
case RUN_LIVE_DEBUG: {
ScriptEditor::get_singleton()->get_debugger()->set_live_debugging(live_debug_button->is_pressed());
} break;
case RUN_DEPLOY_DUMB_CLIENTS: {
bool ischecked = fileserver_menu->get_popup()->is_item_checked( fileserver_menu->get_popup()->get_item_index(RUN_DEPLOY_DUMB_CLIENTS));
@ -2997,6 +3025,7 @@ void EditorNode::set_current_scene(int p_idx) {
call_deferred("_set_main_scene_state",state); //do after everything else is done setting up
//print_line("set current 6 ");
changing_scene=false;
ScriptEditor::get_singleton()->get_debugger()->update_live_edit_root();
}
@ -3134,6 +3163,8 @@ Error EditorNode::load_scene(const String& p_scene) {
prev_scene->set_disabled(previous_scenes.size()==0);
opening_prev=false;
ScriptEditor::get_singleton()->get_debugger()->update_live_edit_root();
//top_pallete->set_current_tab(0); //always go to scene
push_item(new_scene);
@ -3569,6 +3600,7 @@ void EditorNode::_bind_methods() {
ObjectTypeDB::bind_method("set_current_scene",&EditorNode::set_current_scene);
ObjectTypeDB::bind_method("set_current_version",&EditorNode::set_current_version);
ObjectTypeDB::bind_method("_scene_tab_changed",&EditorNode::_scene_tab_changed);
ObjectTypeDB::bind_method("_scene_tab_script_edited",&EditorNode::_scene_tab_script_edited);
ObjectTypeDB::bind_method("_set_main_scene_state",&EditorNode::_set_main_scene_state);
ObjectTypeDB::bind_method("_update_scene_tabs",&EditorNode::_update_scene_tabs);
@ -4013,6 +4045,13 @@ void EditorNode::_load_docks() {
}
void EditorNode::_scene_tab_script_edited(int p_tab) {
Ref<Script> script = editor_data.get_scene_root_script(p_tab);
if (script.is_valid())
edit_resource(script);
}
void EditorNode::_scene_tab_changed(int p_tab) {
@ -4167,6 +4206,7 @@ EditorNode::EditorNode() {
scene_tabs->add_tab("unsaved");
scene_tabs->set_tab_align(Tabs::ALIGN_CENTER);
scene_tabs->connect("tab_changed",this,"_scene_tab_changed");
scene_tabs->connect("right_button_pressed",this,"_scene_tab_script_edited");
top_dark_vb->add_child(scene_tabs);
//left
left_l_hsplit = memnew( HSplitContainer );
@ -4584,6 +4624,14 @@ EditorNode::EditorNode() {
play_custom_scene_button->connect("pressed", this,"_menu_option",make_binds(RUN_PLAY_CUSTOM_SCENE));
play_custom_scene_button->set_tooltip("Play custom scene ("+keycode_get_string(KEY_MASK_CMD|KEY_MASK_SHIFT|KEY_F5)+").");
live_debug_button = memnew( ToolButton );
play_hb->add_child(live_debug_button);
live_debug_button->set_toggle_mode(true);
live_debug_button->set_focus_mode(Control::FOCUS_NONE);
live_debug_button->set_icon(gui_base->get_icon("LiveDebug","EditorIcons"));
live_debug_button->connect("pressed", this,"_menu_option",make_binds(RUN_LIVE_DEBUG));
live_debug_button->set_tooltip("Toggle Live Debugging On/Off");
fileserver_menu = memnew( MenuButton );
play_hb->add_child(fileserver_menu);
fileserver_menu->set_flat(true);

View file

@ -152,6 +152,7 @@ class EditorNode : public Node {
RUN_PROJECT_MANAGER,
RUN_FILE_SERVER,
RUN_DEPLOY_DUMB_CLIENTS,
RUN_LIVE_DEBUG,
SETTINGS_UPDATE_ALWAYS,
SETTINGS_UPDATE_CHANGES,
SETTINGS_IMPORT,
@ -239,6 +240,7 @@ class EditorNode : public Node {
ToolButton *animation_menu;
ToolButton *play_scene_button;
ToolButton *play_custom_scene_button;
ToolButton *live_debug_button;
TextureProgress *audio_vu;
MenuButton *fileserver_menu;
@ -469,6 +471,7 @@ class EditorNode : public Node {
void _dock_split_dragged(int ofs);
void _dock_popup_exit();
void _scene_tab_changed(int p_tab);
void _scene_tab_script_edited(int p_tab);
Dictionary _get_main_scene_state();
void _set_main_scene_state(Dictionary p_state);

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

View file

@ -250,6 +250,8 @@ public:
void set_window_layout(Ref<ConfigFile> p_layout);
void get_window_layout(Ref<ConfigFile> p_layout);
ScriptEditorDebugger *get_debugger() { return debugger; }
ScriptEditor(EditorNode *p_editor);
~ScriptEditor();
};

View file

@ -107,8 +107,8 @@ void TileMapEditor::_set_cell(const Point2i& p_pos,int p_value,bool p_flip_h, bo
if (p_with_undo) {
undo_redo->add_do_method(this,"_set_cell_shortened",Point2(p_pos),p_value,p_flip_h,p_flip_v,p_transpose);
undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p_pos),prev_val,prev_flip_h,prev_flip_v,prev_transpose);
undo_redo->add_do_method(node,"set_cellv",Point2(p_pos),p_value,p_flip_h,p_flip_v,p_transpose);
undo_redo->add_undo_method(node,"set_cellv",Point2(p_pos),prev_val,prev_flip_h,prev_flip_v,prev_transpose);
} else {
node->set_cell(p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v,p_transpose);
@ -314,8 +314,8 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
for(Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
Point2i p=E->key();
undo_redo->add_do_method(this,"_set_cell_shortened",Point2(p),node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y));
undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr);
undo_redo->add_do_method(node,"set_cellv",Point2(p),node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y));
undo_redo->add_undo_method(node,"set_cellv",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr);
}
undo_redo->commit_action();
@ -344,7 +344,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
//return true;
_set_cell(local,TileMap::INVALID_CELL);
return true;
} else {
} else if (!mb.pressed) {
if (tool==TOOL_ERASING) {
@ -353,9 +353,10 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
for(Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) {
Point2i p=E->key();
//undo_redo->add_do_method(node,"set_cell",p.x,p.y,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y));
_set_cell(p,TileMap::INVALID_CELL,false,false,false,true);
undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr);
//undo_redo->add_do_method(node,"set_cell",p,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y));
//_set_cell(p,TileMap::INVALID_CELL,false,false,false,true);
undo_redo->add_do_method(node,"set_cellv",Point2(p),TileMap::INVALID_CELL,false,false,false);
undo_redo->add_undo_method(node,"set_cellv",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr);
}
undo_redo->commit_action();

View file

@ -1131,7 +1131,7 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) {
tree->set_column_min_width(1,90);
filters = memnew( LineEdit );
vb->add_margin_child("Filters for Non-Resources (Comma Separated):",filters);
vb->add_margin_child("Filters to export non-resource files (Comma Separated, ie: *.json, *.txt):",filters);
filters->connect("text_changed",this,"_filters_edited");

View file

@ -33,7 +33,8 @@
#include "scene/resources/packed_scene.h"
#include "editor_settings.h"
#include "tools/editor/plugins/canvas_item_editor_plugin.h"
#include "script_editor_debugger.h"
#include "tools/editor/plugins/script_editor_plugin.h"
void SceneTreeDock::_unhandled_key_input(InputEvent p_event) {
@ -105,6 +106,13 @@ Node* SceneTreeDock::instance(const String& p_file) {
editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",instanced_scene);
editor_data->get_undo_redo().add_do_reference(instanced_scene);
editor_data->get_undo_redo().add_undo_method(parent,"remove_child",instanced_scene);
String new_name = parent->validate_child_name(instanced_scene->get_name());
ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
editor_data->get_undo_redo().add_do_method(sed,"live_debug_instance_node",edited_scene->get_path_to(parent),p_file,new_name);
editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+new_name));
editor_data->get_undo_redo().commit_action();
@ -389,9 +397,14 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
editor_data->get_undo_redo().add_do_method(d,"set_owner",node->get_owner());
}
editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",dup);
editor_data->get_undo_redo().add_undo_method(parent,"remove_child",dup);
editor_data->get_undo_redo().add_undo_method(parent,"remove_child",dup);
editor_data->get_undo_redo().add_do_reference(dup);
ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
editor_data->get_undo_redo().add_do_method(sed,"live_debug_duplicate_node",edited_scene->get_path_to(node),attempt);
editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+attempt));
//parent->add_child(dup);
//reselect.push_back(dup);
}
@ -903,6 +916,13 @@ void SceneTreeDock::_node_reparent(NodePath p_path,bool p_node_only) {
editor_data->get_undo_redo().add_do_method(node->get_parent(),"remove_child",node);
editor_data->get_undo_redo().add_do_method(new_parent,"add_child",node);
ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
String new_name = new_parent->validate_child_name(node->get_name());
editor_data->get_undo_redo().add_do_method(sed,"live_debug_reparent_node",edited_scene->get_path_to(node),edited_scene->get_path_to(new_parent),new_name,-1);
editor_data->get_undo_redo().add_undo_method(sed,"live_debug_reparent_node",NodePath(String(edited_scene->get_path_to(new_parent))+"/"+new_name),edited_scene->get_path_to(node->get_parent()),node->get_name(),node->get_index());
editor_data->get_undo_redo().add_do_method(this,"_set_owners",edited_scene,owners);
if (editor->get_animation_editor()->get_root()==node)
@ -1025,6 +1045,11 @@ void SceneTreeDock::_delete_confirm() {
editor_data->get_undo_redo().add_undo_method(this,"_set_owners",edited_scene,owners);
//editor_data->get_undo_redo().add_undo_method(n,"set_owner",n->get_owner());
editor_data->get_undo_redo().add_undo_reference(n);
ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
editor_data->get_undo_redo().add_do_method(sed,"live_debug_remove_and_keep_node",edited_scene->get_path_to(n),n->get_instance_ID());
editor_data->get_undo_redo().add_undo_method(sed,"live_debug_restore_node",n->get_instance_ID(),edited_scene->get_path_to(n->get_parent()),n->get_index());
}
@ -1082,12 +1107,20 @@ void SceneTreeDock::_create() {
editor_data->get_undo_redo().create_action("Create Node");
if (edited_scene) {
editor_data->get_undo_redo().add_do_method(parent,"add_child",child);
editor_data->get_undo_redo().add_do_method(child,"set_owner",edited_scene);
editor_data->get_undo_redo().add_do_method(editor_selection,"clear");
editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",child);
editor_data->get_undo_redo().add_do_reference(child);
editor_data->get_undo_redo().add_undo_method(parent,"remove_child",child);
String new_name = parent->validate_child_name(child->get_type());
ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger();
editor_data->get_undo_redo().add_do_method(sed,"live_debug_create_node",edited_scene->get_path_to(parent),child->get_type(),new_name);
editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+new_name));
} else {
editor_data->get_undo_redo().add_do_method(editor,"set_edited_scene",child);

View file

@ -241,6 +241,8 @@ void ScriptEditorDebugger::_parse_message(const String& p_msg,const Array& p_dat
lv[level]=it;
}
le_clear->set_disabled(false);
le_set->set_disabled(false);
} else if (p_msg=="stack_dump") {
@ -443,6 +445,8 @@ void ScriptEditorDebugger::_notification(int p_what) {
tb->set_hover_texture( get_icon("CloseHover","EditorIcons"));
tb->set_pressed_texture( get_icon("Close","EditorIcons"));
scene_tree_refresh->set_icon( get_icon("Reload","EditorIcons"));
le_set->connect("pressed",this,"_live_edit_set");
le_clear->connect("pressed",this,"_live_edit_clear");
} break;
case NOTIFICATION_PROCESS: {
@ -468,6 +472,12 @@ void ScriptEditorDebugger::_notification(int p_what) {
emit_signal("show_debugger",true);
reason->set_text("Child Process Connected");
reason->set_tooltip("Child Process Connected");
scene_tree->clear();
le_set->set_disabled(true);
le_clear->set_disabled(false);
//live_edit_root->set_text("/root");
update_live_edit_root();
} else {
@ -613,6 +623,10 @@ void ScriptEditorDebugger::stop(){
log_forced_visible=false;
}
node_path_cache.clear();
res_path_cache.clear();
le_clear->set_disabled(false);
le_set->set_disabled(true);
hide();
@ -664,6 +678,336 @@ String ScriptEditorDebugger::get_var_value(const String& p_var) const {
return variables->get_var_value(p_var);
}
int ScriptEditorDebugger::_get_node_path_cache(const NodePath& p_path) {
const int *r = node_path_cache.getptr(p_path);
if (r)
return *r;
last_path_id++;
node_path_cache[p_path]=last_path_id;
Array msg;
msg.push_back("live_node_path");
msg.push_back(p_path);
msg.push_back(last_path_id);
ppeer->put_var(msg);
return last_path_id;
}
int ScriptEditorDebugger::_get_res_path_cache(const String& p_path) {
Map<String,int>::Element *E=res_path_cache.find(p_path);
if (E)
return E->get();
last_path_id++;
res_path_cache[p_path]=last_path_id;
Array msg;
msg.push_back("live_res_path");
msg.push_back(p_path);
msg.push_back(last_path_id);
ppeer->put_var(msg);
return last_path_id;
}
void ScriptEditorDebugger::_method_changed(Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE) {
if (!p_base || !live_debug || !connection.is_valid() || !editor->get_edited_scene())
return;
Node *node = p_base->cast_to<Node>();
VARIANT_ARGPTRS
for(int i=0;i<VARIANT_ARG_MAX;i++) {
//no pointers, sorry
if (argptr[i] && (argptr[i]->get_type()==Variant::OBJECT || argptr[i]->get_type()==Variant::_RID))
return;
}
if (node) {
NodePath path = editor->get_edited_scene()->get_path_to(node);
int pathid = _get_node_path_cache(path);
Array msg;
msg.push_back("live_node_call");
msg.push_back(pathid);
msg.push_back(p_name);
for(int i=0;i<VARIANT_ARG_MAX;i++) {
//no pointers, sorry
msg.push_back(*argptr[i]);
}
ppeer->put_var(msg);
return;
}
Resource *res = p_base->cast_to<Resource>();
if (res && res->get_path()!=String()) {
String respath = res->get_path();
int pathid = _get_res_path_cache(respath);
Array msg;
msg.push_back("live_res_call");
msg.push_back(pathid);
msg.push_back(p_name);
for(int i=0;i<VARIANT_ARG_MAX;i++) {
//no pointers, sorry
msg.push_back(*argptr[i]);
}
ppeer->put_var(msg);
return;
}
//print_line("method");
}
void ScriptEditorDebugger::_property_changed(Object*p_base,const StringName& p_property,const Variant& p_value){
if (!p_base || !live_debug || !connection.is_valid() || !editor->get_edited_scene())
return;
Node *node = p_base->cast_to<Node>();
if (node) {
NodePath path = editor->get_edited_scene()->get_path_to(node);
int pathid = _get_node_path_cache(path);
if (p_value.is_ref()) {
Ref<Resource> res = p_value;
if (res.is_valid() && res->get_path()!=String()) {
Array msg;
msg.push_back("live_node_prop_res");
msg.push_back(pathid);
msg.push_back(p_property);
msg.push_back(res->get_path());
ppeer->put_var(msg);
}
} else {
Array msg;
msg.push_back("live_node_prop");
msg.push_back(pathid);
msg.push_back(p_property);
msg.push_back(p_value);
ppeer->put_var(msg);
}
return;
}
Resource *res = p_base->cast_to<Resource>();
if (res && res->get_path()!=String()) {
String respath = res->get_path();
int pathid = _get_res_path_cache(respath);
if (p_value.is_ref()) {
Ref<Resource> res = p_value;
if (res.is_valid() && res->get_path()!=String()) {
Array msg;
msg.push_back("live_res_prop_res");
msg.push_back(pathid);
msg.push_back(p_property);
msg.push_back(res->get_path());
ppeer->put_var(msg);
}
} else {
Array msg;
msg.push_back("live_res_prop");
msg.push_back(pathid);
msg.push_back(p_property);
msg.push_back(p_value);
ppeer->put_var(msg);
}
return;
}
//print_line("prop");
}
void ScriptEditorDebugger::_method_changeds(void *p_ud,Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE) {
ScriptEditorDebugger *sed = (ScriptEditorDebugger*)p_ud;
sed->_method_changed(p_base,p_name,VARIANT_ARG_PASS);
}
void ScriptEditorDebugger::_property_changeds(void *p_ud,Object*p_base,const StringName& p_property,const Variant& p_value){
ScriptEditorDebugger *sed = (ScriptEditorDebugger*)p_ud;
sed->_property_changed(p_base,p_property,p_value);
}
void ScriptEditorDebugger::set_live_debugging(bool p_enable) {
live_debug=p_enable;
}
void ScriptEditorDebugger::_live_edit_set() {
if (!connection.is_valid())
return;
TreeItem* ti = scene_tree->get_selected();
if (!ti)
return;
String path;
while(ti) {
String lp=ti->get_text(0);
path="/"+lp+path;
ti=ti->get_parent();
}
NodePath np = path;
editor->get_editor_data().set_edited_scene_live_edit_root(np);
update_live_edit_root();
}
void ScriptEditorDebugger::_live_edit_clear() {
NodePath np = NodePath("/root");
editor->get_editor_data().set_edited_scene_live_edit_root(np);
update_live_edit_root();
}
void ScriptEditorDebugger::update_live_edit_root() {
NodePath np = editor->get_editor_data().get_edited_scene_live_edit_root();
if (connection.is_valid()) {
Array msg;
msg.push_back("live_set_root");
msg.push_back(np);
if (editor->get_edited_scene())
msg.push_back(editor->get_edited_scene()->get_filename());
else
msg.push_back("");
ppeer->put_var(msg);
}
live_edit_root->set_text(np);
}
void ScriptEditorDebugger::live_debug_create_node(const NodePath& p_parent,const String& p_type,const String& p_name) {
if (live_debug && connection.is_valid()) {
Array msg;
msg.push_back("live_create_node");
msg.push_back(p_parent);
msg.push_back(p_type);
msg.push_back(p_name);
ppeer->put_var(msg);
}
}
void ScriptEditorDebugger::live_debug_instance_node(const NodePath& p_parent,const String& p_path,const String& p_name){
if (live_debug && connection.is_valid()) {
Array msg;
msg.push_back("live_instance_node");
msg.push_back(p_parent);
msg.push_back(p_path);
msg.push_back(p_name);
ppeer->put_var(msg);
}
}
void ScriptEditorDebugger::live_debug_remove_node(const NodePath& p_at){
if (live_debug && connection.is_valid()) {
Array msg;
msg.push_back("live_remove_node");
msg.push_back(p_at);
ppeer->put_var(msg);
}
}
void ScriptEditorDebugger::live_debug_remove_and_keep_node(const NodePath& p_at,ObjectID p_keep_id) {
if (live_debug && connection.is_valid()) {
Array msg;
msg.push_back("live_remove_and_keep_node");
msg.push_back(p_at);
msg.push_back(p_keep_id);
ppeer->put_var(msg);
}
}
void ScriptEditorDebugger::live_debug_restore_node(ObjectID p_id, const NodePath& p_at, int p_at_pos){
if (live_debug && connection.is_valid()) {
Array msg;
msg.push_back("live_restore_node");
msg.push_back(p_id);
msg.push_back(p_at);
msg.push_back(p_at_pos);
ppeer->put_var(msg);
}
}
void ScriptEditorDebugger::live_debug_duplicate_node(const NodePath& p_at,const String& p_new_name){
if (live_debug && connection.is_valid()) {
Array msg;
msg.push_back("live_duplicate_node");
msg.push_back(p_at);
msg.push_back(p_new_name);
ppeer->put_var(msg);
}
}
void ScriptEditorDebugger::live_debug_reparent_node(const NodePath& p_at, const NodePath& p_new_place, const String &p_new_name, int p_at_pos){
if (live_debug && connection.is_valid()) {
Array msg;
msg.push_back("live_reparent_node");
msg.push_back(p_at);
msg.push_back(p_new_place);
msg.push_back(p_new_name);
msg.push_back(p_at_pos);
ppeer->put_var(msg);
}
}
void ScriptEditorDebugger::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_stack_dump_frame_selected"),&ScriptEditorDebugger::_stack_dump_frame_selected);
@ -676,6 +1020,16 @@ void ScriptEditorDebugger::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_performance_draw"),&ScriptEditorDebugger::_performance_draw);
ObjectTypeDB::bind_method(_MD("_performance_select"),&ScriptEditorDebugger::_performance_select);
ObjectTypeDB::bind_method(_MD("_scene_tree_request"),&ScriptEditorDebugger::_scene_tree_request);
ObjectTypeDB::bind_method(_MD("_live_edit_set"),&ScriptEditorDebugger::_live_edit_set);
ObjectTypeDB::bind_method(_MD("_live_edit_clear"),&ScriptEditorDebugger::_live_edit_clear);
ObjectTypeDB::bind_method(_MD("live_debug_create_node"),&ScriptEditorDebugger::live_debug_create_node);
ObjectTypeDB::bind_method(_MD("live_debug_instance_node"),&ScriptEditorDebugger::live_debug_instance_node);
ObjectTypeDB::bind_method(_MD("live_debug_remove_node"),&ScriptEditorDebugger::live_debug_remove_node);
ObjectTypeDB::bind_method(_MD("live_debug_remove_and_keep_node"),&ScriptEditorDebugger::live_debug_remove_and_keep_node);
ObjectTypeDB::bind_method(_MD("live_debug_restore_node"),&ScriptEditorDebugger::live_debug_restore_node);
ObjectTypeDB::bind_method(_MD("live_debug_duplicate_node"),&ScriptEditorDebugger::live_debug_duplicate_node);
ObjectTypeDB::bind_method(_MD("live_debug_reparent_node"),&ScriptEditorDebugger::live_debug_reparent_node);
ADD_SIGNAL(MethodInfo("goto_script_line"));
ADD_SIGNAL(MethodInfo("breaked",PropertyInfo(Variant::BOOL,"reallydid")));
@ -843,6 +1197,26 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){
info_left->add_margin_child("Clicked Control:",clicked_ctrl);
clicked_ctrl_type = memnew( LineEdit );
info_left->add_margin_child("Clicked Control Type:",clicked_ctrl_type);
live_edit_root = memnew( LineEdit );
{
HBoxContainer *lehb = memnew( HBoxContainer );
Label *l = memnew( Label("Live Edit Root:") );
lehb->add_child(l);
l->set_h_size_flags(SIZE_EXPAND_FILL);
le_set = memnew( Button("Set From Tree") );
lehb->add_child(le_set);
le_clear = memnew( Button("Clear") );
lehb->add_child(le_clear);
info_left->add_child(lehb);
MarginContainer *mc = memnew( MarginContainer );
mc->add_child(live_edit_root);
info_left->add_child(mc);
le_set->set_disabled(true);
le_clear->set_disabled(true);
}
VBoxContainer *info_right = memnew(VBoxContainer);
info_right->set_h_size_flags(SIZE_EXPAND_FILL);
info->add_child(info_right);
@ -868,6 +1242,11 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor){
hide();
log_forced_visible=false;
p_editor->get_undo_redo()->set_method_notify_callback(_method_changeds,this);
p_editor->get_undo_redo()->set_property_notify_callback(_property_changeds,this);
live_debug=false;
last_path_id=false;
}
ScriptEditorDebugger::~ScriptEditorDebugger() {

View file

@ -56,9 +56,13 @@ class ScriptEditorDebugger : public Control {
LineEdit *clicked_ctrl;
LineEdit *clicked_ctrl_type;
LineEdit *live_edit_root;
Tree *scene_tree;
HSplitContainer *info;
Button *scene_tree_refresh;
Button *le_set;
Button *le_clear;
TextureButton *tb;
@ -94,11 +98,17 @@ class ScriptEditorDebugger : public Control {
Array message;
int pending_in_queue;
HashMap<NodePath,int> node_path_cache;
int last_path_id;
Map<String,int> res_path_cache;
EditorNode *editor;
bool breaked;
bool live_debug;
void _performance_draw();
void _performance_select(Object *, int, bool);
void _stack_dump_frame_selected();
@ -108,6 +118,20 @@ class ScriptEditorDebugger : public Control {
void _scene_tree_request();
void _parse_message(const String& p_msg,const Array& p_data);
int _get_node_path_cache(const NodePath& p_path);
int _get_res_path_cache(const String& p_path);
void _live_edit_set();
void _live_edit_clear();
void _method_changed(Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE);
void _property_changed(Object*p_base,const StringName& p_property,const Variant& p_value);
static void _method_changeds(void *p_ud,Object*p_base,const StringName& p_name,VARIANT_ARG_DECLARE);
static void _property_changeds(void *p_ud,Object*p_base,const StringName& p_property,const Variant& p_value);
protected:
void _notification(int p_what);
@ -127,6 +151,19 @@ public:
String get_var_value(const String& p_var) const;
void set_live_debugging(bool p_enable);
void live_debug_create_node(const NodePath& p_parent,const String& p_type,const String& p_name);
void live_debug_instance_node(const NodePath& p_parent,const String& p_path,const String& p_name);
void live_debug_remove_node(const NodePath& p_at);
void live_debug_remove_and_keep_node(const NodePath& p_at,ObjectID p_keep_id);
void live_debug_restore_node(ObjectID p_id,const NodePath& p_at,int p_at_pos);
void live_debug_duplicate_node(const NodePath& p_at,const String& p_new_name);
void live_debug_reparent_node(const NodePath& p_at,const NodePath& p_new_place,const String& p_new_name,int p_at_pos);
void update_live_edit_root();
virtual Size2 get_minimum_size() const;
ScriptEditorDebugger(EditorNode *p_editor=NULL);
~ScriptEditorDebugger();

View file

@ -190,7 +190,7 @@ class DaeExporter:
if (not os.path.isfile(dstfile)):
shutil.copy(imgpath,dstfile)
imgpath="images/"+os.path.basename(imgpath)
imgpath="images/"+os.path.basename(imgpath)
else:
### if file is not found save it as png file in the destination folder
img_tmp_path = image.filepath
@ -204,7 +204,7 @@ class DaeExporter:
if (not os.path.isfile(dstfile)):
image.save()
imgpath="images/"+os.path.basename(image.filepath)
imgpath="images/"+os.path.basename(image.filepath)
image.filepath = img_tmp_path
else: