YAVE
is node based visual programming environment with functional reactive programming (FRP).
Disclaimer: This project is still in very early stage!
To play around with YAVE
, you can also build from source with standard CMake on Win/Linux.
There are also CI compiled binary artifacts, but these might not work on some environments.
If you have any problem, report issue or ask on gitter.
Procedural content creation with node based visual programming languages are becoming popular in audio and graphics domain because of its flexibility and usability for artists.
In node based languages, you can define how data will be transformed into final output by using data flow graph, which is quite easy to understand even for non-programmers.
However, composing values which change over time (like animations) in node based languages is not trivial. This is because you need to calculate how current time maps to value rather than what kind of operation you want to apply to time related to values. This is different from popular editing paradigm based on declarative time manipulation, which allows you to compose values in the time domain easily.
This has been a known problem in functional programming community, and they found elegant solution by using higher-order functions which commonly known as Functional Reactive Programming (FRP)
.
FRP was introduced for declarative programming paradigm for animations, then its target was shifted to real time applications like GUI.
This project is aiming for incorporating core concept of FRP into end user programming environment.
-
Functional programming
YAVE
supports various functional programming features, including higher-order functions and currying.- Each 'sub-graph' can be used as function value when there's no input.
- Recursion is currently not supported to avoid infinite loops. It is recommended to implement your recursive algorithm in C++ (which is much faster) or use higher-order combinators.
-
Reactivity and declarative time manipulation
YAVE
is based on functional reactive programming (FRP). All node functions are internally represented as function over Behaviours (time-varying values).- FRP enables you to transform any value over time from caller side. For example, you can make single animation and combine them with different time scales/delays without modifying original animation.
- For example,
Time.ReTime
is low-level primitive which transform time of value. - Another example is
Animation
nodes, which provide abstraction for values with time interval. You can apply various temporal transformations like scale, extend, concat, merge, etc.
-
Type system
YAVE
is statically typed language.- Type system of
YAVE
is based on classic Hindley-Milner type inference, with some extension to support ad-hoc overloading. - Type errors are currently displayed very poorly. I'm planning to improve that.
-
Fully interoperable with C++
- Functional programming languages tend to lack support of GUI and high performance graphics, which are must for practical visual scripting environment.
YAVE
avoids this limitation by implementing functional runtime system as EDSL (embedded domain specific language) on C++. - You can add new data types or implement your own node functions from C++. Object system of
YAVE
is designed to support plugin style extensions in the future.
- Functional programming languages tend to lack support of GUI and high performance graphics, which are must for practical visual scripting environment.
Note: Nodes in YAVE
takes input from right side and returns to left.
- Function node
Function nodes represent 'backend' functions. It can be used for either function call (when all arguments are connected) or 'lambda mode' (when there's no input). Lambda mode is used to pass function as value instead of calling it.
Example: Num.Float
, Num.Int
, etc.
Note: YAVE
currently does not have flat lambda introducer like other functional visual programming languages. You always need to create group first, then use it as lambda mode to pass user-defined functions to higher-order functions (this means you always need to use let f x =...
rather than \x ->...
, in analogy to textual languages). Any partially connected nodes are rejected by parser, to simplify syntax for now.
Note: Some function nodes has default values for some sockets which can be changed from GUI. These are treated as connected to invisible node.
- Group node
Group nodes have multiple roles in YAVE
.
Groups can be used as user-defined functions (same as function nodes), and it also creates its own namespace. Namespaces created by groups can be used as path to find and reference functions from anywhere.
- Macro node
Macro nodes are used to procedurally generate nodes from arbitrary number of inputs. For example, List.List
is macro node which generates tree by List.Cons
and List.Nil
. Macro nodes will be expanded in parser stage.
YAVE
is implemented in C++20 (moving from C++17).
This project heavily exploits metaprogramming capability of modern C++. For example, runtime representation of node functions (including runtime type information) are generated through templates. It event has compile time type checker to verify usage of runtime typed objects inside node functions.
YAVE
's node compiler translates node graph into small functional runtime implemented in C++.
There's no code generation or caching optimizations yet.
Vulkan API is used for graphics backend and user interface.
This project is still in very early stage. There are still lots of things to be implemented.
To-Do list:
-
Proper engineering as GUI application
- There are tons of terrible codes/designs in the codebase, which I eager to rewrite.
- Current GUI frontend is prototype with ImGui which has some limitations.
- Qt or custom UI framework with Vulkan might be better for future development.
-
Runtime improvements
- Introducing evaluation context
- Optimization paths
- Parallel scheduling support
- Multi output support
- Dynamic caching
-
Type system improvements
- Improve error message
- Display principal types on GUI
- Replace current hacky type inference implementation..
-
Nodes
- Always add more useful nodes!
- Improve vector graphics support
- GLSL, Python script nodes
To build YAVE
, you need compilers which support some features of C++20.
Currently following compilers are used for development:
- VS2019 Preview (Win)
- Clang 10 (Linux)
- GCC 10 (Linux)
You also need CMake and VulkanSDK.
First build may take longer time to build dependencies.
LGPLv3
- Atsushi Nagaoka (@mocabe)
Note: These screenshots and gifs can be outdated.