# properties.h ## Overview
This file implements a Properties View. The Properties View provides a way of displaying and editing the properties of objects in The Truth. To use a Properties View, you first create it with `create_properties_view()`, then set The Truth object to edit with `set_object()` and finally you call `ui()` to render the UI of the view. Note that the Properties View assumes that The Truth pointer `tm_the_truth_o` is constant. If you switch to a different Truth, you must destroy the properties view and create a new one. The basic operation of the Properties View is to enumerate all the properties of the edited object and then draw corresponding controls for them. For example, a *bool* property would result in a checkbox, a string property would result in a text box, etc. There are numerous ways of customizing the Property View for an object. If you want to take over the drawing of the Property View completely for a certain Truth Type, you can add a `TM_TT_ASPECT__PROPERTIES` aspect to the type and implement its `custom_ui()` method. To implement your custom UI you would typically use the functions in the the `tm_properties_view_api` to draw parts of your UI. Other functions in the `TM_TT_ASPECT__PROPERTIES` aspect lets you customize the Properties View in different ways. If you just want to customize how a single property is drawn you can use the *property aspect* `TM_TT_PROP_ASPECT__PROPERTIES__CUSTOM_UI`. Note that if you can do this, it is usually better than customizing the whole UI, since you don't have to rewrite the customization code if you add new properties, etc. If the edited object is an instance of a prototype, local properties will be shown in white, while inherited properties will be greyed out. You can use a context menu to reset a property to the prototype's value or to propagate the instance value to the prototype. Note that if you are making your own UI and draw it in sone other way than using the `tm_properties_view_api` functions and you want to indicate prototypes and overrides in some way, you have to implement it yourself. In addition to editing the properties of single objects, the Properties view can also edit multiple objects simultaneously (in multi-edit mode). To use multi-editing, set the view to view a number of objects with `set_objects()`. When multi-editing, the property system will automatically create a "proxy" object that represents the set of edited objects. This proxy object is given a prototype and only the property values that are the same for all edited objects are overridden locally. This gives editing a set of objects a lot of the same feel as editing an instanced object from a prototype. Fields without consensus are grayed out and consensus fields are shown in white. Changes made to the proxy object are automatically propagated to the set of edited objects by examining the `last_undo_scope` and the undo actions performed in that scope. Similarly, changes to the object set are tracked by looking at their version numbers and propagated to the proxy object. If all the edited objects are of a uniform truth type, the Properties View will use that type to look for a `TM_TT_ASPECT__PROPERTIES` aspect. Note that depending on what you do in your properties aspect, you may have to take special care do deal with multi-editing scenarios. As long as you just call the `tm_properties_view_api` functions to render property UIs, everything should work, but if you do other stuff you may need special code. As an example, suppose you have a button that computes a value for one property based on another one. Without special care, the value will be computed for the proxy object and then that changed value will be propagated to *all* the objects. What you probably want instead is to perform the computation for *each* object. You can do that by explicitly calling `proxy_to_objects()` to check if you are editing a proxy object and get the corresponding list of objects. Another useful function when editing multiple objects is `get_property_value()`. If called with a proxy object, it will return the *consensus* value for the property -- i.e. if all the objects agree on the value, that value will be returned, otherwise nil. This is useful when you are customizing the UI based on the value of the properties. You don't want to use the values from the proxy objects, but rather the consensus value from all edited objects.
## Index
Tab settings
`TM_TT_TYPE__PROPERTIES_SETTINGS`
`enum TM_TT_PROP__PROPERTIES_SETTINGS`

Properties view customization
`tm_properties_view_o`
`enum tm_properties_metric`
`struct tm_properties_ui_args_t`

`struct tm_properties_aspect_i`
`custom_ui()`
`prototype_asset_picker_type_name()`
`custom_subobject_ui()`
`custom_child_ui()`
`get_type_display_name()`
`get_display_name()`

`TM_TT_ASPECT__PROPERTIES`
`tm_tt_prop_aspect__properties__asset_picker`
`TM_TT_PROP_ASPECT__PROPERTIES__ASSET_PICKER`
`TM_TT_PROP_ASPECT__PROPERTIES__USE_LOCAL_ENTITY_PICKER`
`tm_tt_prop_aspect__properties__custom_ui`
`TM_TT_PROP_ASPECT__PROPERTIES__CUSTOM_UI`
`tm_properties_set_custom_property_ui()`

`struct tm_properties_float_display_converter_i`
`inst`
`model_to_display()`
`display_to_model()`
`get_spinner_settings()`

`TM_PROPERTY_ASPECT__PROPERTIES__FLOAT_DISPLAY_CONVERTER`
`tm_validate_aspect_i`
`TM_TT_ASPECT__VALIDATE`

API
`struct tm_properties_ui_info_t`

`struct tm_properties_uint32_display_converter_i`
`inst`
`model_to_display()`
`display_to_model()`

`struct tm_properties_reference_picker_args_t`
`struct tm_properties_view_config_t`
`struct tm_properties_float_slider_t`

`struct tm_properties_view_api`

Setting up the view
`create_properties_view()`
`destroy_properties_view()`
`set_object()`
`set_object_with_mask()`
`set_mask()`
`set_objects()`
`objects()`
`ui()`
`update()`

Custom UI helper functions
`ui_info()`
`metrics()`
`get_display_name()`
`get_type_display_name()`

Generic property UIs
`ui_object()`
`ui_object_default()`
`ui_property()`
`ui_property_with_name()`
`ui_property_default()`
`ui_property_default_with_name()`
`ui_tree_item()`
`ui_group()`

Property context menu
`show_subobject_menu()`
`begin_subobject_menu_scope()`
`end_subobject_menu_scope()`
`begin_context_menu_scope()`
`end_context_menu_scope()`
`selected_context_menu_item()`
`add_context_menu_items()`
`context_menu()`

Standard property controls
`ui_bool()`
`ui_uint32()`
`ui_uint64()`
`ui_float()`
`ui_double()`
`ui_string()`
`ui_reference()`
`ui_reference_args()`
`ui_subobject()`
`ui_subobject_direct()`
`ui_reference_set()`
`ui_subobject_set()`
`ui_subobject_set_item_header()`
`ui_subobject_set_item()`

Pop-up pickers
`ui_uint32_popup_picker()`
`ui_uint64_popup_picker()`
`ui_reference_popup_picker()`
`ui_string_popup_picker()`
`popup_pick_with_categories()`

Dropdown pickers
`ui_uint32_dropdown()`
`ui_uint64_dropdown()`

Non-standard editors
`ui_float_slider()`

Struct editors
`ui_vec2()`
`ui_vec3()`
`ui_vec4()`
`ui_color_picker()`
`ui_color_temperature()`
`ui_color_button()`
`ui_expanded_color_picker()`
`ui_rotation()`
`ui_visibility_flags()`

Draw helpers
`ui_label()`
`ui_horizontal_line()`
`ui_static_text()`

Custom editors
`ui_prototype()`

Path editors
`ui_open_path()`
`ui_save_path()`

Multi-editing
`ui_multi_object()`
`proxy_to_objects()`
`multi_proxy()`
`get_property_value()`

Helpers
`was_changed()`
`internal__copy_expanded_state()`

`TM_PROPERTIES_VIEW_API_NAME`
## API

Tab settings

### `TM_TT_TYPE__PROPERTIES_SETTINGS`
~~~c #define TM_TT_TYPE__PROPERTIES_SETTINGS "tm_properties_settings" #define TM_TT_TYPE_HASH__PROPERTIES_SETTINGS TM_STATIC_HASH("tm_properties_settings", 0x32e2b7b01c647065ULL) ~~~ Truth object used to remember the settings of the properties view when restoring the tab.
### `enum TM_TT_PROP__PROPERTIES_SETTINGS`
Properties of `TM_TT_TYPE__PROPERTIES_SETTINGS`. ~~~c enum TM_TT_PROP__PROPERTIES_SETTINGS { // Represents the sub-properties of the root object that are visible TM_TT_PROP__PROPERTIES_SETTINGS__MASK, // uint64_t }; ~~~

Properties view customization

These interfaces lets you customize the Properties View for specific object types. ### `tm_properties_view_o`
~~~c typedef struct tm_properties_view_o tm_properties_view_o; ~~~ Represents a Properties View.
### `enum tm_properties_metric`
Indices the `metrics` array in `tm_properties_ui_args_t`. This can be used in custom draw callbacks to make sure margins and sizes in the UI are consistent with what the built-in function uses. When you call one of the built-in functions, the metrics array can be used to change the look. ~~~c enum tm_properties_metric { TM_PROPERTIES_METRIC_LABEL_WIDTH, TM_PROPERTIES_METRIC_MARGIN, TM_PROPERTIES_METRIC_ITEM_HEIGHT, TM_PROPERTIES_METRIC_INDENT, TM_PROPERTIES_METRIC_EDIT_WIDTH, TM_PROPERTIES_METRIC_SUBOBJECT_LABEL_MARGIN, TM_PROPERTIES_METRIC_CHECKBOX_CONTROL_WIDTH, TM_PROPERTIES_METRIC_GROUP_RECT_PADDING, TM_PROPERTIES_METRIC_GROUP_LABEL_LEFT_MARGIN, TM_PROPERTIES_METRIC_MENU_WIDTH, TM_PROPERTIES_METRIC_COLOR_PICKER_RGB_LABEL_SIZE, TM_PROPERTIES_METRIC_COLOR_PICKER_INPUT_SIZE, TM_PROPERTIES_METRIC_COLOR_PICKER_HSV_LABEL_SIZE, TM_PROPERTIES_METRIC_COLOR_PICKER_SLIDER_MARGIN, TM_PROPERTIES_METRIC_COLOR_PICKER_SLIDER_KNOB_SIZE, TM_PROPERTIES_METRIC_NUM, }; ~~~
### `struct tm_properties_ui_args_t`
Struct passed to all property drawing functions to provide them with the objects they need to implement property editing. ~~~c typedef struct tm_properties_ui_args_t { // The properties view where the control lives. struct tm_properties_view_o *pv; // The UI where the control lives. struct tm_ui_o *ui; // Style parameter for the UI. struct tm_ui_style_t *uistyle; // The tab where the control lives. struct tm_tab_i *tab; // The Truth that is being edited in the view. struct tm_the_truth_o *tt; // The Asset Browser root object. This is used by property UIs that need to browse for assets. tm_tt_id_t asset_root; // The Undo Stack that undo scopes should be pushed to when property values are changed. struct tm_undo_stack_i *undo_stack; // Metrics table for properties UI. Indexed by [[enum tm_properties_metric]]. Can be used to both // query and set the metrics. If zero, the defaults are used. Get the default values from // [[tm_properties_view_api->metrics()]]. float *metrics; // When you call [[ui_bool()]] or any of the other property functions, if the value is changed // and a new undo scope is created, this variable will be set to that undo scope. The purpose of // this is to allow you to add additional changes to that same undo scope. For example, you may // have a [[ui_uint32_dropdown()]] that affects the type of a subobject. In that case you want // to make the change of the subobject type a part of the same undo scope that changed the // [[ui_uint32_dropdown()]] value (otherwise you would have to undo twice -- once to change the // subobject type, and once to change the enum value). tm_tt_undo_scope_t last_undo_scope; } tm_properties_ui_args_t; ~~~
### `struct tm_properties_aspect_i`
Aspect that can be used to customize the property view for a specific Truth type. !!! TODO: API-REVIEW This interface is kind of a grab bag of different things. It should only have the `custom_ui()` callback, and the other functions should be broken out into separate aspects. #### `custom_ui()` ~~~c float (*custom_ui)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, tm_tt_id_t object, uint32_t indent); ~~~ Optional. If non-zero, implements a custom callback for rendering the UI instead of the default behavior. Should return the y-position where to continue drawing properties after drawing the item. #### `prototype_asset_picker_type_name()` ~~~c tm_strhash_t (*prototype_asset_picker_type_name)(struct tm_the_truth_o *tt, tm_tt_id_t o); ~~~ Optional. Returns a non-zero value if this type allows for picking a prototype asset when used as a subobject. Note that picking a new prototype will reset the subobject to the prototype. #### `custom_subobject_ui()` ~~~c float (*custom_subobject_ui)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t subobject, uint32_t indent); ~~~ Optional. If non-zero, implements a custom callback for drawing a subobject inline in the parent's property view. Normally, subobjects are drawn with a header that allows them to be collapsed and expanded. !!! TODO: API-REVIEW We should probably implement this as an aspect flag "draw_subobject_inline" instead of having a custom callback for it. #### `custom_child_ui()` ~~~c float (*custom_child_ui)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, tm_tt_id_t parent, tm_tt_id_t child, uint32_t indent); ~~~ Optional. If implemented, allows a parent to override the property UI of one of its children. If implemented for the parent and returning a changed value, this will be used instead of the default property UI for the child. #### `get_type_display_name()` ~~~c const char *(*get_type_display_name)(void); ~~~ Optional. Can be implemented to give a custom name to this type. By default the name is the name of the Truth type capitalized and with the initial `tm_` removed (if present). So `tm_transform_component` would get the name `Transform Component`. #### `get_display_name()` ~~~c void (*get_display_name)(const struct tm_the_truth_o *tt, tm_tt_id_t object, char *buffer, uint32_t size); ~~~ Optional. Can be implemented to give custom names to objects of this type. By default we look for a "name" property and if not found we use the type name. !!! TODO: API-REVIEW This should be its own aspect instead of being a part of `TM_TT_ASPECT__PROPERTIES`.
### `TM_TT_ASPECT__PROPERTIES`
~~~c #define TM_TT_ASPECT__PROPERTIES ~~~ Aspect identifier for `tm_properties_aspect_i`.
### `tm_tt_prop_aspect__properties__asset_picker`
~~~c typedef char *tm_tt_prop_aspect__properties__asset_picker; ~~~ Property aspect that specifies that the property should use the Asset Picker to set the value. (Note: Only `TM_THE_TRUTH_PROPERTY_TYPE_REFERENCE` type properties can use this.) The property should be set to the name of the asset type that the asset picker should pick.
### `TM_TT_PROP_ASPECT__PROPERTIES__ASSET_PICKER`
~~~c #define TM_TT_PROP_ASPECT__PROPERTIES__ASSET_PICKER ~~~ Aspect identifier for `tm_tt_prop_aspect__properties__asset_picker`.
### `TM_TT_PROP_ASPECT__PROPERTIES__USE_LOCAL_ENTITY_PICKER`
~~~c #define TM_TT_PROP_ASPECT__PROPERTIES__USE_LOCAL_ENTITY_PICKER ~~~ If set to a non-zero value, a "local entity picker" will be used to pick the `TM_THE_TRUTH_PROPERTY_TYPE_REFERENCE` property. The local entity picker let's you pick another named entity within the same entity asset.
### `tm_tt_prop_aspect__properties__custom_ui`
~~~c typedef float tm_tt_prop_aspect__properties__custom_ui(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t indent, uint32_t property); ~~~ Used to implement a custom UI for a single property in an object.
### `TM_TT_PROP_ASPECT__PROPERTIES__CUSTOM_UI`
~~~c #define TM_TT_PROP_ASPECT__PROPERTIES__CUSTOM_UI ~~~ Property aspect identifier for `tm_tt_prop_aspect__properties__custom_ui`.
### `tm_properties_set_custom_property_ui()`
~~~c #define tm_properties_set_custom_property_ui(tt, type, property, f) ~~~ Sets the `TM_TT_PROP_ASPECT__PROPERTIES__CUSTOM_UI` aspect of the `type` and `property` to `f` with proper type checking of the `f` parameter. !!! TODO: API-REVIEW It is a bit weird to only provide this helper function for the `TM_TT_PROP_ASPECT__PROPERTIES__CUSTOM_UI` aspect. If we think type safety of aspects is important we should probably have a more general mechanism for it.
### `struct tm_properties_float_display_converter_i`
Converts a value between a "display" value to be shown in the UI and a "model" value to be stored in the data model. This function can do things such as convert from degrees to radians or clamp the value to a range. !!! TODO: API-REVIEW The use of these functions is a bit inconsistent -- i.e. we provide it for float and uint32_t, but not for double. #### `inst` ~~~c void *inst; ~~~ #### `model_to_display()` ~~~c float (*model_to_display)(void *inst, float v); ~~~ #### `display_to_model()` ~~~c float (*display_to_model)(void *inst, float v); ~~~ #### `get_spinner_settings()` ~~~c void (*get_spinner_settings)(void *inst, struct tm_ui_spinner_t *spinner); ~~~ Get settings for spinner.
### `TM_PROPERTY_ASPECT__PROPERTIES__FLOAT_DISPLAY_CONVERTER`
~~~c #define TM_PROPERTY_ASPECT__PROPERTIES__FLOAT_DISPLAY_CONVERTER ~~~ Returns the `tm_properties_float_display_converter_i` converter (if any) to use for the property.
### `tm_validate_aspect_i`
~~~c typedef bool tm_validate_aspect_i(struct tm_the_truth_o *tt, tm_tt_id_t o, uint32_t property, const void *value); ~~~ Aspect used to validate property values. The properties system will call this aspect to validate values and only write them into The Truth if it returns *true*. If the function returns *false* on a transient change, that change will simply be ignored. If the function returns *false* on a commit change, the commit will be aborted and the value will revert to its previous value. If a value is out of range, `tm_validate_aspect_i` may choose to clamp the value to the appropriate range and return *true*, instead of returning *false*. `tm_validate_aspect_i` is called with the `object` and the `property` that is to be validated. `value` is a pointer to a value of a type matching the property type (i.e. `bool` for `TM_THE_TRUTH_PROPERTY_TYPE_BOOL`, `tm_vec3_t` for `TM_TT_TYPE__VEC3` etc). !!! TODO: API-REVIEW Maybe this function should take a `tm_tt_prop_value_t` instead of a `void *`.
### `TM_TT_ASPECT__VALIDATE`
~~~c #define TM_TT_ASPECT__VALIDATE ~~~ Aspect identifier for `tm_validate_aspect_i`.

API

### `struct tm_properties_ui_info_t`
Return value for `ui_info()`. Used to return information to the caller about internal workings of the Property View. ~~~c typedef struct tm_properties_ui_info_t { // ID of last hovered control in the UI. uint64_t last_hovered_focusable_control; // [[tm_rect_t]] of last hovered item that can produce a context menu. tm_rect_t last_hovered_context_menu_rect; } tm_properties_ui_info_t; ~~~
### `struct tm_properties_uint32_display_converter_i`
Value converter for `uint32_t` values. #### `inst` ~~~c void *inst; ~~~ #### `model_to_display()` ~~~c uint32_t (*model_to_display)(void *inst, uint32_t v); ~~~ #### `display_to_model()` ~~~c uint32_t (*display_to_model)(void *inst, uint32_t v); ~~~
### `struct tm_properties_reference_picker_args_t`
Optional arguments for `ui_reference()`. ~~~c typedef struct tm_properties_reference_picker_args_t { // Provides an array of required asset labels for picked assets. Only assets that have all the // `labels` in the array will show up in the asset picker for the reference. const uint64_t *labels; // List of Truth objects that should be excluded from the asset picker. Usually used to prevent // an object from picking itself. const tm_tt_id_t *excludes; // Number of elements in `labels`. uint32_t num_labels; // Number of elements in `excludes`. uint32_t num_excludes; } tm_properties_reference_picker_args_t; ~~~
### `struct tm_properties_view_config_t`
Configuration parameters to set up the Properties View. ~~~c typedef struct tm_properties_view_config_t { // The Truth where objects live. Note that this can't be changed for the Properties View. If you // want to change The Truth of the objects being edited, you have to destroy the view and // create a new one. struct tm_the_truth_o *tt; // Stack where undo scopes should be posted. This is typically the application stack. struct tm_undo_stack_i *undo_stack; } tm_properties_view_config_t; ~~~
### `struct tm_properties_float_slider_t`
Properties for float sliders. ~~~c typedef struct tm_properties_float_slider_t { // Range of slider. float min, max; // Step of slider. If non-zero, slider changes will be rounded to an integral number of steps. // I.e. with `{min = 0, max = 0.5, step = 0.1}`, the slider can take on the values 0, 0.1, 0.2, // 0.3, 0.4 and 0.5. float step; // If *true*, a text edit box will be shown next to the slider, otherwise the control will // just be a slider. bool show_edit_box; TM_PAD(3); // If non-zero, values edited in the text edit box will be clamped to this range. If zero, // values in the text edit box will be clamped to the *min* and *max* values. It is sometimes // useful to have the slider represent the "normal" range of values, but allow the user to // go outside that range by explicitly typing a value in the edit box. float edit_min, edit_max; // Optional. Specifies a converter that will be used for the values. tm_properties_float_display_converter_i *converter; } tm_properties_float_slider_t; ~~~
### `struct tm_properties_view_api`
API for showing the "properties" view of an object in The Truth. The properties view shows an object's properties and allows the user to edit them. A default editing experience is provided for all objects in The Truth, but the properties viewer can also be extended with custom views, such as color pickers, etc. These custom views are mostly implemented through Truth aspects such as `TM_TT_ASPECT__PROPERTIES`.

Setting up the view

#### `create_properties_view()` ~~~c tm_properties_view_o *(*create_properties_view)(struct tm_allocator_i *allocator, const tm_properties_view_config_t *config); ~~~ Creates a new properties view. #### `destroy_properties_view()` ~~~c void (*destroy_properties_view)(tm_properties_view_o *inst); ~~~ Destroys a properties view created with `create_properties_view()`. #### `set_object()` ~~~c bool (*set_object)(tm_properties_view_o *inst, tm_tt_id_t object); ~~~ Sets the object in The Truth that the properties view should display. Returns *true* if the object was actually changed (if it was different from the previously set object). #### `set_object_with_mask()` ~~~c bool (*set_object_with_mask)(tm_properties_view_o *inst, tm_tt_id_t object, uint64_t property_mask); ~~~ Sets the object to display together with a mask of the properties to edit. Only the properties in the mask will be shown. Properties not in the mask will not be shown. #### `set_mask()` ~~~c bool (*set_mask)(tm_properties_view_o *inst, uint64_t property_mask); ~~~ Sets the mask of properties to show for the current object. Calling `set_object()` followed `set_mask()` is the same as calling `set_object_with_mask()`. #### `set_objects()` ~~~c bool (*set_objects)(tm_properties_view_o *inst, const tm_tt_id_t *objects, uint32_t n); ~~~ Sets the property view to edit multiple objects in a "consensus view". Returns *true* if the objects were actually changed (if they were different from the previous objects). #### `objects()` ~~~c const tm_tt_id_t *(*objects)(tm_properties_view_o *inst); ~~~ Returns the properties currently edited by the property tab. The objects are returned as a `carray.inl`, so you can use `tm_carray_size()` for the count. #### `ui()` ~~~c void (*ui)(tm_properties_view_o *inst, tm_tt_id_t asset_root, struct tm_ui_o *ui, const struct tm_ui_style_t *style, tm_rect_t rect, struct tm_tab_i *tab); ~~~ Draws the UI of the properties view. #### `update()` ~~~c void (*update)(tm_properties_view_o *inst, struct tm_ui_o *ui); ~~~ Updates the internal state of `inst`. Should be run once a frame, after any properties have been drawn.

Custom UI helper functions

#### `ui_info()` ~~~c tm_properties_ui_info_t *(*ui_info)(tm_properties_view_o *inst); ~~~ Returns a struct with information about the current UI state of the properties. For example, we can see if the most recently hovered item is focusable. The UI info is useful for implementing some custom property behaviors. The returned value can be modified. !!! TODO: API-REVIEW Better documentation of when and why you would modify the returned value. #### `metrics()` ~~~c float *(*metrics)(tm_properties_view_o *inst); ~~~ Returns the default metrics used for drawing the properties UI. Use `enum tm_properties_metric` to index. These are good to use as sensible starting values when supplying the optional `metrics` field in `tm_properties_ui_args_t`. #### `get_display_name()` ~~~c void (*get_display_name)(const struct tm_the_truth_o *tt, tm_tt_id_t object, char *buffer, uint32_t size); ~~~ Gets the name that the properties will display for the specified `object` and stores it in `buffer` -- a fixed size buffer of size `size`. #### `get_type_display_name()` ~~~c void (*get_type_display_name)(const struct tm_the_truth_o *tt, tm_tt_type_t object_type, char *buffer, uint32_t size); ~~~ Gets the name that the properties will display for the specified `object_type` and stores it in the `buffer` -- a fixed size buffer of size `size`.

Generic property UIs

#### `ui_object()` ~~~c float (*ui_object)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, tm_tt_id_t object, uint32_t indent); ~~~ Draws the properties UI for `object` inside the `item_rect`. The properties UI is laid out vertically. `ui_object()` (and all the other drawing functions) return the y-coordinate where the next control should be drawn. Typically you would set `item_rect.y` to the returned value and then use it to draw the next control. #### `ui_object_default()` ~~~c float (*ui_object_default)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, tm_tt_id_t object, uint32_t indent); ~~~ As `ui_object()`, but ignores any custom UI set with `TM_TT_ASPECT__PROPERTIES`. This can be useful if you want to draw the default UI and then do some special stuff, from within your custom properties UI. Note that in this case, you can't call `ui_object()` directly, since `ui_object()` would call back into your custom properties UI function, causing infinite recursion. #### `ui_property()` ~~~c float (*ui_property)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, tm_tt_id_t object, uint32_t indent, uint32_t property); ~~~ Draws the UI for a single object property. This is useful when you want to implement custom drawing for the whole object, but keep the regular interface for some properties. #### `ui_property_with_name()` ~~~c float (*ui_property_with_name)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t indent, uint32_t property); ~~~ As `ui_property()`, but lets you specify a custom `name` and `tooltip` for the property. #### `ui_property_default()` ~~~c float (*ui_property_default)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, tm_tt_id_t object, uint32_t indent, uint32_t property); ~~~ As `ui_property()`, but ignores any custom UI set with `TM_TT_PROP_ASPECT__PROPERTIES__CUSTOM_UI`. You can call this from `ui_property()` to draw the default UI without getting infinite recursion. #### `ui_property_default_with_name()` ~~~c float (*ui_property_default_with_name)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t indent, uint32_t property); ~~~ As `ui_property_default()`, but lets you specify a custom `name` and `tooltip` for the property. #### `ui_tree_item()` ~~~c bool (*ui_tree_item)(struct tm_properties_ui_args_t *args, uint64_t key, tm_rect_t rect, uint32_t indent, bool expanded_default, const char *tooltip, uint64_t ui_id); ~~~ Draws a header for an expandable/collapsable sub item in the properties view. Note that this function just draws the background and the icon for collapsing/expanding, not the header text. If you want to draw header text, you should use `ui_group()`, or draw it later, on top of the background. `key` should be an ID uniquely identifying this sub item. It is used to keep track of which items have been expanded and collapsed. If `expanded_default` is true, the item is expanded by default the first time it's drawn, otherwise collapsed. `ui_id` is optional, if non-zero, it will be used for the UI ID of the tree item rect. Returns *true* if the item is expanded and *false* if it's collapsed. When the item is expanded, you should draw the UIs of its sub-items. #### `ui_group()` ~~~c float (*ui_group)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t indent, bool expanded_default, bool *is_expanded); ~~~ As `ui_tree_item()` but also draws a label with the text `name`. The key is automatically generated by hashing the `object` and the `name`.

Property context menu

#### `show_subobject_menu()` ~~~c tm_tt_undo_scope_t (*show_subobject_menu)(struct tm_the_truth_o *tt, struct tm_undo_stack_i *undo_stack, struct tm_ui_o *ui, struct tm_ui_style_t *uistyle, tm_tt_id_t object, uint32_t property, tm_tt_id_t sub, tm_vec2_t pos); ~~~ Shows the standard dropdown menu for an object from a subobject set that allows the object to be overridden, removed, etc. If a change was made, returns the undo scope of the change, otherwise, returns `TM_TT_NO_UNDO_SCOPE`. #### `begin_subobject_menu_scope()` ~~~c void (*begin_subobject_menu_scope)(struct tm_properties_ui_args_t *args, tm_rect_t rect, tm_tt_id_t object, uint32_t property, tm_tt_id_t sub, uint64_t ui_id); ~~~ Like `show_subobject_menu()`, but adds a context menu scope and context menu items to it. This is useful when a control deeper inside your UI code also adds context menu items, and you want the subobject menu combined with the menu of that control. `ui_id` is optional, if non-zero, it will be possible to double click that UI item in order to override. #### `end_subobject_menu_scope()` ~~~c void (*end_subobject_menu_scope)(struct tm_properties_ui_args_t *args, tm_tt_id_t object, uint32_t property, tm_tt_id_t sub, uint64_t ui_id); ~~~ Must be called at some point after calling `begin_subobject_menu_scope()`. `ui_id` is optional, if non-zero, it will be possible to double click that UI item in order to override. #### `begin_context_menu_scope()` ~~~c void (*begin_context_menu_scope)(struct tm_properties_view_o *pv, tm_rect_t rect); ~~~ Begins a new property context menu scope. Within a scope, calls to `add_context_menu_items()` will add themself to the scope and and be available when the user right clicks within the rectangle `rect`. Each call to `begin_context_menu_scope()` must match a call to `end_context_menu_scope()`. #### `end_context_menu_scope()` ~~~c void (*end_context_menu_scope)(struct tm_properties_view_o *pv, uint64_t *out_id, char **out_text); ~~~ Ends a scope begun by `begin_context_menu_scope()`. Each call to `begin_context_menu_scope()` must match a call to `end_context_menu_scope()`. `out_id` and `out_text` are optional and will be populated with the id and label of the item that the user chose in the menu, if any. #### `selected_context_menu_item()` ~~~c void (*selected_context_menu_item)(struct tm_properties_view_o *pv, uint64_t *out_id, char **out_text); ~~~ Fetches the item that was selected by the user within a context menu scope, if any. `out_id` and `out_text` are optional, they are set to 0 if no item was chosen. This function is useful when you don't want to call `end_context_menu_scope()`, but still peek at the selected item. #### `add_context_menu_items()` ~~~c void (*add_context_menu_items)(struct tm_properties_view_o *pv, const struct tm_ui_menu_item_t *items, uint32_t num_items); ~~~ Adds a range of property context menu items, which will be available between the calls to `begin_context_menu_scope()` and `end_context_menu_scope()`. #### `context_menu()` ~~~c void (*context_menu)(struct tm_properties_ui_args_t *args); ~~~ Display the property context menu populated with the `add_context_menu_items()`.

Standard property controls

This functions draw the standard property controls. The arguments are: * `args` -- describes the Property View context in which the controls are drawn. * `item_rect` -- rectangle where the item is drawn, note that the item may use a different height than the one specified in the `item_rect` if it needs more space. * `name` -- the name of the property drawn. This will displayed as a label for the control. * `tooltip` -- tooltip to show if the label is hovered. * `object` -- the object to display. * `property` -- the property to display. If you pass `NULL` for the name parameter, no label will be drawn and the control will fill the entire `item_rect`. This is useful when you want to draw compact controls or customize the drawing of the label. The functions return an y-position where the next control should be drawn (below the control drawn by the function). Usually you would assign the return value to `item_rect.y` and then use that `item_rect` to draw the next control. #### `ui_bool()` ~~~c float (*ui_bool)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property); ~~~ Draws a checkbox control to edit a `TM_THE_TRUTH_PROPERTY_TYPE_BOOL`. #### `ui_uint32()` ~~~c float (*ui_uint32)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, tm_properties_uint32_display_converter_i *converter); ~~~ Draws a textbox control to edit a `TM_THE_TRUTH_PROPERTY_TYPE_UINT32_T`. If the `converter` parameter is supplied, it will be used to convert between a model and a display value. #### `ui_uint64()` ~~~c float (*ui_uint64)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property); ~~~ Draws a textbox control to edit a `TM_THE_TRUTH_PROPERTY_TYPE_UINT64_T`. !!! TODO: API-REVIEW Should take a converter parameter. #### `ui_float()` ~~~c float (*ui_float)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, const tm_properties_float_display_converter_i *converter); ~~~ Draws a textbox control to edit a `TM_THE_TRUTH_PROPERTY_TYPE_FLOAT`. If the `converter` parameter is supplied, it will be used to convert between a model and a display value. #### `ui_double()` ~~~c float (*ui_double)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property); ~~~ Draws a textbox control to edit a `TM_THE_TRUTH_PROPERTY_TYPE_DOUBLE`. !!! TODO: API-REVIEW Should take a converter parameter. #### `ui_string()` ~~~c float (*ui_string)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property); ~~~ Draws a textbox control to edit a `TM_THE_TRUTH_PROPERTY_TYPE_STRING`. #### `ui_reference()` ~~~c float (*ui_reference)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property); ~~~ Draws a control to edit a `TM_THE_TRUTH_PROPERTY_TYPE_REFERENCE`. This is the same as calling `ui_reference_args()` with `NULL` for the `picker_args` parameter. #### `ui_reference_args()` ~~~c float (*ui_reference_args)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, const struct tm_properties_reference_picker_args_t *picker_args); ~~~ Draws a popup picker editor to pick a reference's value. The `picker_args` control the display of the picker. #### `ui_subobject()` ~~~c float (*ui_subobject)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, uint32_t indent, bool expanded_by_default); ~~~ Draws the UI for a `TM_THE_TRUTH_PROPERTY_TYPE_SUBOBJECT` property. Typically the subobject UI is just a collapsible panel where the regular property UI for the subobject is drawn, but the subobject UI code also deals with things such as inherited and overridden subbobjects. If `expanded_by_default` is *true*, the subobject starts expanded, otherwise collapsed. #### `ui_subobject_direct()` ~~~c float (*ui_subobject_direct)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t parent, tm_tt_id_t subobject, uint32_t indent, bool expanded_by_default); ~~~ As `ui_subobject()` but instead of passing `object` and `property` you pass `parent` and `subobject`. This can be useful when you want to use the subobject UI for things that aren't subobjects. #### `ui_reference_set()` ~~~c float (*ui_reference_set)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, uint32_t indent); ~~~ Draws the UI for a `TM_THE_TRUTH_PROPERTY_TYPE_REFERENCE_SET` property. The reference set is drawn as a list of `ui_reference()` UIs. #### `ui_subobject_set()` ~~~c float (*ui_subobject_set)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, uint32_t indent); ~~~ Draws the UI for a `TM_THE_TRUTH_PROPERTY_TYPE_SUBOBJECT_SET`. The subobject set is drawn as a list of `ui_subobject()` UIs. #### `ui_subobject_set_item_header()` ~~~c bool (*ui_subobject_set_item_header)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, tm_tt_id_t object, uint32_t property, tm_tt_id_t sub, uint32_t indent, const char *custom_name, bool expanded_by_default); ~~~ Draws the header that would normally be displayed above each subobject in a subobject set, without drawing the subobject itself. This can be useful when you want to completely customize the subobject drawing. If `custom_name` is not NULL, it will be just as the text in the subobject header, otherwise, the default subobject name will be used. Returns *true* if the subobject is expanded and *false* if it is collapsed. #### `ui_subobject_set_item()` ~~~c float (*ui_subobject_set_item)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, tm_tt_id_t object, uint32_t property, tm_tt_id_t sub, uint32_t indent, bool expanded_by_default); ~~~ Draws a single item `sub` from a subobject set (including the header). This can be used instead of drawing the whole set with `ui_subobject_set()` when you want to customize the drawing.

Pop-up pickers

These pickers lets the user pick a value from a list of strings using a pop-up search box that lists all the strings that match what the user has typed. #### `ui_uint32_popup_picker()` ~~~c float (*ui_uint32_popup_picker)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, const char **items, uint32_t num_items); ~~~ Sets `property` to the picked index in the `items` string table. !!! TODO: API-REVIEW Should this picker have an `items_values` indirection table. #### `ui_uint64_popup_picker()` ~~~c float (*ui_uint64_popup_picker)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, const char **items, const uint64_t *items_values, uint32_t num_items); ~~~ Sets `property` to `items_values[i]` where `i` is the picked index in the `items` string table. #### `ui_reference_popup_picker()` ~~~c float (*ui_reference_popup_picker)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, const char **items, const tm_tt_id_t *items_references, uint32_t num_items); ~~~ Sets `property` to `items_references[i]` where `i` is the picked index in the `items` string table. #### `ui_string_popup_picker()` ~~~c float (*ui_string_popup_picker)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, const char **items, uint32_t num_items); ~~~ Sets `property` to the picked string in the `items` string table. #### `popup_pick_with_categories()` ~~~c bool (*popup_pick_with_categories)(struct tm_properties_ui_args_t *args, uint64_t ui_id, tm_vec2_t pos, const char *const *strings, const char *const *categories, uint32_t num_strings, uint32_t *pick_index); ~~~ Helper that displays a popup picker with categories at position `pos`. `strings` specifies the name of each item and `categories` its category. You can use slashes in the category names to create a hierarchy of categories (e.g. `Math/Vec2`). Returns *true* if an item was picked and returns the picked item in `pick_index`.

Dropdown pickers

Lets the user pick a value from a dropdown list of strings. #### `ui_uint32_dropdown()` ~~~c float (*ui_uint32_dropdown)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, const char **items, const char **item_tooltips, const uint32_t *items_uint32, uint32_t num_items); ~~~ Sets `property` to `items_uint32[i]` where `i` is the index of the picked string. If `items_uint32` is NULL, then the property will be set to `i` instead. #### `ui_uint64_dropdown()` ~~~c float (*ui_uint64_dropdown)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, const char **items, const char **item_tooltips, const uint64_t *items_uint64, uint32_t num_items); ~~~ Sets `property` to `items_uint64[i]` where `i` is the index of the picked string. If `items_uint64` is NULL, then the property will be set to `i` instead.

Non-standard editors

Property editors that use a special display of the value. #### `ui_float_slider()` ~~~c float (*ui_float_slider)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, const tm_properties_float_slider_t *slider); ~~~ Lets the user edit the value of a floating point number using a slider.

Struct editors

Custom property editors for common object types. #### `ui_vec2()` ~~~c float (*ui_vec2)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t vec); ~~~ Editor for `TM_TT_TYPE__VEC2`. #### `ui_vec3()` ~~~c float (*ui_vec3)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t vec); ~~~ Editor for `TM_TT_TYPE__VEC3`. #### `ui_vec4()` ~~~c float (*ui_vec4)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t vec); ~~~ Editor for `TM_TT_TYPE__VEC4`. #### `ui_color_picker()` ~~~c float (*ui_color_picker)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t color); ~~~ Color picker editor for `TM_TT_TYPE__COLOR_RGB`. #### `ui_color_temperature()` ~~~c float (*ui_color_temperature)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *tooltip, tm_tt_id_t color); ~~~ Temperature editor for `TM_TT_TYPE__COLOR_RGB`. #### `ui_color_button()` ~~~c bool (*ui_color_button)(struct tm_properties_ui_args_t *args, const struct tm_ui_button_t *color_button, tm_tt_id_t color); ~~~ Draws a the "color button" part of the standard `ui_color_picker()`. Useful when you want a custom color editor. #### `ui_expanded_color_picker()` ~~~c float (*ui_expanded_color_picker)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, tm_tt_id_t color); ~~~ Draws the expanded color picker part of the standard `ui_color_picker()`. Useful when you want a custom color picker. #### `ui_rotation()` ~~~c float (*ui_rotation)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t rotation); ~~~ Editor for `TM_TT_TYPE__ROTATION`. #### `ui_visibility_flags()` ~~~c float (*ui_visibility_flags)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, uint32_t indent); ~~~ Editor for a property that is a subobject set of `TM_TT_TYPE__VISIBILITY_FLAG`.

Draw helpers

#### `ui_label()` ~~~c float (*ui_label)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip); ~~~ Draws the standard label that would normally be drawn for a property. This is useful when you want to draw the property yourself, but still want it to have a standard label. #### `ui_horizontal_line()` ~~~c float (*ui_horizontal_line)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect); ~~~ Draws a horizontal line in the property editor, useful for separating sections. #### `ui_static_text()` ~~~c float (*ui_static_text)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, const char *text); ~~~ Draws a piece of static text with a `name` label in the properties UI.

Custom editors

#### `ui_prototype()` ~~~c float (*ui_prototype)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t parent, uint32_t property, tm_tt_id_t subobject, tm_strhash_t pick_type_hash); ~~~ Draws a UI that lets you change the prototype of an inherited object.

Path editors

#### `ui_open_path()` ~~~c float (*ui_open_path)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, const char *extensions, const char *description, bool *picked); ~~~ Shows a button that picks a path to open using the system file dialog box. If `picked` is non-NULL, it will be set to *true* if a path was picked. #### `ui_save_path()` ~~~c float (*ui_save_path)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, const char *name, const char *tooltip, tm_tt_id_t object, uint32_t property, const char *extensions, const char *description, bool *picked); ~~~ Shows a button that picks a path to save using the system file dialog box. If `picked` is non-NULL, it will be set to *true* if a path was picked.

Multi-editing

#### `ui_multi_object()` ~~~c float (*ui_multi_object)(struct tm_properties_ui_args_t *args, tm_rect_t item_rect, tm_tt_id_t parent_proxy, uint32_t property, const tm_tt_id_t *objects, uint32_t n, uint32_t indent); ~~~ Renders a multi-select editor for the `objects`. This will create an appropriate proxy object for representing the multi-selection and then pass that proxy object to the UI system. If the `objects` come from a parent proxy object, you should pass the `parent_proxy` object and the `property` where the objects are located. #### `proxy_to_objects()` ~~~c const tm_tt_id_t *(*proxy_to_objects)(struct tm_properties_view_o *pv, tm_tt_id_t proxy); ~~~ If `proxy` is a proxy, returns (as a carray), the list of objects it is a proxy for. If `proxy` is not a proxy, returns NULL. #### `multi_proxy()` ~~~c tm_tt_id_t (*multi_proxy)(struct tm_properties_view_o *pv, tm_tt_id_t parent_proxy, uint32_t property, const tm_tt_id_t *objects, uint32_t n); ~~~ Returns a proxy object that can be used for editing the `objects`. Note that if the `objects` are not of the same type, the function will return 0. #### `get_property_value()` ~~~c const struct tm_tt_prop_value_t *(*get_property_value)(struct tm_properties_view_o *pv, tm_tt_id_t object, uint32_t property, struct tm_temp_allocator_i *ta); ~~~ Gets the value of the specified `property` in the `object`. If the `object` is a proxy for a multi-edit operation, `get_property_value()` returns the consensus value of the edited objects. Similar to `tm_the_truth_api->get_property_value()`, `ta` can be NULL if you are querying the value of a non-set property. Note that there are no consensus values for set properties. The returned value is allocated using the frame allocator.

Helpers

#### `was_changed()` ~~~c bool (*was_changed)(struct tm_properties_ui_args_t *args, tm_tt_id_t object, uint32_t property); ~~~ Returns *true* if the specified `property` of the `object` was changed in this frame. (This is done by inspecting the `last_undo_scope`.) #### `internal__copy_expanded_state()` ~~~c void (*internal__copy_expanded_state)(tm_properties_view_o *pv, tm_tt_id_t from_key, tm_tt_id_t to_key); ~~~ The Property View internally keeps track of the state of which subobjects have been expanded in the UI and which haven't. This function lets you copy that state from one Truth object to another. This can be useful for example when you duplicate Truth objects so that after duplication, the duplicated item has the same subobjects expanded as the original one.
### `TM_PROPERTIES_VIEW_API_NAME`
~~~c #define TM_PROPERTIES_VIEW_API_NAME "tm_properties_view_api" ~~~