summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorFranco Eusébio Garcia <francoegarcia@outlook.com>2016-05-01 05:33:32 -0300
committerRémi Verschelde <remi@verschelde.fr>2016-05-01 10:33:32 +0200
commita735573327d26536bd29e14350f1e5811c030b86 (patch)
treee37ff9ff7c196f66178233c292af40dd833ee9eb /tools
parentff40dcd83f7cc74446ee90a911b58c165b6e164f (diff)
Add math/script expression evaluation in editor (#3620)
Rebase of #453
Diffstat (limited to 'tools')
-rw-r--r--tools/editor/property_editor.cpp189
-rw-r--r--tools/editor/property_editor.h28
2 files changed, 184 insertions, 33 deletions
diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp
index 1340670db1..110f5bb7f5 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<Node>();
@@ -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<Script> script= Ref<Script>(script_language ->create_script());
+ script->set_source_code(_build_script(p_text));
+ Error err = script->reload();
+ if (err) {
+ print_line("[PropertyValueEvaluator] Error loading script for expression: " + p_text);
+ return _default_eval(p_text);
+ }
+
+ ScriptInstance *script_instance = script->instance_create(this);
+
+ Variant::CallError call_err;
+ script_instance->call("set_this",obj);
+ double result = script_instance->call("e", NULL, 0, call_err );
+ if (call_err.error == Variant::CallError::CALL_OK) {
+ return result;
+ }
+ print_line("[PropertyValueEvaluator]: Error eval! Error code: " + itos(call_err.error));
+
+ memdelete(script_instance);
+
+ return _default_eval(p_text);
+}
+
+
+void PropertyValueEvaluator::edit(Object *p_obj) {
+ obj = p_obj;
+}
+
+String PropertyValueEvaluator::_build_script(const String& p_text) {
+ String script_text = "tool\nvar this\nfunc set_this(p_this):\n\tthis=p_this\nfunc e():\n\treturn ";
+ script_text += p_text.strip_edges();
+ script_text += "\n";
+ return script_text;
+}
+
+PropertyValueEvaluator::PropertyValueEvaluator() {
+ script_language = ScriptServer::get_language(0); // todo: get script language from editor setting
+}
+
+PropertyValueEvaluator::~PropertyValueEvaluator() {
+
+}
diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h
index b870a618e9..1fedb832ed 100644
--- a/tools/editor/property_editor.h
+++ b/tools/editor/property_editor.h
@@ -46,6 +46,8 @@
@author Juan Linietsky <reduzio@gmail.com>
*/
+class PropertyValueEvaluator;
+
class CustomPropertyEditor : public Popup {
OBJ_TYPE( CustomPropertyEditor, Popup );
@@ -104,6 +106,8 @@ class CustomPropertyEditor : public Popup {
bool updating;
+ PropertyValueEvaluator *evaluator;
+
void _text_edit_changed();
void _file_selected(String p_file);
void _scroll_modified(double p_value);
@@ -137,6 +141,8 @@ public:
void set_read_only(bool p_read_only) { read_only=p_read_only; }
+ void set_value_evaluator( PropertyValueEvaluator *p_evaluator) { evaluator=p_evaluator; }
+
bool edit(Object* p_owner,const String& p_name,Variant::Type p_type, const Variant& p_variant,int p_hint,String p_hint_text);
CustomPropertyEditor();
@@ -151,6 +157,8 @@ class PropertyEditor : public Control {
//Object *object;
LineEdit *search_box;
+ PropertyValueEvaluator *evaluator;
+
Object* obj;
Array _prop_edited_name;
@@ -283,4 +291,24 @@ public:
~SectionedPropertyEditor();
};
+class PropertyValueEvaluator : public ValueEvaluator {
+ OBJ_TYPE( PropertyValueEvaluator, ValueEvaluator );
+
+ Object *obj;
+ ScriptLanguage *script_language;
+ String _build_script(const String& p_text);
+
+ _FORCE_INLINE_ double _default_eval(const String& p_text) {
+ return p_text.to_double();
+ }
+
+public:
+
+ void edit(Object *p_obj);
+ double eval(const String& p_text);
+
+ PropertyValueEvaluator();
+ ~PropertyValueEvaluator();
+};
+
#endif