From a735573327d26536bd29e14350f1e5811c030b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franco=20Eus=C3=A9bio=20Garcia?= Date: Sun, 1 May 2016 05:33:32 -0300 Subject: [PATCH] Add math/script expression evaluation in editor (#3620) Rebase of #453 --- core/helper/value_evaluator.h | 43 +++++++ scene/gui/tree.cpp | 26 ++++- scene/gui/tree.h | 6 +- tools/editor/property_editor.cpp | 189 +++++++++++++++++++++++++------ tools/editor/property_editor.h | 28 +++++ 5 files changed, 252 insertions(+), 40 deletions(-) create mode 100644 core/helper/value_evaluator.h diff --git a/core/helper/value_evaluator.h b/core/helper/value_evaluator.h new file mode 100644 index 00000000000..a03602bc614 --- /dev/null +++ b/core/helper/value_evaluator.h @@ -0,0 +1,43 @@ +/*************************************************************************/ +/* value_evaluator.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef VALUE_EVALUATOR_H +#define VALUE_EVALUATOR_H + +#include "core/object.h" + +class ValueEvaluator : public Object { + + OBJ_TYPE(ValueEvaluator, Object); +public: + virtual double eval(const String& p_text) { + return p_text.to_double(); + } +}; + +#endif // VALUE_EVALUATOR_H diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 718206dee1b..278e6584fa4 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -154,7 +154,7 @@ void TreeItem::set_text(int p_column,String p_text) { ERR_FAIL_INDEX( p_column, cells.size() ); cells[p_column].text=p_text; - if (cells[p_column].mode==TreeItem::CELL_MODE_RANGE) { + if (cells[p_column].mode==TreeItem::CELL_MODE_RANGE || cells[p_column].mode==TreeItem::CELL_MODE_RANGE_EXPRESSION) { cells[p_column].min=0; cells[p_column].max=p_text.get_slice_count(","); @@ -704,6 +704,7 @@ void TreeItem::_bind_methods() { BIND_CONSTANT( CELL_MODE_STRING ); BIND_CONSTANT( CELL_MODE_CHECK ); BIND_CONSTANT( CELL_MODE_RANGE ); + BIND_CONSTANT( CELL_MODE_RANGE_EXPRESSION ); BIND_CONSTANT( CELL_MODE_ICON ); BIND_CONSTANT( CELL_MODE_CUSTOM ); @@ -1127,7 +1128,8 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& //font->draw( ci, text_pos, p_item->cells[i].text, col,item_rect.size.x-check_w ); } break; - case TreeItem::CELL_MODE_RANGE: { + case TreeItem::CELL_MODE_RANGE: + case TreeItem::CELL_MODE_RANGE_EXPRESSION: { if (p_item->cells[i].text!="") { @@ -1594,7 +1596,8 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_ } } break; - case TreeItem::CELL_MODE_RANGE: { + case TreeItem::CELL_MODE_RANGE: + case TreeItem::CELL_MODE_RANGE_EXPRESSION: { if (c.text!="") { @@ -1794,6 +1797,13 @@ void Tree::text_editor_enter(String p_text) { //popup_edited_item->edited_signal.call( popup_edited_item_col ); } break; + case TreeItem::CELL_MODE_RANGE_EXPRESSION: { + + if(evaluator) + c.val=evaluator->eval(p_text); + else + c.val=p_text.to_double(); + } break; default: { ERR_FAIL(); } } @@ -2372,7 +2382,7 @@ bool Tree::edit_selected() { item_edited(col,s); return true; - } else if (c.mode==TreeItem::CELL_MODE_RANGE && c.text!="") { + } else if ((c.mode==TreeItem::CELL_MODE_RANGE||c.mode==TreeItem::CELL_MODE_RANGE_EXPRESSION) && c.text!="") { popup_menu->clear(); for (int i=0;iset_pos( textedpos ); @@ -2398,7 +2408,7 @@ bool Tree::edit_selected() { text_editor->set_text( c.mode==TreeItem::CELL_MODE_STRING?c.text:rtos(c.val) ); text_editor->select_all(); - if (c.mode==TreeItem::CELL_MODE_RANGE) { + if (c.mode==TreeItem::CELL_MODE_RANGE || c.mode==TreeItem::CELL_MODE_RANGE_EXPRESSION ) { value_editor->set_pos(textedpos + Point2i(0,text_editor->get_size().height) ); value_editor->set_size( Size2(rect.size.width,1)); @@ -3227,6 +3237,9 @@ bool Tree::is_folding_hidden() const { return hide_folding; } +void Tree::set_value_evaluator(ValueEvaluator *p_evaluator) { + evaluator = p_evaluator; +} void Tree::_bind_methods() { @@ -3367,6 +3380,7 @@ Tree::Tree() { hide_folding=false; + evaluator=NULL; } diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 1ba1c6a4947..75bcfd8e336 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -34,6 +34,7 @@ #include "scene/gui/line_edit.h" #include "scene/gui/scroll_bar.h" #include "scene/gui/slider.h" +#include "core/helper/value_evaluator.h" /** @author Juan Linietsky @@ -52,6 +53,7 @@ public: CELL_MODE_STRING, ///< just a string CELL_MODE_CHECK, ///< string + check CELL_MODE_RANGE, ///< Contains a range + CELL_MODE_RANGE_EXPRESSION, ///< Contains a range CELL_MODE_ICON, ///< Contains a icon, not editable CELL_MODE_CUSTOM, ///< Contains a custom value, show a string, and an edit button }; @@ -422,6 +424,8 @@ friend class TreeItem; bool hide_folding; + ValueEvaluator *evaluator; + protected: static void _bind_methods(); @@ -482,7 +486,7 @@ public: void set_hide_folding(bool p_hide); bool is_folding_hidden() const; - + void set_value_evaluator(ValueEvaluator *p_evaluator); Tree(); ~Tree(); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 1340670db1f..110f5bb7f58 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -1313,7 +1313,10 @@ void CustomPropertyEditor::_modified(String p_string) { case Variant::REAL: { if (hint!=PROPERTY_HINT_EXP_EASING) { - v=value_editor[0]->get_text().to_double(); + if (evaluator) + evaluator->eval(value_editor[0]->get_text()); + else + v=value_editor[0]->get_text().to_double(); emit_signal("variant_changed"); } @@ -1327,8 +1330,13 @@ void CustomPropertyEditor::_modified(String p_string) { case Variant::VECTOR2: { Vector2 vec; - vec.x=value_editor[0]->get_text().to_double(); - vec.y=value_editor[1]->get_text().to_double(); + if (evaluator) { + vec.x=evaluator->eval(value_editor[0]->get_text()); + vec.y=evaluator->eval(value_editor[1]->get_text()); + } else { + vec.x=value_editor[0]->get_text().to_double(); + vec.y=value_editor[1]->get_text().to_double(); + } v=vec; emit_signal("variant_changed"); @@ -1336,10 +1344,17 @@ void CustomPropertyEditor::_modified(String p_string) { case Variant::RECT2: { Rect2 r2; - r2.pos.x=value_editor[0]->get_text().to_double(); - r2.pos.y=value_editor[1]->get_text().to_double(); - r2.size.x=value_editor[2]->get_text().to_double(); - r2.size.y=value_editor[3]->get_text().to_double(); + if (evaluator) { + r2.pos.x=evaluator->eval(value_editor[0]->get_text()); + r2.pos.y=evaluator->eval(value_editor[1]->get_text()); + r2.size.x=evaluator->eval(value_editor[2]->get_text()); + r2.size.y=evaluator->eval(value_editor[3]->get_text()); + } else { + r2.pos.x=value_editor[0]->get_text().to_double(); + r2.pos.y=value_editor[1]->get_text().to_double(); + r2.size.x=value_editor[2]->get_text().to_double(); + r2.size.y=value_editor[3]->get_text().to_double(); + } v=r2; emit_signal("variant_changed"); @@ -1348,9 +1363,15 @@ void CustomPropertyEditor::_modified(String p_string) { case Variant::VECTOR3: { Vector3 vec; - vec.x=value_editor[0]->get_text().to_double(); - vec.y=value_editor[1]->get_text().to_double(); - vec.z=value_editor[2]->get_text().to_double(); + if (evaluator) { + vec.x=evaluator->eval(value_editor[0]->get_text()); + vec.y=evaluator->eval(value_editor[1]->get_text()); + vec.z=evaluator->eval(value_editor[2]->get_text()); + } else { + vec.x=value_editor[0]->get_text().to_double(); + vec.y=value_editor[1]->get_text().to_double(); + vec.z=value_editor[2]->get_text().to_double(); + } v=vec; emit_signal("variant_changed"); @@ -1358,10 +1379,17 @@ void CustomPropertyEditor::_modified(String p_string) { case Variant::PLANE: { Plane pl; - pl.normal.x=value_editor[0]->get_text().to_double(); - pl.normal.y=value_editor[1]->get_text().to_double(); - pl.normal.z=value_editor[2]->get_text().to_double(); - pl.d=value_editor[3]->get_text().to_double(); + if (evaluator) { + pl.normal.x=evaluator->eval(value_editor[0]->get_text()); + pl.normal.y=evaluator->eval(value_editor[1]->get_text()); + pl.normal.z=evaluator->eval(value_editor[2]->get_text()); + pl.d=evaluator->eval(value_editor[3]->get_text()); + } else { + pl.normal.x=value_editor[0]->get_text().to_double(); + pl.normal.y=value_editor[1]->get_text().to_double(); + pl.normal.z=value_editor[2]->get_text().to_double(); + pl.d=value_editor[3]->get_text().to_double(); + } v=pl; emit_signal("variant_changed"); @@ -1369,10 +1397,17 @@ void CustomPropertyEditor::_modified(String p_string) { case Variant::QUAT: { Quat q; - q.x=value_editor[0]->get_text().to_double(); - q.y=value_editor[1]->get_text().to_double(); - q.z=value_editor[2]->get_text().to_double(); - q.w=value_editor[3]->get_text().to_double(); + if (evaluator) { + q.x=evaluator->eval(value_editor[0]->get_text()); + q.y=evaluator->eval(value_editor[1]->get_text()); + q.z=evaluator->eval(value_editor[2]->get_text()); + q.w=evaluator->eval(value_editor[3]->get_text()); + } else { + q.x=value_editor[0]->get_text().to_double(); + q.y=value_editor[1]->get_text().to_double(); + q.z=value_editor[2]->get_text().to_double(); + q.w=value_editor[3]->get_text().to_double(); + } v=q; emit_signal("variant_changed"); @@ -1380,14 +1415,23 @@ void CustomPropertyEditor::_modified(String p_string) { case Variant::_AABB: { Vector3 pos; - pos.x=value_editor[0]->get_text().to_double(); - pos.y=value_editor[1]->get_text().to_double(); - pos.z=value_editor[2]->get_text().to_double(); Vector3 size; - size.x=value_editor[3]->get_text().to_double(); - size.y=value_editor[4]->get_text().to_double(); - size.z=value_editor[5]->get_text().to_double(); + if (evaluator) { + pos.x=evaluator->eval(value_editor[0]->get_text()); + pos.y=evaluator->eval(value_editor[1]->get_text()); + pos.z=evaluator->eval(value_editor[2]->get_text()); + size.x=evaluator->eval(value_editor[3]->get_text()); + size.y=evaluator->eval(value_editor[4]->get_text()); + size.z=evaluator->eval(value_editor[5]->get_text()); + } else { + pos.x=value_editor[0]->get_text().to_double(); + pos.y=value_editor[1]->get_text().to_double(); + pos.z=value_editor[2]->get_text().to_double(); + size.x=value_editor[3]->get_text().to_double(); + size.y=value_editor[4]->get_text().to_double(); + size.z=value_editor[5]->get_text().to_double(); + } v=AABB(pos,size); emit_signal("variant_changed"); @@ -1396,8 +1440,11 @@ void CustomPropertyEditor::_modified(String p_string) { Matrix32 m; for(int i=0;i<6;i++) { - - m.elements[i/2][i%2]=value_editor[i]->get_text().to_double(); + if (evaluator) { + m.elements[i/2][i%2]=evaluator->eval(value_editor[i]->get_text()); + } else { + m.elements[i/2][i%2]=value_editor[i]->get_text().to_double(); + } } v=m; @@ -1409,7 +1456,11 @@ void CustomPropertyEditor::_modified(String p_string) { Matrix3 m; for(int i=0;i<9;i++) { - m.elements[i/3][i%3]=value_editor[i]->get_text().to_double(); + if (evaluator) { + m.elements[i/3][i%3]=evaluator->eval(value_editor[i]->get_text()); + } else { + m.elements[i/3][i%3]=value_editor[i]->get_text().to_double(); + } } v=m; @@ -1421,13 +1472,24 @@ void CustomPropertyEditor::_modified(String p_string) { Matrix3 basis; for(int i=0;i<9;i++) { - basis.elements[i/3][i%3]=value_editor[(i/3)*4+i%3]->get_text().to_double(); + if (evaluator) { + basis.elements[i/3][i%3]=evaluator->eval(value_editor[(i/3)*4+i%3]->get_text()); + } else { + basis.elements[i/3][i%3]=value_editor[(i/3)*4+i%3]->get_text().to_double(); + } } Vector3 origin; - origin.x=value_editor[3]->get_text().to_double(); - origin.y=value_editor[7]->get_text().to_double(); - origin.z=value_editor[11]->get_text().to_double(); + + if (evaluator) { + origin.x=evaluator->eval(value_editor[3]->get_text()); + origin.y=evaluator->eval(value_editor[7]->get_text()); + origin.z=evaluator->eval(value_editor[11]->get_text()); + } else { + origin.x=value_editor[3]->get_text().to_double(); + origin.y=value_editor[7]->get_text().to_double(); + origin.z=value_editor[11]->get_text().to_double(); + } v=Transform(basis,origin); emit_signal("variant_changed"); @@ -1736,6 +1798,8 @@ CustomPropertyEditor::CustomPropertyEditor() { add_child(menu); menu->connect("item_pressed",this,"_menu_option"); + evaluator = NULL; + spinbox = memnew ( SpinBox ); add_child(spinbox); spinbox->set_area_as_parent_rect(5); @@ -1750,7 +1814,7 @@ CustomPropertyEditor::CustomPropertyEditor() { bool PropertyEditor::_might_be_in_instance() { if (!obj) - return NULL; + return false; Node *node = obj->cast_to(); @@ -2695,8 +2759,11 @@ void PropertyEditor::update_tree() { } + if (p.hint==PROPERTY_HINT_ENUM) + item->set_cell_mode( 1, TreeItem::CELL_MODE_RANGE ); + else + item->set_cell_mode( 1, TreeItem::CELL_MODE_RANGE_EXPRESSION ); - item->set_cell_mode( 1, TreeItem::CELL_MODE_RANGE ); if (p.hint==PROPERTY_HINT_SPRITE_FRAME) { item->set_range_config(1,0,99999,1); @@ -3390,6 +3457,9 @@ void PropertyEditor::edit(Object* p_object) { } obj=p_object; + + evaluator->edit(p_object); + update_tree(); if (obj) { @@ -3719,6 +3789,10 @@ PropertyEditor::PropertyEditor() { custom_editor->connect("resource_edit_request", this,"_resource_edit_request",make_binds(),CONNECT_DEFERRED); tree->set_hide_folding(true); + evaluator = memnew (PropertyValueEvaluator); + tree->set_value_evaluator(evaluator); + custom_editor->set_value_evaluator(evaluator); + capitalize_paths=true; autoclear=false; tree->set_column_titles_visible(false); @@ -3737,6 +3811,7 @@ PropertyEditor::PropertyEditor() { PropertyEditor::~PropertyEditor() { + memdelete(evaluator); } @@ -3975,3 +4050,51 @@ SectionedPropertyEditor::~SectionedPropertyEditor() { memdelete(filter); } + +double PropertyValueEvaluator::eval(const String& p_text) { + + if (!obj) + return _default_eval(p_text); + + Ref