1# Parametric Shapes 2You can now create parametric shapes, which contain named parameters bound 3to GUI widgets (like sliders), that you can manipulate in the Viewer window. 4The shape animates in real time as you change parameter values. 5 6## GUI Changes 7The following program declares a shape parameter that is 8bound to a graphical slider widget: 9``` 10 parametric 11 size :: slider(1,5) = 3; 12 in 13 cube size 14``` 15When you run this program, the Viewer window contains a slider that lets 16you vary the `size` parameter from 1 to 5, with an initial value of `3`. 17For more examples, see the `*.curv` files in this directory. 18 19The value picker widgets are contained in a window named `Shape Parameters`. 20You can resize this window, move it, and minimize it by double clicking the 21title bar. Use CTRL+H to hide or show the window. 22 23Each value picker widget has a `(?)` help button that explains its user interface. 24 25## Language Changes 26To add graphical parameters to a shape in a Curv program, 27you prefix a shape expression with a `parametric` clause: 28``` 29 parametric <parameter1>; <parameter2>; ... in <shape-expression> 30``` 31This is an expression that returns a parametric shape value. 32 33Each `<parameter>` has the form: 34``` 35 <identifier> :: <picker> = <initial-value>; 36``` 37A *picker* expression specifies the type and range of values of the parameter, 38and also specifies what kind of value picker widget is used in the GUI. 39 40Since the `<identifier>` appears as a label in the GUI, we now support 41quoted identifiers, which can contain spaces and ASCII punctuation. 42For example, `'hello world'` is a quoted identifier, legal in any situation 43where a normal identifier is legal. 44 45Here are the currently supported picker expressions: 46* `checkbox` -- A boolean parameter (true or false), represented by 47 a checkbox widget. 48* `colour_picker` -- An RGB colour value. The widget allows you to edit RGB 49 or HSV colour components directly, or use a colour wheel to select colours 50 visually. 51* `slider(low,high)` -- The parameter is a number in a continuous range 52 between `low` and `high`. A linear slider widget is used to set the number. 53* `int_slider(low,high)` -- The parameter is an integer between `low` and 54 `high`. A linear slider widget is used to set the integer. 55* `scale_picker` -- The parameter is a *scale factor*: a number \> 0 and \< infinity. 56 The widget lets you increase or decrease the value by dragging with the mouse, 57 and the value changes according to a logarithmic (not linear) scale. 58 This is the same logic used to modify the zoom factor in the Viewer window 59 using a mouse scroll wheel or trackpad scroll gesture. 60 61Parametric shapes (and pickers) are first class values that can be bound to a 62variable, passed as a parameter to a function, or returned as a result. 63Parametric shapes contain metadata that names their parameters, and allows 64new versions of the shape to be constructed using modified parameter values. 65One consequence is that you can create library functions that return 66parametric shapes. This is in contrast to the OpenSCAD "customizer" feature, 67which relies on structured comments in source code to identify parameters. 68These comments can only appear in the top level source file. 69 70## Bugs and Limitations 71There is no way to save the parameter data. 72 73The `color_picker` widget sets its parameter to an sRGB triple. 74However, the internal representation for colour values in Curv is not 75sRGB, but rather linear RGB. So you can't pass a colour parameter directly 76to the `colour` operator, without using a conversion. 77You could work around this by explicitly 78converting a colour parameter `c` to linear RGB using `sRGB(c)`. 79However, I think it is better if colour parameters are represented 80directly as linear RGB. 81 82The shape expression that follows a `parametric` clause must be compiled into 83a GLSL shader program for execution on the GPU. This means that only a restricted 84subset of Curv may be used. Right now, there are too many limitations. The 85implementation is not yet complete. 86 87There is no way for a library function to take a parametric shape as an argument, 88add more GUI parameters, and return an extended parametric shape as the result. 89 90The widgets are somewhat ugly. I am using the ImGui widget library. 91 92## TODO 93Any parameter can be copied and then pasted as a Curv expression. 94 95Here are some ideas for new picker types: 96* `dropdown_menu(menu_items)` -- select one of N labelled alternatives. 97* vector sliders -- the parameter value is a vector with between 2 and 4 elements. 98 Each vector element is represented by a slider. 99* angle -- an angle picker widget lets you graphically select an angle between `0` 100 and `tau` using a circular pick area. 101* bounded 2D vector -- specify a 2D vector by clicking on one of the points 102 in a rectangular pick area. 103* unbounded 2D vector -- specify a 2D vector by using pan and zoom gestures 104 within a rectangular pick area. 105* 3D direction -- a 3D picker widget that lets you specify a 3D normalized vector, 106 visualized as a direction in 3D space. As seen in the AntTweakBar widget library. 107* 3D rotation -- a 3D picker widget that lets you specify a 3D rotation, 108 encoded as a quaternion. As seen in the AntTweakBar widget library. 109 110Make the GUI look more beautiful and have a more intuitive UI. 111Should I consider using a different widget library? 112