123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- .. _doc_evaluating_expressions:
- Evaluating expressions
- ======================
- Godot provides an :ref:`class_Expression` class you can use to evaluate expressions.
- An expression can be:
- - A mathematical expression such as ``(2 + 4) * 16/4.0``.
- - A built-in method call like ``deg2rad(90)``.
- - A method call on an user-provided script like ``update_health()``,
- if ``base_instance`` is set to a value other than ``null`` when calling
- :ref:`Expression.execute() <class_Expression_method_execute>`.
- .. note::
- The Expression class is independent from GDScript.
- It's available even if you compile Godot with the GDScript module disabled.
- Basic usage
- -----------
- To evaluate a mathematical expression, use::
- var expression = Expression.new()
- expression.parse("20 + 10*2 - 5/2.0")
- var result = expression.execute()
- print(result) # 37.5
- The following operators are available:
- +------------------------+-------------------------------------------------------------------------------------+
- | Operator | Notes |
- +========================+=====================================================================================+
- | Addition ``+`` | Can also be used to concatenate strings and arrays: |
- | | - ``"hello" + " world"`` = ``hello world`` |
- | | - ``[1, 2] + [3, 4]`` = ``[1, 2, 3, 4]`` |
- +------------------------+-------------------------------------------------------------------------------------+
- | Subtraction (``-``) | |
- +------------------------+-------------------------------------------------------------------------------------+
- | Multiplication (``*``) | |
- +------------------------+-------------------------------------------------------------------------------------+
- | Division (``/``) | Performs and integer division if both operands are integers. |
- | | If at least one of them is a floating-point number, returns a floating-point value. |
- +------------------------+-------------------------------------------------------------------------------------+
- | Modulo (``%``) | Returns the remainder of an integer division. |
- +------------------------+-------------------------------------------------------------------------------------+
- Spaces around operators are optional. Also, keep in mind the usual
- `order of operations <https://en.wikipedia.org/wiki/Order_of_operations>`__
- applies. Use parentheses to override the order of operations if needed.
- All the Variant types supported in Godot can be used: integers, floating-point
- numbers, strings, arrays, dictionaries, colors, vectors, …
- Arrays and dictionaries can be indexed like in GDScript::
- # Returns 1.
- [1, 2][0]
- # Returns 3. Negative indices can be used to count from the end of the array.
- [1, 3][-1]
- # Returns "green".
- {"favorite_color": "green"}["favorite_color"]
- # All 3 lines below return 7.0 (Vector3 is floating-point).
- Vector3(5, 6, 7)[2]
- Vector3(5, 6, 7)["z"]
- Vector3(5, 6, 7).z
- Passing variables to an expression
- ----------------------------------
- You can pass variables to an expression. These variables will then
- become available in the expression's "context" and will be substituted when used
- in the expression::
- var expression = Expression.new()
- # Define the variable names first in the second parameter of `parse()`.
- # In this example, we use `x` for the variable name.
- expression.parse("20 + 2 * x", ["x"])
- # Then define the variable values in the first parameter of `execute()`.
- # Here, `x` is assigned the integer value 5.
- var result = expression.execute([5])
- print(result) # 30
- Both the variable names and variable values **must** be specified as an array,
- even if you only define one variable. Also, variable names are **case-sensitive**.
- Setting a base instance for the expression
- ------------------------------------------
- By default, an expression has a base instance of ``null``. This means the
- expression has no base instance associated to it.
- When calling :ref:`Expression.execute() <class_Expression_method_execute>`,
- you can set the value of the ``base_instance`` parameter to a specific object
- instance such as ``self``, another script instance or even a singleton::
- func double(number):
- return number * 2
- func _ready():
- var expression = Expression.new()
- expression.parse("double(10)")
- # This won't work since we're not passing the current script as the base instance.
- var result = expression.execute([], null)
- print(result) # null
- # This will work since we're passing the current script (i.e. self)
- # as the base instance.
- result = expression.execute([], self)
- print(result) # 20
- Associating a base instance allows doing the following:
- - Reference the instance's constants (``const``) in the expression.
- - Reference the instance's member variables (``var``) in the expression.
- - Call methods defined in the instance and use their return values in the expression.
- .. warning::
- Setting a base instance to a value other than ``null`` allows referencing
- constants, member variables, and calling all methods defined in the script
- attached to the instance. Allowing users to enter expressions may allow
- cheating in your game, or may even introduce security vulnerabilities if you
- allow arbitrary clients to run expressions on other players' devices.
- Example script
- --------------
- The script below demonstrates what the Expression class is capable of::
- const DAYS_IN_YEAR = 365
- var script_member_variable = 1000
- func _ready():
- # Constant mathexpression.
- evaluate("2 + 2")
- # Math expression with variables.
- evaluate("x + y", ["x", "y"], [60, 100])
- # Call built-in method (hardcoded in the Expression class).
- evaluate("deg2rad(90)")
- # Call user method (defined in the script).
- # We can do this because the expression execution is bound to `self`
- # in the `evaluate()` method.
- # Since this user method returns a value, we can use it in math expressions.
- evaluate("call_me() + DAYS_IN_YEAR + script_member_variable")
- evaluate("call_me(42)")
- evaluate("call_me('some string')")
- func evaluate(command, variable_names = [], variable_values = []) -> void:
- var expression = Expression.new()
- var error = expression.parse(command, variable_names)
- if error != OK:
- push_error(expression.get_error_text())
- return
- var result = expression.execute(variable_values, self)
- if not expression.has_execute_failed():
- print(str(result))
- func call_me(argument = null):
- print("\nYou called 'call_me()' in the expression text.")
- if argument:
- print("Argument passed: %s" % argument)
- # The method's return value is also the expression's return value.
- return 0
- The output from the script will be::
- 4
- 160
- 1.570796
- You called 'call_me()' in the expression text.
- 1365
- You called 'call_me()' in the expression text.
- Argument passed: 42
- 0
- You called 'call_me()' in the expression text.
- Argument passed: some string
- 0
- Built-in functions
- ------------------
- Most methods available in the :ref:`class_@GDScript` scope are available in the
- Expression class, even if no base instance is bound to the expression.
- The same parameters and return types are available.
- However, unlike GDScript, parameters are **always required** even if they're
- specified as being optional in the class reference. In contrast, this
- restriction on arguments doesn't apply to user-made functions when you bind a
- base instance to the expression.
|