# Solved Conflicts:
#	tools/editor/property_editor.cpp
#	tools/editor/property_editor.h
This commit is contained in:
Mariano Javier Suligoy 2015-08-30 02:48:45 -03:00
commit c688b55019
32 changed files with 853 additions and 60 deletions

View File

@ -1477,7 +1477,6 @@ Globals::Globals() {
custom_prop_info["render/mipmap_policy"]=PropertyInfo(Variant::INT,"render/mipmap_policy",PROPERTY_HINT_ENUM,"Allow,Allow For Po2,Disallow");
custom_prop_info["render/thread_model"]=PropertyInfo(Variant::INT,"render/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded");
custom_prop_info["physics_2d/thread_model"]=PropertyInfo(Variant::INT,"physics_2d/thread_model",PROPERTY_HINT_ENUM,"Single-Unsafe,Single-Safe,Multi-Threaded");
set("display/emulate_touchscreen",false);
using_datapack=false;
}

View File

@ -746,6 +746,25 @@ bool ObjectTypeDB::has_method(StringName p_type,StringName p_method,bool p_no_in
}
bool ObjectTypeDB::get_setter_and_type_for_property(const StringName& p_class, const StringName& p_prop, StringName& r_class, StringName& r_setter) {
TypeInfo *type=types.getptr(p_class);
TypeInfo *check=type;
while(check) {
if (check->property_setget.has(p_prop)) {
r_class=check->name;
r_setter=check->property_setget[p_prop].setter;
return true;
}
check=check->inherits_ptr;
}
return false;
}
#ifdef DEBUG_METHODS_ENABLED
MethodBind* ObjectTypeDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind , const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) {
StringName mdname=method_name.name;

View File

@ -476,6 +476,8 @@ public:
static int get_integer_constant(const StringName& p_type, const StringName &p_name, bool *p_success=NULL);
static StringName get_category(const StringName& p_node);
static bool get_setter_and_type_for_property(const StringName& p_class, const StringName& p_prop, StringName& r_class, StringName& r_setter);
static void set_type_enabled(StringName p_type,bool p_enable);
static bool is_type_enabled(StringName p_type);

View File

@ -271,6 +271,38 @@ void InputDefault::parse_input_event(const InputEvent& p_event) {
mouse_button_mask|=(1<<p_event.mouse_button.button_index);
else
mouse_button_mask&=~(1<<p_event.mouse_button.button_index);
if (main_loop && emulate_touch && p_event.mouse_button.button_index==1) {
InputEventScreenTouch touch_event;
touch_event.index=0;
touch_event.pressed=p_event.mouse_button.pressed;
touch_event.x=p_event.mouse_button.x;
touch_event.y=p_event.mouse_button.y;
InputEvent ev;
ev.type=InputEvent::SCREEN_TOUCH;
ev.screen_touch=touch_event;
main_loop->input_event(ev);
}
} break;
case InputEvent::MOUSE_MOTION: {
if (main_loop && emulate_touch && p_event.mouse_motion.button_mask&1) {
InputEventScreenDrag drag_event;
drag_event.index=0;
drag_event.x=p_event.mouse_motion.x;
drag_event.y=p_event.mouse_motion.y;
drag_event.relative_x=p_event.mouse_motion.relative_x;
drag_event.relative_y=p_event.mouse_motion.relative_y;
drag_event.speed_x=p_event.mouse_motion.speed_x;
drag_event.speed_y=p_event.mouse_motion.speed_y;
InputEvent ev;
ev.type=InputEvent::SCREEN_DRAG;
ev.screen_drag=drag_event;
main_loop->input_event(ev);
}
} break;
case InputEvent::JOYSTICK_BUTTON: {
@ -362,8 +394,19 @@ void InputDefault::action_release(const StringName& p_action){
}
}
void InputDefault::set_emulate_touch(bool p_emulate) {
emulate_touch=p_emulate;
}
bool InputDefault::is_emulating_touchscreen() const {
return emulate_touch;
}
InputDefault::InputDefault() {
mouse_button_mask=0;
emulate_touch=false;
main_loop=NULL;
}

View File

@ -78,6 +78,8 @@ public:
void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
virtual bool is_emulating_touchscreen() const=0;
Input();
};
@ -99,6 +101,8 @@ class InputDefault : public Input {
Vector2 mouse_pos;
MainLoop *main_loop;
bool emulate_touch;
struct SpeedTrack {
uint64_t last_tick;
@ -147,6 +151,9 @@ public:
void iteration(float p_step);
void set_emulate_touch(bool p_emulate);
virtual bool is_emulating_touchscreen() const;
InputDefault();
};

View File

@ -31,7 +31,7 @@
#include <stdarg.h>
#include "dir_access.h"
#include "globals.h"
#include "input.h"
OS* OS::singleton=NULL;
@ -363,7 +363,7 @@ Error OS::set_cwd(const String& p_cwd) {
bool OS::has_touchscreen_ui_hint() const {
//return false;
return GLOBAL_DEF("display/emulate_touchscreen",false);
return Input::get_singleton() && Input::get_singleton()->is_emulating_touchscreen();
}
int OS::get_free_static_memory() const {

View File

@ -3048,6 +3048,37 @@ bool String::is_valid_identifier() const {
//kind of poor should be rewritten properly
String String::world_wrap(int p_chars_per_line) const {
int from=0;
int last_space=0;
String ret;
for(int i=0;i<length();i++) {
if (i-from>=p_chars_per_line) {
if (last_space==-1) {
ret+=substr(from,i-from+1)+"\n";
} else {
ret+=substr(from,last_space-from)+"\n";
i=last_space; //rewind
}
from=i+1;
last_space=-1;
} else if (operator[](i)==' ' || operator[](i)=='\t') {
last_space=i;
} else if (operator[](i)=='\n') {
ret+=substr(from,i-from);
from=i+1;
last_space=-1;
}
}
if (from<length()) {
ret+=substr(from,length());
}
return ret;
}
String String::c_unescape() const {
String escaped=*this;

View File

@ -209,6 +209,7 @@ public:
String xml_unescape() const;
String c_escape() const;
String c_unescape() const;
String world_wrap(int p_chars_per_line) const;
String percent_encode() const;
String percent_decode() const;

View File

@ -75,7 +75,7 @@
#include "core/io/file_access_zip.h"
#include "translation.h"
#include "version.h"
#include "os/input.h"
#include "performance.h"
static Globals *globals=NULL;
@ -847,6 +847,14 @@ Error Main::setup2() {
GLOBAL_DEF("application/icon",String());
Globals::get_singleton()->set_custom_property_info("application/icon",PropertyInfo(Variant::STRING,"application/icon",PROPERTY_HINT_FILE,"*.png,*.webp"));
if (bool(GLOBAL_DEF("display/emulate_touchscreen",false))) {
if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) {
//only if no touchscreen ui hint, set emulation
InputDefault *id = Input::get_singleton()->cast_to<InputDefault>();
if (id)
id->set_emulate_touch(true);
}
}
MAIN_PRINT("Main: Load Remaps");
path_remap->load_remaps();

View File

@ -2625,14 +2625,14 @@ void GDParser::_parse_class(ClassNode *p_class) {
Node *subexpr=NULL;
subexpr = _parse_and_reduce_expression(p_class,false);
subexpr = _parse_and_reduce_expression(p_class,false,autoexport);
if (!subexpr)
return;
member.expression=subexpr;
if (autoexport) {
if (subexpr->type==Node::TYPE_ARRAY) {
if (1)/*(subexpr->type==Node::TYPE_ARRAY) {
member._export.type=Variant::ARRAY;
@ -2640,7 +2640,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
member._export.type=Variant::DICTIONARY;
} else {
} else*/ {
if (subexpr->type!=Node::TYPE_CONSTANT) {

View File

@ -504,6 +504,23 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) {
mouse_mode=p_mode;
if (mouse_mode==MOUSE_MODE_CAPTURED) {
while(true) {
//flush pending motion events
if (XPending(x11_display) > 0) {
XEvent event;
XPeekEvent(x11_display, &event);
if (event.type==MotionNotify) {
XNextEvent(x11_display,&event);
} else {
break;
}
} else {
break;
}
}
if (XGrabPointer(x11_display, x11_window, True,
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask, GrabModeAsync, GrabModeAsync,
@ -518,6 +535,8 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) {
0,0,0,0, (int)center.x, (int)center.y);
input->set_mouse_pos(center);
} else {
do_mouse_warp=false;
}
}
@ -1131,7 +1150,7 @@ void OS_X11::process_xevents() {
//printf("checking events %i\n", XPending(x11_display));
bool do_mouse_warp=false;
do_mouse_warp=false;
while (XPending(x11_display) > 0) {
XEvent event;
@ -1245,6 +1264,36 @@ void OS_X11::process_xevents() {
} break;
case MotionNotify: {
// FUCK YOU X11 API YOU SERIOUSLY GROSS ME OUT
// YOU ARE AS GROSS AS LOOKING AT A PUTRID PILE
// OF POOP STICKING OUT OF A CLOGGED TOILET
// HOW THE FUCK I AM SUPPOSED TO KNOW WHICH ONE
// OF THE MOTION NOTIFY EVENTS IS THE ONE GENERATED
// BY WARPING THE MOUSE POINTER?
// YOU ARE FORCING ME TO FILTER ONE BY ONE TO FIND IT
// PLEASE DO ME A FAVOR AND DIE DROWNED IN A FECAL
// MOUNTAIN BECAUSE THAT'S WHERE YOU BELONG.
while(true) {
if (mouse_mode==MOUSE_MODE_CAPTURED && event.xmotion.x==current_videomode.width/2 && event.xmotion.y==current_videomode.height/2) {
//this is likely the warp event since it was warped here
center=Vector2(event.xmotion.x,event.xmotion.y);
break;
}
if (XPending(x11_display) > 0) {
XEvent tevent;
XPeekEvent(x11_display, &tevent);
if (tevent.type==MotionNotify) {
XNextEvent(x11_display,&event);
} else {
break;
}
} else {
break;
}
}
last_timestamp=event.xmotion.time;

View File

@ -114,6 +114,7 @@ class OS_X11 : public OS_Unix {
bool minimized;
int dpad_last[2];
bool do_mouse_warp;
const char *cursor_theme;
int cursor_size;

View File

@ -322,8 +322,8 @@ void Sprite::_bind_methods() {
ADD_PROPERTYNZ( PropertyInfo( Variant::VECTOR2, "offset"), _SCS("set_offset"),_SCS("get_offset"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_h"), _SCS("set_flip_h"),_SCS("is_flipped_h"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "flip_v"), _SCS("set_flip_v"),_SCS("is_flipped_v"));
ADD_PROPERTYNO( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes"));
ADD_PROPERTYNO( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes"));
ADD_PROPERTYNO( PropertyInfo( Variant::INT, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_vframes"),_SCS("get_vframes"));
ADD_PROPERTYNO( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_hframes"),_SCS("get_hframes"));
ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame"));
ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate"));
ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region"));

View File

@ -578,8 +578,8 @@ void Sprite3D::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_hframes"),&Sprite3D::get_hframes);
ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_texture"),_SCS("get_texture"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes"), _SCS("set_vframes"),_SCS("get_vframes"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes"), _SCS("set_hframes"),_SCS("get_hframes"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "vframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_vframes"),_SCS("get_vframes"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "hframes",PROPERTY_HINT_RANGE,"1,16384,1"), _SCS("set_hframes"),_SCS("get_hframes"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "frame",PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"),_SCS("get_frame"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "region"), _SCS("set_region"),_SCS("is_region"));
ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region_rect"), _SCS("set_region_rect"),_SCS("get_region_rect"));

View File

@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "spin_box.h"
#include "os/input.h"
Size2 SpinBox::get_minimum_size() const {
@ -62,6 +62,13 @@ LineEdit *SpinBox::get_line_edit() {
}
void SpinBox::_line_edit_input(const InputEvent& p_event) {
}
void SpinBox::_input_event(const InputEvent& p_event) {
if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed) {
@ -94,6 +101,48 @@ void SpinBox::_input_event(const InputEvent& p_event) {
} break;
}
}
if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) {
//set_default_cursor_shape(CURSOR_VSIZE);
Vector2 cpos = Vector2(p_event.mouse_button.x,p_event.mouse_button.y);
drag.mouse_pos=cpos;
}
if (p_event.type==InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) {
//set_default_cursor_shape(CURSOR_ARROW);
if (drag.enabled) {
drag.enabled=false;
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
warp_mouse(drag.capture_pos);
}
}
if (p_event.type==InputEvent::MOUSE_MOTION && p_event.mouse_button.button_mask&1) {
Vector2 cpos = Vector2(p_event.mouse_motion.x,p_event.mouse_motion.y);
if (drag.enabled) {
float diff_y = drag.mouse_pos.y - cpos.y;
diff_y=pow(ABS(diff_y),1.8)*SGN(diff_y);
diff_y*=0.1;
drag.mouse_pos=cpos;
drag.base_val=CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max());
set_val( drag.base_val);
} else if (drag.mouse_pos.distance_to(cpos)>2) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
drag.enabled=true;
drag.base_val=get_val();
drag.mouse_pos=cpos;
drag.capture_pos=cpos;
}
}
}
@ -177,6 +226,7 @@ void SpinBox::_bind_methods() {
ObjectTypeDB::bind_method(_MD("is_editable"),&SpinBox::is_editable);
ObjectTypeDB::bind_method(_MD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit);
ObjectTypeDB::bind_method(_MD("get_line_edit"),&SpinBox::get_line_edit);
ObjectTypeDB::bind_method(_MD("_line_edit_input"),&SpinBox::_line_edit_input);
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"editable"),_SCS("set_editable"),_SCS("is_editable"));
@ -196,4 +246,6 @@ SpinBox::SpinBox() {
//connect("value_changed",this,"_value_changed");
line_edit->connect("text_entered",this,"_text_entered",Vector<Variant>(),CONNECT_DEFERRED);
line_edit->connect("focus_exit",this,"_line_edit_focus_exit",Vector<Variant>(),CONNECT_DEFERRED);
line_edit->connect("input_event",this,"_line_edit_input");
drag.enabled=false;
}

View File

@ -44,6 +44,18 @@ class SpinBox : public Range {
String prefix;
String suffix;
void _line_edit_input(const InputEvent& p_event);
struct Drag {
float base_val;
bool enabled;
Vector2 from;
Vector2 mouse_pos;
Vector2 capture_pos;
} drag;
void _line_edit_focus_exit();
protected:

View File

@ -31,7 +31,7 @@
#include "os/os.h"
#include "os/keyboard.h"
#include "globals.h"
#include "os/input.h"
@ -70,6 +70,7 @@ Size2 TreeItem::Cell::get_icon_size() const {
else
return icon_region.size;
}
void TreeItem::Cell::draw_icon(const RID& p_where, const Point2& p_pos, const Size2& p_size) const{
if (icon.is_null())
@ -728,14 +729,20 @@ TreeItem::~TreeItem() {
tree->root=0;
}
if (tree && tree->popup_edited_item==this)
if (tree && tree->popup_edited_item==this) {
tree->popup_edited_item=NULL;
tree->pressing_for_editor=false;
}
if (tree && tree->selected_item==this)
tree->selected_item=NULL;
if (tree && tree->edited_item==this)
if (tree && tree->edited_item==this) {
tree->edited_item=NULL;
tree->pressing_for_editor=false;
}
}
@ -1292,7 +1299,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col
} else if (select_mode==SELECT_SINGLE || select_mode==SELECT_MULTI) {
if (&selected_cell==&c) {
if (!r_in_range && &selected_cell==&c) {
if (!selected_cell.selected) {
@ -1301,6 +1308,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col
selected_item=p_selected;
selected_col=i;
emit_signal("cell_selected");
if (select_mode==SELECT_MULTI)
emit_signal("multi_selected",p_current,i,true);
@ -1317,6 +1325,7 @@ void Tree::select_single_item(TreeItem *p_selected,TreeItem *p_current,int p_col
if (r_in_range && *r_in_range) {
if (!c.selected && c.selectable) {
c.selected=true;
emit_signal("multi_selected",p_current,i,true);
@ -1467,7 +1476,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
if (select_mode==SELECT_MULTI && p_mod.shift && selected_item && selected_item!=p_item) {
bool inrange=false;
print_line("SELECT MULTI AND SHIFT AND ALL");
select_single_item( p_item, root, col,selected_item,&inrange );
} else {
select_single_item( p_item, root, col );
@ -1490,7 +1499,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
/* editing */
bool bring_up_editor=c.selected && already_selected;
bool bring_up_editor=c.selected;// && already_selected;
bool bring_up_value_editor=false;
String editor_text=c.text;
@ -1605,31 +1614,14 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
return -1;
click_handled=true;
popup_edited_item=p_item;
popup_edited_item_col=col;
text_editor->set_pos(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset );
text_editor->set_size( Size2(col_width,item_h));
text_editor->clear();
text_editor->set_text( editor_text );
text_editor->select_all();
if (bring_up_value_editor) {
value_editor->set_pos(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset+Point2i(0,text_editor->get_size().height) );
value_editor->set_size( Size2(col_width,1));
value_editor->show_modal();
updating_value_editor=true;
value_editor->set_min( c.min );
value_editor->set_max( c.max );
value_editor->set_step( c.step );
value_editor->set_val( c.val );
value_editor->set_exp_unit_value( c.expr );
updating_value_editor=false;
}
text_editor->show_modal();
text_editor->grab_focus();
pressing_item_rect=Rect2(get_global_pos() + Point2i(col_ofs,_get_title_button_height()+y_ofs)-cache.offset,Size2(col_width,item_h));
pressing_for_editor_text=editor_text;
pressing_for_editor=true;
return -1; //select
} else {
@ -2062,6 +2054,33 @@ void Tree::_input_event(InputEvent p_event) {
update();
}
if (pressing_for_editor && popup_edited_item && popup_edited_item->get_cell_mode(popup_edited_item_col)==TreeItem::CELL_MODE_RANGE) {
//range drag
if (!range_drag_enabled) {
Vector2 cpos = Vector2(b.x,b.y);
if (cpos.distance_to(pressing_pos)>2) {
range_drag_enabled=true;
range_drag_capture_pos=cpos;
range_drag_base=popup_edited_item->get_range(popup_edited_item_col);
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
}
} else {
TreeItem::Cell &c=popup_edited_item->cells[popup_edited_item_col];
float diff_y = -b.relative_y;
diff_y=pow(ABS(diff_y),1.8)*SGN(diff_y);
diff_y*=0.1;
range_drag_base=CLAMP(range_drag_base + c.step * diff_y, c.min, c.max);
popup_edited_item->set_range(popup_edited_item_col,range_drag_base);
item_edited(popup_edited_item_col,popup_edited_item);
}
}
if (drag_touching && ! drag_touching_deaccel) {
@ -2084,6 +2103,31 @@ void Tree::_input_event(InputEvent p_event) {
if (b.button_index==BUTTON_LEFT) {
if (pressing_for_editor) {
if (range_drag_enabled) {
range_drag_enabled=false;
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
warp_mouse(range_drag_capture_pos);
} else {
text_editor->set_pos(pressing_item_rect.pos);
text_editor->set_size(pressing_item_rect.size);
text_editor->clear();
text_editor->set_text( pressing_for_editor_text );
text_editor->select_all();
text_editor->show_modal();
text_editor->grab_focus();
}
pressing_for_editor=false;
}
if (cache.click_type==Cache::CLICK_BUTTON) {
emit_signal("button_pressed",cache.click_item,cache.click_column,cache.click_id);
@ -2145,11 +2189,15 @@ void Tree::_input_event(InputEvent p_event) {
break;
click_handled=false;
pressing_for_editor=false;
blocked++;
bool handled = propagate_mouse_event(pos+cache.offset,0,0,b.doubleclick,root,b.button_index,b.mod);
blocked--;
if (pressing_for_editor) {
pressing_pos=Point2(b.x,b.y);
}
if (drag_touching) {
@ -2615,6 +2663,8 @@ void Tree::clear() {
selected_item=NULL;
edited_item=NULL;
popup_edited_item=NULL;
selected_item=NULL;
pressing_for_editor=false;
update();
};
@ -3189,6 +3239,8 @@ Tree::Tree() {
drag_speed=0;
drag_touching=false;
drag_touching_deaccel=false;
pressing_for_editor=false;
range_drag_enabled=false;
}

View File

@ -258,7 +258,18 @@ friend class TreeItem;
TreeItem *popup_edited_item;
TreeItem *selected_item;
TreeItem *edited_item;
int pressed_button;
bool pressing_for_editor;
String pressing_for_editor_text;
Vector2 pressing_pos;
Rect2 pressing_item_rect;
float range_drag_base;
bool range_drag_enabled;
Vector2 range_drag_capture_pos;
//TreeItem *cursor_item;
//int cursor_column;

View File

@ -297,7 +297,7 @@ void make_default_theme() {
t->set_color("font_color_hover","MenuButton", control_font_color_hover );
t->set_color("font_color_disabled","MenuButton", Color(1,1,1,0.3) );
t->set_constant("hseparation","MenuButton", 0 );
t->set_constant("hseparation","MenuButton", 3 );
// CheckBox

View File

@ -0,0 +1,231 @@
#include "array_property_edit.h"
#include "editor_node.h"
#define ITEMS_PER_PAGE 100
Variant ArrayPropertyEdit::get_array() const{
Object*o = ObjectDB::get_instance(obj);
if (!o)
return Array();
Variant arr=o->get(property);
if (!arr.is_array()) {
Variant::CallError ce;
arr=Variant::construct(default_type,NULL,0,ce);
}
return arr;
}
void ArrayPropertyEdit::_notif_change() {
_change_notify();
}
void ArrayPropertyEdit::_notif_changev(const String& p_v) {
_change_notify(p_v.utf8().get_data());
}
void ArrayPropertyEdit::_set_size(int p_size) {
Variant arr = get_array();
arr.call("resize",p_size);
Object*o = ObjectDB::get_instance(obj);
if (!o)
return;
o->set(property,arr);
}
void ArrayPropertyEdit::_set_value(int p_idx,const Variant& p_value) {
Variant arr = get_array();
arr.set(p_idx,p_value);
Object*o = ObjectDB::get_instance(obj);
if (!o)
return;
o->set(property,arr);
}
bool ArrayPropertyEdit::_set(const StringName& p_name, const Variant& p_value){
String pn=p_name;
if (pn.begins_with("array/")) {
if (pn=="array/size") {
Variant arr = get_array();
int size = arr.call("size");
int newsize=p_value;
if (newsize==size)
return true;
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action("Resize Array");
ur->add_do_method(this,"_set_size",newsize);
ur->add_undo_method(this,"_set_size",size);
if (newsize<size) {
for(int i=newsize;i<size;i++) {
ur->add_undo_method(this,"_set_value",i,arr.get(i));
}
}
ur->add_do_method(this,"_notif_change");
ur->add_undo_method(this,"_notif_change");
ur->commit_action();
return true;
}
if (pn=="array/page") {
page=p_value;
_change_notify();
return true;
}
} else if (pn.begins_with("indices")) {
if (pn.find("_")!=-1) {
//type
int idx=pn.get_slicec('/',1).get_slicec('_',0).to_int();
int type = p_value;
Variant arr = get_array();
Variant value = arr.get(idx);
if (value.get_type()!=type && type>=0 && type<Variant::VARIANT_MAX) {
Variant::CallError ce;
Variant new_value=Variant::construct(Variant::Type(type),NULL,0,ce);
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action("Change Array Value Type");
ur->add_do_method(this,"_set_value",idx,new_value);
ur->add_undo_method(this,"_set_value",idx,value);
ur->add_do_method(this,"_notif_change");
ur->add_undo_method(this,"_notif_change");
ur->commit_action();
}
return true;
} else {
int idx=pn.get_slicec('/',1).to_int();
Variant arr = get_array();
Variant value = arr.get(idx);
UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
ur->create_action("Change Array Value");
ur->add_do_method(this,"_set_value",idx,p_value);
ur->add_undo_method(this,"_set_value",idx,value);
ur->add_do_method(this,"_notif_changev",p_name);
ur->add_undo_method(this,"_notif_changev",p_name);
ur->commit_action();
return true;
}
}
return false;
}
bool ArrayPropertyEdit::_get(const StringName& p_name,Variant &r_ret) const {
Variant arr = get_array();
//int size = arr.call("size");
String pn=p_name;
if (pn.begins_with("array/")) {
if (pn=="array/size") {
r_ret=arr.call("size");
return true;
}
if (pn=="array/page") {
r_ret=page;
return true;
}
} else if (pn.begins_with("indices")) {
if (pn.find("_")!=-1) {
//type
int idx=pn.get_slicec('/',1).get_slicec('_',0).to_int();
bool valid;
r_ret=arr.get(idx,&valid);
if (valid)
r_ret=r_ret.get_type();
return valid;
} else {
int idx=pn.get_slicec('/',1).to_int();
bool valid;
r_ret=arr.get(idx,&valid);
return valid;
}
}
return false;
}
void ArrayPropertyEdit::_get_property_list( List<PropertyInfo> *p_list) const{
Variant arr = get_array();
int size = arr.call("size");
p_list->push_back( PropertyInfo(Variant::INT,"array/size",PROPERTY_HINT_RANGE,"0,100000,1") );
int pages = size/ITEMS_PER_PAGE;
if (pages>0)
p_list->push_back( PropertyInfo(Variant::INT,"array/page",PROPERTY_HINT_RANGE,"0,"+itos(pages)+",1") );
int offset=page*ITEMS_PER_PAGE;
int items=MIN(size-offset,ITEMS_PER_PAGE);
for(int i=0;i<items;i++) {
Variant v=arr.get(i+offset);
if (arr.get_type()==Variant::ARRAY) {
p_list->push_back(PropertyInfo(Variant::INT,"indices/"+itos(i+offset)+"_type",PROPERTY_HINT_ENUM,vtypes));
}
if (arr.get_type()!=Variant::ARRAY || v.get_type()!=Variant::NIL) {
PropertyInfo pi(v.get_type(),"indices/"+itos(i+offset));
if (v.get_type()==Variant::OBJECT) {
pi.hint=PROPERTY_HINT_RESOURCE_TYPE;
pi.hint_string="Resource";
}
p_list->push_back(pi);
}
}
}
void ArrayPropertyEdit::edit(Object* p_obj,const StringName& p_prop,Variant::Type p_deftype) {
page=0;
property=p_prop;
obj=p_obj->get_instance_ID();
default_type=p_deftype;
}
void ArrayPropertyEdit::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_set_size"),&ArrayPropertyEdit::_set_size);
ObjectTypeDB::bind_method(_MD("_set_value"),&ArrayPropertyEdit::_set_value);
ObjectTypeDB::bind_method(_MD("_notif_change"),&ArrayPropertyEdit::_notif_change);
ObjectTypeDB::bind_method(_MD("_notif_changev"),&ArrayPropertyEdit::_notif_changev);
}
ArrayPropertyEdit::ArrayPropertyEdit()
{
page=0;
for(int i=0;i<Variant::VARIANT_MAX;i++) {
if (i>0)
vtypes+=",";
vtypes+=Variant::get_type_name( Variant::Type(i) );
}
default_type=Variant::NIL;
}

View File

@ -0,0 +1,36 @@
#ifndef ARRAY_PROPERTY_EDIT_H
#define ARRAY_PROPERTY_EDIT_H
#include "scene/main/node.h"
class ArrayPropertyEdit : public Reference {
OBJ_TYPE(ArrayPropertyEdit,Reference);
int page;
ObjectID obj;
StringName property;
String vtypes;
Variant get_array() const;
Variant::Type default_type;
void _notif_change();
void _notif_changev(const String& p_v);
void _set_size(int p_size);
void _set_value(int p_idx,const Variant& p_value);
protected:
static void _bind_methods();
bool _set(const StringName& p_name, const Variant& p_value);
bool _get(const StringName& p_name,Variant &r_ret) const;
void _get_property_list( List<PropertyInfo> *p_list) const;
public:
void edit(Object* p_obj, const StringName& p_prop, Variant::Type p_deftype);
ArrayPropertyEdit();
};
#endif // ARRAY_PROPERTY_EDIT_H

View File

@ -523,7 +523,7 @@ Ref<Script> EditorData::get_scene_root_script(int p_idx) const {
if (!edited_scene[p_idx].root)
return Ref<Script>();
Ref<Script> s=edited_scene[p_idx].root->get_script();
if (!s.is_valid()) {
if (!s.is_valid() && edited_scene[p_idx].root->get_child_count()) {
Node *n = edited_scene[p_idx].root->get_child(0);
while(!s.is_valid() && n && n->get_filename()==String()) {
s=n->get_script();

View File

@ -93,7 +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"
#include "os/input.h"
// end
#include "tools/editor/io_plugins/editor_texture_import_plugin.h"
#include "tools/editor/io_plugins/editor_scene_import_plugin.h"
@ -1765,6 +1765,7 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) {
int idx = editor_data.add_edited_scene(-1);
_scene_tab_changed(idx);
editor_data.clear_editor_states();
//_cleanup_scene();
@ -4163,6 +4164,14 @@ EditorNode::EditorNode() {
EditorHelp::generate_doc(); //before any editor classes are crated
if (!OS::get_singleton()->has_touchscreen_ui_hint() && Input::get_singleton()) {
//only if no touchscreen ui hint, set emulation
InputDefault *id = Input::get_singleton()->cast_to<InputDefault>();
if (id)
id->set_emulate_touch(false); //just disable just in case
}
singleton=this;
last_checked_version=0;
changing_scene=false;
@ -4835,6 +4844,7 @@ EditorNode::EditorNode() {
property_editor->set_autoclear(true);
property_editor->set_show_categories(true);
property_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
property_editor->set_use_doc_hints(true);
property_editor->hide_top_label();

View File

@ -549,6 +549,49 @@ void AnimationPlayerEditor::ensure_visibility() {
_animation_edit();
}
Dictionary AnimationPlayerEditor::get_state() const {
Dictionary d;
d["visible"]=is_visible();
if (is_visible() && player) {
d["player"]=EditorNode::get_singleton()->get_edited_scene()->get_path_to(player);
d["animation"]=player->get_current_animation();
d["editing"]=edit_anim->is_pressed();
}
return d;
}
void AnimationPlayerEditor::set_state(const Dictionary& p_state) {
if (p_state.has("visible") && p_state["visible"]) {
Node *n = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["player"]);
if (n && n->cast_to<AnimationPlayer>()) {
player=n->cast_to<AnimationPlayer>();
_update_player();
show();
set_process(true);
ensure_visibility();
EditorNode::get_singleton()->animation_panel_make_visible(true);
if (p_state.has("animation")) {
String anim = p_state["animation"];
_select_anim_by_name(anim);
if (p_state.has("editing") && p_state["editing"]) {
edit_anim->set_pressed(true);
_animation_edit();
}
}
}
}
}
void AnimationPlayerEditor::_animation_resource_edit() {
if (animation->get_item_count()) {

View File

@ -151,6 +151,10 @@ protected:
static void _bind_methods();
public:
Dictionary get_state() const;
void set_state(const Dictionary& p_state);
void ensure_visibility();
void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo=p_undo_redo; }
@ -167,6 +171,9 @@ class AnimationPlayerEditorPlugin : public EditorPlugin {
public:
virtual Dictionary get_state() const { return anim_editor->get_state(); }
virtual void set_state(const Dictionary& p_state) { anim_editor->set_state(p_state); }
virtual String get_name() const { return "Anim"; }
bool has_main_screen() const { return false; }
virtual void edit(Object *p_node);

View File

@ -216,6 +216,8 @@ MeshInstanceEditor::MeshInstanceEditor() {
SpatialEditor::get_singleton()->add_control_to_menu_panel(options);
options->set_text("Mesh");
options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("MeshInstance","EditorIcons"));
options->get_popup()->add_item("Create Trimesh Static Body",MENU_OPTION_CREATE_STATIC_TRIMESH_BODY);
options->get_popup()->add_item("Create Convex Static Body",MENU_OPTION_CREATE_STATIC_CONVEX_BODY);
options->get_popup()->add_separator();

View File

@ -330,6 +330,8 @@ MultiMeshEditor::MultiMeshEditor() {
options->set_area_as_parent_rect();
options->set_text("MultiMesh");
options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("MultiMeshInstance","EditorIcons"));
options->get_popup()->add_item("Populate Surface");
options->get_popup()->connect("item_pressed", this,"_menu_option");

View File

@ -146,6 +146,7 @@ void Particles2DEditorPlugin::_notification(int p_what) {
if (p_what==NOTIFICATION_ENTER_TREE) {
menu->get_popup()->connect("item_pressed",this,"_menu_callback");
menu->set_icon(menu->get_popup()->get_icon("Particles2D","EditorIcons"));
file->connect("file_selected",this,"_file_selected");
}
}

View File

@ -111,6 +111,7 @@ void ParticlesEditor::_populate() {
void ParticlesEditor::_notification(int p_notification) {
if (p_notification==NOTIFICATION_ENTER_TREE) {
options->set_icon(options->get_popup()->get_icon("Particles","EditorIcons"));
}
}

View File

@ -2168,7 +2168,18 @@ void SpatialEditorViewport::set_state(const Dictionary& p_state) {
view_menu->get_popup()->set_item_checked( idx, listener );
}
if (p_state.has("previewing")) {
Node *pv = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["previewing"]);
if (pv && pv->cast_to<Camera>()) {
previewing=pv->cast_to<Camera>();
previewing->connect("exit_tree",this,"_preview_exited_scene");
VS::get_singleton()->viewport_attach_camera( viewport->get_viewport(), previewing->get_camera() ); //replace
view_menu->hide();
surface->update();
preview_camera->set_pressed(true);
preview_camera->show();
}
}
}
Dictionary SpatialEditorViewport::get_state() const {
@ -2181,6 +2192,10 @@ Dictionary SpatialEditorViewport::get_state() const {
d["use_environment"]=camera->get_environment().is_valid();
d["use_orthogonal"]=camera->get_projection()==Camera::PROJECTION_ORTHOGONAL;
d["listener"]=viewport->is_audio_listener();
if (previewing) {
d["previewing"]=EditorNode::get_singleton()->get_edited_scene()->get_path_to(previewing);
}
return d;
}

View File

@ -40,6 +40,8 @@
#include "editor_import_export.h"
#include "editor_node.h"
#include "multi_node_edit.h"
#include "array_property_edit.h"
#include "editor_help.h"
void CustomPropertyEditor::_notification(int p_what) {
@ -2270,6 +2272,23 @@ void PropertyEditor::update_tree() {
sep->set_selectable(1,false);
sep->set_custom_bg_color(0,get_color("prop_category","Editor"));
sep->set_custom_bg_color(1,get_color("prop_category","Editor"));
if (use_doc_hints) {
StringName type=p.name;
if (!class_descr_cache.has(type)) {
String descr;
DocData *dd=EditorHelp::get_doc_data();
Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(type);
if (E) {
descr=E->get().brief_description;
}
class_descr_cache[type]=descr.world_wrap(80);
}
sep->set_tooltip(0,"Class: "+p.name+":\n\n"+class_descr_cache[type]);
}
//sep->set_custom_color(0,Color(1,1,1));
@ -2323,6 +2342,42 @@ void PropertyEditor::update_tree() {
item->set_tooltip(0, p.name);
if (use_doc_hints) {
StringName setter;
StringName type;
if (ObjectTypeDB::get_setter_and_type_for_property(obj->get_type_name(),p.name,type,setter)) {
String descr;
bool found=false;
Map<StringName,Map<StringName,String> >::Element *E=descr_cache.find(type);
if (E) {
Map<StringName,String>::Element *F=E->get().find(setter);
if (F) {
found=true;
descr=F->get();
}
}
if (!found) {
DocData *dd=EditorHelp::get_doc_data();
Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(type);
if (E) {
for(int i=0;i<E->get().methods.size();i++) {
if (E->get().methods[i].name==setter.operator String()) {
descr=E->get().methods[i].description.strip_edges().world_wrap(80);
}
}
}
descr_cache[type][setter]=descr;
}
item->set_tooltip(0, "Property: "+p.name+"\n\n"+descr);
}
}
//EditorHelp::get_doc_data();
Dictionary d;
d["name"]=p.name;
d["type"]=(int)p.type;
@ -2405,8 +2460,10 @@ void PropertyEditor::update_tree() {
item->set_cell_mode( 1, TreeItem::CELL_MODE_RANGE );
if (p.hint==PROPERTY_HINT_SPRITE_FRAME) {
item->set_range_config(1,0,99999,1);
if (p.hint==PROPERTY_HINT_RANGE || p.hint==PROPERTY_HINT_EXP_RANGE) {
} else if (p.hint==PROPERTY_HINT_RANGE || p.hint==PROPERTY_HINT_EXP_RANGE) {
int c = p.hint_string.get_slice_count(",");
float min=0,max=100,step=1;
@ -2507,11 +2564,32 @@ void PropertyEditor::update_tree() {
}
} break;
case Variant::ARRAY: {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->add_button(1,get_icon("EditResource","EditorIcons"));
Variant v = obj->get(p.name);
if (v.is_array())
item->set_text(1,"Array["+itos(v.call("size"))+"]");
else
item->set_text(1,"Array[]");
item->set_icon( 0, get_icon("ArrayData","EditorIcons") );
} break;
case Variant::INT_ARRAY: {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->set_editable( 1, !read_only );
item->set_text(1,"[IntArray]");
item->add_button(1,get_icon("EditResource","EditorIcons"));
Variant v = obj->get(p.name);
if (v.is_array())
item->set_text(1,"IntArray["+itos(v.call("size"))+"]");
else
item->set_text(1,"IntArray[]");
item->set_icon( 0, get_icon("ArrayInt","EditorIcons") );
@ -2519,26 +2597,86 @@ void PropertyEditor::update_tree() {
case Variant::REAL_ARRAY: {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->set_editable( 1, !read_only );
item->set_text(1,"[RealArray]");
item->add_button(1,get_icon("EditResource","EditorIcons"));
Variant v = obj->get(p.name);
if (v.is_array())
item->set_text(1,"FloatArray["+itos(v.call("size"))+"]");
else
item->set_text(1,"FloatArray[]");
item->set_icon( 0, get_icon("ArrayReal","EditorIcons") );
} break;
case Variant::STRING_ARRAY: {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->set_editable( 1, !read_only );
item->set_text(1,"[StringArray]");
item->add_button(1,get_icon("EditResource","EditorIcons"));
Variant v = obj->get(p.name);
if (v.is_array())
item->set_text(1,"String["+itos(v.call("size"))+"]");
else
item->set_text(1,"String[]");
item->set_icon( 0, get_icon("ArrayString","EditorIcons") );
} break;
case Variant::RAW_ARRAY: {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->set_editable( 1, !read_only );
item->set_text(1,"[Raw Data]");
item->add_button(1,get_icon("EditResource","EditorIcons"));
Variant v = obj->get(p.name);
if (v.is_array())
item->set_text(1,"Byte["+itos(v.call("size"))+"]");
else
item->set_text(1,"Byte[]");
item->set_icon( 0, get_icon("ArrayData","EditorIcons") );
} break;
case Variant::VECTOR2_ARRAY: {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->add_button(1,get_icon("EditResource","EditorIcons"));
Variant v = obj->get(p.name);
if (v.is_array())
item->set_text(1,"Vector2["+itos(v.call("size"))+"]");
else
item->set_text(1,"Vector2[]");
item->set_icon( 0, get_icon("Vector2","EditorIcons") );
} break;
case Variant::VECTOR3_ARRAY: {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->add_button(1,get_icon("EditResource","EditorIcons"));
Variant v = obj->get(p.name);
if (v.is_array())
item->set_text(1,"Vector3["+itos(v.call("size"))+"]");
else
item->set_text(1,"Vector3[]");
item->set_icon( 0, get_icon("Vector","EditorIcons") );
} break;
case Variant::COLOR_ARRAY: {
item->set_cell_mode( 1, TreeItem::CELL_MODE_CUSTOM );
item->add_button(1,get_icon("EditResource","EditorIcons"));
Variant v = obj->get(p.name);
if (v.is_array())
item->set_text(1,"Color["+itos(v.call("size"))+"]");
else
item->set_text(1,"Color[]");
item->set_icon( 0, get_icon("Color","EditorIcons") );
} break;
case Variant::VECTOR2: {
@ -2734,7 +2872,7 @@ void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value) {
}
}
if (!undo_redo || obj->cast_to<MultiNodeEdit>()) { //kind of hacky
if (!undo_redo || obj->cast_to<MultiNodeEdit>() || obj->cast_to<ArrayPropertyEdit>()) { //kind of hacky
obj->set(p_name,p_value);
_changed_callbacks(obj,p_name);
@ -3054,6 +3192,19 @@ void PropertyEditor::_edit_button(Object *p_item, int p_column, int p_button) {
emit_signal("resource_selected",r,n);
}
} else if (t==Variant::ARRAY || t==Variant::INT_ARRAY || t==Variant::REAL_ARRAY || t==Variant::STRING_ARRAY || t==Variant::VECTOR2_ARRAY || t==Variant::VECTOR3_ARRAY || t==Variant::COLOR_ARRAY || t==Variant::RAW_ARRAY) {
Variant v = obj->get(n);
if (v.get_type()!=t) {
Variant::CallError ce;
v=Variant::construct(Variant::Type(t),NULL,0,ce);
}
Ref<ArrayPropertyEdit> ape = memnew( ArrayPropertyEdit );
ape->edit(obj,n,Variant::Type(t));
EditorNode::get_singleton()->push_item(ape.ptr());
}
}
}
@ -3239,6 +3390,7 @@ PropertyEditor::PropertyEditor() {
read_only=false;
show_categories=false;
refresh_countdown=0;
use_doc_hints=false;
}

View File

@ -96,6 +96,7 @@ class CustomPropertyEditor : public Popup {
SpinBox *spinbox;
HSlider *slider;
Control *easing_draw;
Object* owner;
@ -159,10 +160,14 @@ class PropertyEditor : public Control {
bool read_only;
bool show_categories;
float refresh_countdown;
bool use_doc_hints;
HashMap<String,String> pending;
String selected_property;
Map<StringName,Map<StringName,String> > descr_cache;
Map<StringName,String > class_descr_cache;
CustomPropertyEditor *custom_editor;
void _resource_edit_request();
@ -219,6 +224,7 @@ public:
void set_autoclear(bool p_enable);
void set_show_categories(bool p_show);
void set_use_doc_hints(bool p_enable) { use_doc_hints=p_enable; }
PropertyEditor();
~PropertyEditor();