瀏覽代碼

Add math/script expression evaluation in editor (#3620)

Rebase of #453
Franco Eusébio Garcia 9 年之前
父節點
當前提交
a735573327
共有 5 個文件被更改,包括 252 次插入40 次删除
  1. 43 0
      core/helper/value_evaluator.h
  2. 20 6
      scene/gui/tree.cpp
  3. 5 1
      scene/gui/tree.h
  4. 156 33
      tools/editor/property_editor.cpp
  5. 28 0
      tools/editor/property_editor.h

+ 43 - 0
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

+ 20 - 6
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() );
 	ERR_FAIL_INDEX( p_column, cells.size() );
 	cells[p_column].text=p_text;
 	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].min=0;
 		cells[p_column].max=p_text.get_slice_count(",");
 		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_STRING );
 	BIND_CONSTANT( CELL_MODE_CHECK );
 	BIND_CONSTANT( CELL_MODE_CHECK );
 	BIND_CONSTANT( CELL_MODE_RANGE );
 	BIND_CONSTANT( CELL_MODE_RANGE );
+	BIND_CONSTANT( CELL_MODE_RANGE_EXPRESSION );
 	BIND_CONSTANT( CELL_MODE_ICON );
 	BIND_CONSTANT( CELL_MODE_ICON );
 	BIND_CONSTANT( CELL_MODE_CUSTOM );
 	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 );
 					//font->draw( ci, text_pos, p_item->cells[i].text, col,item_rect.size.x-check_w );
 
 
 				} break;
 				} break;
-				case TreeItem::CELL_MODE_RANGE: {
+				case TreeItem::CELL_MODE_RANGE:
+				case TreeItem::CELL_MODE_RANGE_EXPRESSION: {
 
 
 					if (p_item->cells[i].text!="") {
 					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;
 			} break;
-			case TreeItem::CELL_MODE_RANGE: {
+			case TreeItem::CELL_MODE_RANGE:
+			case TreeItem::CELL_MODE_RANGE_EXPRESSION: {
 
 
 
 
 				if (c.text!="") {
 				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 );
 			//popup_edited_item->edited_signal.call( popup_edited_item_col );
 		} break;
 		} 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(); }
 	default: { ERR_FAIL(); }
 	}
 	}
 
 
@@ -2372,7 +2382,7 @@ bool Tree::edit_selected() {
 		item_edited(col,s);
 		item_edited(col,s);
 
 
 		return true;
 		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();
 		popup_menu->clear();
 		for (int i=0;i<c.text.get_slice_count(",");i++) {
 		for (int i=0;i<c.text.get_slice_count(",");i++) {
@@ -2389,7 +2399,7 @@ bool Tree::edit_selected() {
 		popup_edited_item_col=col;
 		popup_edited_item_col=col;
 		return true;
 		return true;
 
 
-	} else if (c.mode==TreeItem::CELL_MODE_STRING || c.mode==TreeItem::CELL_MODE_RANGE) {
+	} else if (c.mode==TreeItem::CELL_MODE_STRING || c.mode==TreeItem::CELL_MODE_RANGE || c.mode==TreeItem::CELL_MODE_RANGE_EXPRESSION ) {
 
 
 		Point2i textedpos=get_global_pos() + rect.pos;
 		Point2i textedpos=get_global_pos() + rect.pos;
 		text_editor->set_pos( textedpos );
 		text_editor->set_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->set_text( c.mode==TreeItem::CELL_MODE_STRING?c.text:rtos(c.val) );
 		text_editor->select_all();
 		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_pos(textedpos + Point2i(0,text_editor->get_size().height) );
 			value_editor->set_size( Size2(rect.size.width,1));
 			value_editor->set_size( Size2(rect.size.width,1));
@@ -3227,6 +3237,9 @@ bool Tree::is_folding_hidden() const {
 	return hide_folding;
 	return hide_folding;
 }
 }
 
 
+void Tree::set_value_evaluator(ValueEvaluator *p_evaluator) {
+	evaluator = p_evaluator;
+}
 
 
 void Tree::_bind_methods() {
 void Tree::_bind_methods() {
 
 
@@ -3367,6 +3380,7 @@ Tree::Tree() {
 
 
 	hide_folding=false;
 	hide_folding=false;
 
 
+	evaluator=NULL;
 }
 }
 
 
 
 

+ 5 - 1
scene/gui/tree.h

@@ -34,6 +34,7 @@
 #include "scene/gui/line_edit.h"
 #include "scene/gui/line_edit.h"
 #include "scene/gui/scroll_bar.h"
 #include "scene/gui/scroll_bar.h"
 #include "scene/gui/slider.h"
 #include "scene/gui/slider.h"
+#include "core/helper/value_evaluator.h"
 
 
 /**
 /**
 	@author Juan Linietsky <[email protected]>
 	@author Juan Linietsky <[email protected]>
@@ -52,6 +53,7 @@ public:
 		CELL_MODE_STRING, ///< just a string
 		CELL_MODE_STRING, ///< just a string
 		CELL_MODE_CHECK, ///< string + check
 		CELL_MODE_CHECK, ///< string + check
 		CELL_MODE_RANGE, ///< Contains a range
 		CELL_MODE_RANGE, ///< Contains a range
+		CELL_MODE_RANGE_EXPRESSION, ///< Contains a range
 		CELL_MODE_ICON, ///< Contains a icon, not editable
 		CELL_MODE_ICON, ///< Contains a icon, not editable
 		CELL_MODE_CUSTOM, ///< Contains a custom value, show a string, and an edit button
 		CELL_MODE_CUSTOM, ///< Contains a custom value, show a string, and an edit button
 	};
 	};
@@ -422,6 +424,8 @@ friend class TreeItem;
 
 
 	bool hide_folding;
 	bool hide_folding;
 
 
+	ValueEvaluator *evaluator;
+
 protected:
 protected:
 	static void _bind_methods();
 	static void _bind_methods();
 
 
@@ -482,7 +486,7 @@ public:
 	void set_hide_folding(bool p_hide);
 	void set_hide_folding(bool p_hide);
 	bool is_folding_hidden() const;
 	bool is_folding_hidden() const;
 
 
-
+	void set_value_evaluator(ValueEvaluator *p_evaluator);
 
 
 	Tree();
 	Tree();
 	~Tree();
 	~Tree();

+ 156 - 33
tools/editor/property_editor.cpp

@@ -1313,7 +1313,10 @@ void CustomPropertyEditor::_modified(String p_string) {
 		case Variant::REAL: {
 		case Variant::REAL: {
 
 
 			if (hint!=PROPERTY_HINT_EXP_EASING) {
 			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");
 				emit_signal("variant_changed");
 
 
 			}
 			}
@@ -1327,8 +1330,13 @@ void CustomPropertyEditor::_modified(String p_string) {
 		case Variant::VECTOR2: {
 		case Variant::VECTOR2: {
 
 
 			Vector2 vec;
 			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;
 			v=vec;
 			emit_signal("variant_changed");
 			emit_signal("variant_changed");
 
 
@@ -1336,10 +1344,17 @@ void CustomPropertyEditor::_modified(String p_string) {
 		case Variant::RECT2: {
 		case Variant::RECT2: {
 
 
 			Rect2 r2;
 			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;
 			v=r2;
 			emit_signal("variant_changed");
 			emit_signal("variant_changed");
 
 
@@ -1348,9 +1363,15 @@ void CustomPropertyEditor::_modified(String p_string) {
 		case Variant::VECTOR3: {
 		case Variant::VECTOR3: {
 
 
 			Vector3 vec;
 			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;
 			v=vec;
 			emit_signal("variant_changed");
 			emit_signal("variant_changed");
 
 
@@ -1358,10 +1379,17 @@ void CustomPropertyEditor::_modified(String p_string) {
 		case Variant::PLANE: {
 		case Variant::PLANE: {
 
 
 			Plane pl;
 			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;
 			v=pl;
 			emit_signal("variant_changed");
 			emit_signal("variant_changed");
 
 
@@ -1369,10 +1397,17 @@ void CustomPropertyEditor::_modified(String p_string) {
 		case Variant::QUAT: {
 		case Variant::QUAT: {
 
 
 			Quat q;
 			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;
 			v=q;
 			emit_signal("variant_changed");
 			emit_signal("variant_changed");
 
 
@@ -1380,14 +1415,23 @@ void CustomPropertyEditor::_modified(String p_string) {
 		case Variant::_AABB: {
 		case Variant::_AABB: {
 
 
 			Vector3 pos;
 			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;
 			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);
 			v=AABB(pos,size);
 			emit_signal("variant_changed");
 			emit_signal("variant_changed");
 
 
@@ -1396,8 +1440,11 @@ void CustomPropertyEditor::_modified(String p_string) {
 
 
 			Matrix32 m;
 			Matrix32 m;
 			for(int i=0;i<6;i++) {
 			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;
 			v=m;
@@ -1409,7 +1456,11 @@ void CustomPropertyEditor::_modified(String p_string) {
 			Matrix3 m;
 			Matrix3 m;
 			for(int i=0;i<9;i++) {
 			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;
 			v=m;
@@ -1421,13 +1472,24 @@ void CustomPropertyEditor::_modified(String p_string) {
 			Matrix3 basis;
 			Matrix3 basis;
 			for(int i=0;i<9;i++) {
 			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;
 			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);
 			v=Transform(basis,origin);
 			emit_signal("variant_changed");
 			emit_signal("variant_changed");
@@ -1736,6 +1798,8 @@ CustomPropertyEditor::CustomPropertyEditor() {
 	add_child(menu);
 	add_child(menu);
 	menu->connect("item_pressed",this,"_menu_option");
 	menu->connect("item_pressed",this,"_menu_option");
 
 
+	evaluator = NULL;
+
 	spinbox = memnew ( SpinBox );
 	spinbox = memnew ( SpinBox );
 	add_child(spinbox);
 	add_child(spinbox);
 	spinbox->set_area_as_parent_rect(5);
 	spinbox->set_area_as_parent_rect(5);
@@ -1750,7 +1814,7 @@ CustomPropertyEditor::CustomPropertyEditor() {
 bool PropertyEditor::_might_be_in_instance() {
 bool PropertyEditor::_might_be_in_instance() {
 
 
 	if (!obj)
 	if (!obj)
-		return NULL;
+		return false;
 
 
 	Node *node = obj->cast_to<Node>();
 	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) {
 				if (p.hint==PROPERTY_HINT_SPRITE_FRAME) {
 					item->set_range_config(1,0,99999,1);
 					item->set_range_config(1,0,99999,1);
 
 
@@ -3390,6 +3457,9 @@ void PropertyEditor::edit(Object* p_object) {
 	}
 	}
 
 
 	obj=p_object;
 	obj=p_object;
+
+	evaluator->edit(p_object);
+
 	update_tree();
 	update_tree();
 
 
 	if (obj) {
 	if (obj) {
@@ -3719,6 +3789,10 @@ PropertyEditor::PropertyEditor() {
 	custom_editor->connect("resource_edit_request", this,"_resource_edit_request",make_binds(),CONNECT_DEFERRED);
 	custom_editor->connect("resource_edit_request", this,"_resource_edit_request",make_binds(),CONNECT_DEFERRED);
 	tree->set_hide_folding(true);
 	tree->set_hide_folding(true);
 
 
+	evaluator = memnew (PropertyValueEvaluator);
+	tree->set_value_evaluator(evaluator);
+	custom_editor->set_value_evaluator(evaluator);
+
 	capitalize_paths=true;
 	capitalize_paths=true;
 	autoclear=false;
 	autoclear=false;
 	tree->set_column_titles_visible(false);
 	tree->set_column_titles_visible(false);
@@ -3737,6 +3811,7 @@ PropertyEditor::PropertyEditor() {
 
 
 PropertyEditor::~PropertyEditor()
 PropertyEditor::~PropertyEditor()
 {
 {
+	memdelete(evaluator);
 }
 }
 
 
 
 
@@ -3975,3 +4050,51 @@ SectionedPropertyEditor::~SectionedPropertyEditor() {
 
 
 	memdelete(filter);
 	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() {
+
+}

+ 28 - 0
tools/editor/property_editor.h

@@ -46,6 +46,8 @@
 	@author Juan Linietsky <[email protected]>
 	@author Juan Linietsky <[email protected]>
 */
 */
 
 
+class PropertyValueEvaluator;
+
 class CustomPropertyEditor : public Popup {
 class CustomPropertyEditor : public Popup {
 
 
 	OBJ_TYPE( CustomPropertyEditor, Popup );
 	OBJ_TYPE( CustomPropertyEditor, Popup );
@@ -104,6 +106,8 @@ class CustomPropertyEditor : public Popup {
 
 
 	bool updating;
 	bool updating;
 
 
+	PropertyValueEvaluator *evaluator;
+
 	void _text_edit_changed();
 	void _text_edit_changed();
 	void _file_selected(String p_file);
 	void _file_selected(String p_file);
 	void _scroll_modified(double p_value);
 	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_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);
 	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();
 	CustomPropertyEditor();
@@ -151,6 +157,8 @@ class PropertyEditor : public Control {
 	//Object *object;
 	//Object *object;
 	LineEdit *search_box;
 	LineEdit *search_box;
 
 
+	PropertyValueEvaluator *evaluator;
+
 	Object* obj;
 	Object* obj;
 
 
 	Array _prop_edited_name;
 	Array _prop_edited_name;
@@ -283,4 +291,24 @@ public:
 	~SectionedPropertyEditor();
 	~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
 #endif