Merge branch 'master' of https://github.com/okamstudio/godot
This commit is contained in:
commit
c88038228a
50 changed files with 2988 additions and 1459 deletions
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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() {};
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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>
|
||||
|
|
4
demos/misc/regex/engine.cfg
Normal file
4
demos/misc/regex/engine.cfg
Normal file
|
@ -0,0 +1,4 @@
|
|||
[application]
|
||||
|
||||
name="RegEx"
|
||||
main_scene="res://regex.scn"
|
22
demos/misc/regex/regex.gd
Normal file
22
demos/misc/regex/regex.gd
Normal 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
BIN
demos/misc/regex/regex.scn
Normal file
Binary file not shown.
|
@ -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
64
drivers/nrex/README.md
Normal 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.
|
|
@ -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
910
drivers/nrex/nrex.cpp
Normal 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
144
drivers/nrex/nrex.hpp
Normal 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
|
12
drivers/nrex/nrex_config.h
Normal file
12
drivers/nrex/nrex_config.h
Normal 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
114
drivers/nrex/regex.cpp
Normal 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();
|
||||
|
||||
};
|
|
@ -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);
|
|
@ -48,7 +48,7 @@
|
|||
#endif
|
||||
|
||||
|
||||
#include "drivers/trex/regex.h"
|
||||
#include "drivers/nrex/regex.h"
|
||||
|
||||
#ifdef MUSEPACK_ENABLED
|
||||
#include "mpc/audio_stream_mpc.h"
|
||||
|
|
|
@ -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_
|
|
@ -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
|
|
@ -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.
|
||||
|
|
@ -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();
|
||||
};
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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()));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
BIN
tools/editor/icons/icon_live_debug.png
Normal file
BIN
tools/editor/icons/icon_live_debug.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 583 B |
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue