Command System: Querying
Command arguments marked with a question mark can be queried. For example, the material.name command's name argument can be queried for its value, returning the name of the selected materials. If multiple items are selected, multiple names are returned. Although multiple values can be returned by a query, only a single value can be set for a given argument.
- 1 Using the Command History's Results Tab
- 2 Performing a Query
- 3 Querying and the User Interface
- 4 More Information
Using the Command History's Results Tab
The Results tab of the Command History shows the results of any command executed or queried from that viewport, including failures and any queried values. In the case of the material.name command, one name will show up under the command's row for each material that is selected. If no items were selected, the command is disabled and (none) is shown in the results list.
Performing a Query
To query a command, simply insert a ? in place of the value. Queries always return raw values without units, and any square brackets around the question mark are ignored. What kind of value is returned is determined by the argument's datatype.
material.name ? material.name name:?
Querying and the User Interface
The user interface makes heavy use of command queries through the Forms system. The forms system is managed through the Form Editor and the Forms Viewport. The Form Editor is a hierarchical tree of forms, where each form contains sub-forms and commands representing controls. The Forms Viewport uses these forms to display toolbars and properties sheets. Menus, pies and popovers are also created using the forms system.
Without Querying: Simple Buttons
Every control in a form is a command. Commands without queries are simple buttons. These are created using normal commands, such the New command in the File menu, when no arguments are marked for query with a question mark:
Any command without a question mark query will create a button that executes the command. The command's arguments can be set or omitted as desired. If required arguments are not set, the button will open command dialog to prompt the user for values for those arguments. When used in a menu, the entry shows up as a selectable choice that will execute the command. By convention, the label of a menu item that would open a modal dialog usually ends in ellipsis. For instance, Set Material... in the Materials menu is defined with the following command:
ToggleValue: Tool-Stlye Buttons
Commands that define a ToggleValue argument show up as tool-stlye on/off buttons when put into a form. No arguments are queried, as the ToggleValue argument is found automatically. One example is the Cube tool:
tool.set prim.cube on
Because the Cube tool's button uses the command tool.set, which defines a ToggleValue argument, a tool-style button is created. Similarly, the commands for Vertex, Polygon, Edge, Item and Material selections are also ToggleValue commands. The select.fromType command takes a list of selection types, which it tests to see if the first type in the list is the current one, and toggles that one on and off when the button is clicked.
select.fromType "vertex;polygon;edge;item;ptag" 1 select.fromType "polygon;vertex;edge;item;ptag" 1 select.fromType "edge;vertex;polygon;item;ptag" 1 select.fromType "item;vertex;polygon;edge;ptag" 1 select.fromType "ptag;vertex;polygon;edge;item" 1
When put into menus, those same commands are interpreted as checkmark menu items.
With Querying: Other Control Types
Commands queried with the question mark syntax will create different controls depending on the datatype of the argument being queried.
Checkmark controls are created in a form when querying a command argument with a boolean datatype. It is also possible to use special text hints on an integer control, but this is a legacy feature that isn't seen very much anymore.
This creates the Grid Visibility toggle in the GL portion of the Preferences window:
In a menu, this would create a checkmark item. When the control is toggled the question mark is replaced with the new value and the command is executed. You can see this by looking in the Command History viewport's Undo List or the History tabs as you click on buttons in the interface.
Commands with integer or string arguments that are a list of choices create popups. For static lists of options, integers are designated as popups by assigning text hints to the argument, which makes integer values to the possible choices by associating an internal name string with an index. Other times a command might use custom methods to more dynamically populate a popup for both integer and string datatypes. In menus the command becomes a submenu, with each choice a submenu item, but it is also possible to inline the choices into the parent menu by assigning the Inline style to the control in the Form Editor.
The scene.recent command is used to creates the "Open Recent" submenu in the File menu:
Similarly, the select.symmetryAxis command is queried to create a popup in the main toolbar.
In both cases, when an item is selected from the menu, that item replaces the question marked argument and the command is executed.
Text and Numeric Edit Fields
Basic text and numeric datatypes such as string, integer, [[Common Datatypes#distance|distance], [[Common Datatypes#percent|percent], and so on, create edit fields. The numeric datatypes often also have minisliders attached to allow adjusting values with the mouse, such as this command defining a control for the X position of the Cube tool:
tool.attr prim.cube cenX ?
The above creates a distance control with a minislider when the Cube tool is active. tool.attr has a dynamic datatype for the queried argument. Because of this, it only knows what kind of control to create by looking at its other arguments and the system state. In this case, the prim.cube argument requires that the Cube tool be active and that the tool contain a cenX attribute. If the tool is not active there is no context to decide what kind of control to create, and thus it will be skipped over entirely and not appear in the form. For other commands where the datatype is known but there is no context for the command, the control will simply be disabled.
As with other controls based on command queries, changing the value of a numeric control will execute the command with the new value replacing the question marked argument in the command string.
Undoable commands that support dragging, such as create numeric edit fields with minisliders and color controls, take advantage of a feature known as refiring. This means that while the control is being dragged, and until the mouse button is released, only a single command execution will show up in the Undo List. This is done by executing the command for the first drag, but performing an undo on each subsequent change before executing the command again. This makes the undo stack more useful for scripting reference and macro recording, and allows a single undo to apply all of the tweaks done while a mouse button was done. The Command History viewport's History tab,, meanwhile, is a more literal recording of every command fired, including the actual undo and redo operations and the individually retired commands.
For example, let's look at color controls. These are created in a similar manner to other queried controls, by querying the argument of a command with the color datatype. For example, there is the Color property in the Material Editor:
Liike edit fields, color controls support refiring, and changing any component by dragging on the control, or through the color picker by clicking on the control, causes the command to be executed with the new color triple in place of the question mark.
Color Controls, Axis Controls and More
Other control types, like the color control above, are created in a similar manner to edit fields and popups, by simply querying the value of a command's argument that has the associated datatype. Some complex datatypes like &item can also queried to create controls. Note that the control mechanism is not currently extensible, so it is not possible to design new forms controls.
You can see that all these command queries look essentially the same, with the control being created based purely on the datatype of the argument and any hints the command itself has provided.