Cache File: use panels to organize UI

This adds interface panels to organize the Cache File UI parameters for
modifiers and constraints into related components: velocity, time, and
render procedural.

Properties relating to the three aforementioned components are separated
from `uiTemplateCacheFile` into their own functions (e.g.
`uiTemplateCacheFileVelocity` for the velocity one), which are in turn
called from the specific panel creation routines of the modifiers and
constraints (for constraints, the functions are exposed to the RNA).

`uiTemplateCacheFile` now only shows the properties for the file path,
and in the case of constraints, the scale property.

The properties that are only defined per modifier (like the velocity
scale), are shown in the proper modifier layout panel if applicable.

Reviewed By: sybren

Differential Revision: https://developer.blender.org/D13652
This commit is contained in:
Kévin Dietrich 2021-12-23 18:05:00 +01:00
parent 7a71a95f32
commit 43f5e761a6
Notes: blender-bot 2023-02-14 09:44:56 +01:00
Referenced by issue #94387, Mesh sequence cache - crash to desktop with clicking at panel tabs
5 changed files with 321 additions and 71 deletions

View File

@ -1146,6 +1146,30 @@ class ConstraintButtonsSubPanel:
col.prop(con, "frame_start", text="Frame Start")
col.prop(con, "frame_end", text="End")
def draw_transform_cache_velocity(self, context):
self.draw_transform_cache_subpanel(
context, self.layout.template_cache_file_velocity
)
def draw_transform_cache_procedural(self, context):
self.draw_transform_cache_subpanel(
context, self.layout.template_cache_file_procedural
)
def draw_transform_cache_time(self, context):
self.draw_transform_cache_subpanel(
context, self.layout.template_cache_file_time_settings
)
def draw_transform_cache_subpanel(self, context, template_func):
con = self.get_constraint(context)
if con.cache_file is None:
return
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = True
template_func(con, "cache_file")
# Child Of Constraint
@ -1534,6 +1558,54 @@ class BONE_PT_bTransformCacheConstraint(BoneConstraintPanel, ConstraintButtonsPa
self.draw_transform_cache(context)
class OBJECT_PT_bTransformCacheConstraint_velocity(ObjectConstraintPanel, ConstraintButtonsSubPanel, Panel):
bl_parent_id = "OBJECT_PT_bTransformCacheConstraint"
bl_label = "Velocity"
def draw(self, context):
self.draw_transform_cache_velocity(context)
class BONE_PT_bTransformCacheConstraint_velocity(BoneConstraintPanel, ConstraintButtonsSubPanel, Panel):
bl_parent_id = "BONE_PT_bTransformCacheConstraint"
bl_label = "Velocity"
def draw(self, context):
self.draw_transform_cache_velocity(context)
class OBJECT_PT_bTransformCacheConstraint_procedural(ObjectConstraintPanel, ConstraintButtonsSubPanel, Panel):
bl_parent_id = "OBJECT_PT_bTransformCacheConstraint"
bl_label = "Render Procedural"
def draw(self, context):
self.draw_transform_cache_procedural(context)
class BONE_PT_bTransformCacheConstraint_procedural(BoneConstraintPanel, ConstraintButtonsSubPanel, Panel):
bl_parent_id = "BONE_PT_bTransformCacheConstraint"
bl_label = "Render Procedural"
def draw(self, context):
self.draw_transform_cache_procedural(context)
class OBJECT_PT_bTransformCacheConstraint_time(ObjectConstraintPanel, ConstraintButtonsSubPanel, Panel):
bl_parent_id = "OBJECT_PT_bTransformCacheConstraint"
bl_label = "Time"
def draw(self, context):
self.draw_transform_cache_time(context)
class BONE_PT_bTransformCacheConstraint_time(BoneConstraintPanel, ConstraintButtonsSubPanel, Panel):
bl_parent_id = "BONE_PT_bTransformCacheConstraint"
bl_label = "Time"
def draw(self, context):
self.draw_transform_cache_time(context)
# Python Constraint
class OBJECT_PT_bPythonConstraint(ObjectConstraintPanel, ConstraintButtonsPanel, Panel):
@ -1620,6 +1692,9 @@ classes = (
OBJECT_PT_bCameraSolverConstraint,
OBJECT_PT_bObjectSolverConstraint,
OBJECT_PT_bTransformCacheConstraint,
OBJECT_PT_bTransformCacheConstraint_time,
OBJECT_PT_bTransformCacheConstraint_procedural,
OBJECT_PT_bTransformCacheConstraint_velocity,
OBJECT_PT_bPythonConstraint,
OBJECT_PT_bArmatureConstraint,
OBJECT_PT_bArmatureConstraint_bones,
@ -1657,6 +1732,9 @@ classes = (
BONE_PT_bCameraSolverConstraint,
BONE_PT_bObjectSolverConstraint,
BONE_PT_bTransformCacheConstraint,
BONE_PT_bTransformCacheConstraint_time,
BONE_PT_bTransformCacheConstraint_procedural,
BONE_PT_bTransformCacheConstraint_velocity,
BONE_PT_bPythonConstraint,
BONE_PT_bArmatureConstraint,
BONE_PT_bArmatureConstraint_bones,

View File

@ -2544,11 +2544,42 @@ void uiTemplateComponentMenu(uiLayout *layout,
const char *propname,
const char *name);
void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float color[4]);
/**
* Draw the main CacheFile properties and operators (file path, scale, etc.), that is those which
* do not have their own dedicated template functions.
*/
void uiTemplateCacheFile(uiLayout *layout,
const struct bContext *C,
struct PointerRNA *ptr,
const char *propname);
/**
* Lookup the CacheFile PointerRNA of the given pointer and return it in the output parameter.
* Returns true if `ptr` has a RNACacheFile, false otherwise. If false, the output parameter is not
* initialized.
*/
bool uiTemplateCacheFilePointer(struct PointerRNA *ptr,
const char *propname,
struct PointerRNA *r_file_ptr);
/**
* Draw the velocity related properties of the CacheFile.
*/
void uiTemplateCacheFileVelocity(uiLayout *layout, struct PointerRNA *fileptr);
/**
* Draw the render procedural related properties of the CacheFile.
*/
void uiTemplateCacheFileProcedural(uiLayout *layout,
const struct bContext *C,
struct PointerRNA *fileptr);
/**
* Draw the time related properties of the CacheFile.
*/
void uiTemplateCacheFileTimeSettings(uiLayout *layout, struct PointerRNA *fileptr);
/* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
enum uiTemplateListFlags {

View File

@ -6395,64 +6395,21 @@ void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float color[4])
/** \name Cache File Template
* \{ */
void uiTemplateCacheFile(uiLayout *layout,
const bContext *C,
PointerRNA *ptr,
const char *propname)
void uiTemplateCacheFileVelocity(uiLayout *layout, PointerRNA *fileptr)
{
if (!ptr->data) {
return;
}
/* Ensure that the context has a CacheFile as this may not be set inside of modifiers panels. */
uiLayoutSetContextPointer(layout, "edit_cachefile", fileptr);
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
uiItemR(layout, fileptr, "velocity_name", 0, NULL, ICON_NONE);
uiItemR(layout, fileptr, "velocity_unit", 0, NULL, ICON_NONE);
}
if (!prop) {
printf(
"%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
return;
}
void uiTemplateCacheFileProcedural(uiLayout *layout, const bContext *C, PointerRNA *fileptr)
{
/* Ensure that the context has a CacheFile as this may not be set inside of modifiers panels. */
uiLayoutSetContextPointer(layout, "edit_cachefile", fileptr);
if (RNA_property_type(prop) != PROP_POINTER) {
printf("%s: expected pointer property for %s.%s\n",
__func__,
RNA_struct_identifier(ptr->type),
propname);
return;
}
PointerRNA fileptr = RNA_property_pointer_get(ptr, prop);
CacheFile *file = fileptr.data;
uiLayoutSetContextPointer(layout, "edit_cachefile", &fileptr);
uiTemplateID(layout,
C,
ptr,
propname,
NULL,
"CACHEFILE_OT_open",
NULL,
UI_TEMPLATE_ID_FILTER_ALL,
false,
NULL);
if (!file) {
return;
}
SpaceProperties *sbuts = CTX_wm_space_properties(C);
uiLayout *row, *sub, *subsub;
uiLayoutSetPropSep(layout, true);
row = uiLayoutRow(layout, true);
uiItemR(row, &fileptr, "filepath", 0, NULL, ICON_NONE);
sub = uiLayoutRow(row, true);
uiItemO(sub, "", ICON_FILE_REFRESH, "cachefile.reload");
row = uiLayoutRow(layout, false);
uiItemR(row, &fileptr, "is_sequence", 0, NULL, ICON_NONE);
uiLayout *row, *sub;
/* Only enable render procedural option if the active engine supports it. */
const struct RenderEngineType *engine_type = CTX_data_engine_type(C);
@ -6479,40 +6436,115 @@ void uiTemplateCacheFile(uiLayout *layout,
row = uiLayoutRow(layout, false);
uiLayoutSetActive(row, engine_supports_procedural);
uiItemR(row, &fileptr, "use_render_procedural", 0, NULL, ICON_NONE);
uiItemR(row, fileptr, "use_render_procedural", 0, NULL, ICON_NONE);
const bool use_render_procedural = RNA_boolean_get(&fileptr, "use_render_procedural");
const bool use_prefetch = RNA_boolean_get(&fileptr, "use_prefetch");
const bool use_render_procedural = RNA_boolean_get(fileptr, "use_render_procedural");
const bool use_prefetch = RNA_boolean_get(fileptr, "use_prefetch");
row = uiLayoutRow(layout, false);
uiLayoutSetEnabled(row, use_render_procedural);
uiItemR(row, &fileptr, "use_prefetch", 0, NULL, ICON_NONE);
uiItemR(row, fileptr, "use_prefetch", 0, NULL, ICON_NONE);
sub = uiLayoutRow(layout, false);
uiLayoutSetEnabled(sub, use_prefetch && use_render_procedural);
uiItemR(sub, &fileptr, "prefetch_cache_size", 0, NULL, ICON_NONE);
uiItemR(sub, fileptr, "prefetch_cache_size", 0, NULL, ICON_NONE);
}
void uiTemplateCacheFileTimeSettings(uiLayout *layout, PointerRNA *fileptr)
{
/* Ensure that the context has a CacheFile as this may not be set inside of modifiers panels. */
uiLayoutSetContextPointer(layout, "edit_cachefile", fileptr);
uiLayout *row, *sub, *subsub;
row = uiLayoutRow(layout, false);
uiItemR(row, fileptr, "is_sequence", 0, NULL, ICON_NONE);
row = uiLayoutRowWithHeading(layout, true, IFACE_("Override Frame"));
sub = uiLayoutRow(row, true);
uiLayoutSetPropDecorate(sub, false);
uiItemR(sub, &fileptr, "override_frame", 0, "", ICON_NONE);
uiItemR(sub, fileptr, "override_frame", 0, "", ICON_NONE);
subsub = uiLayoutRow(sub, true);
uiLayoutSetActive(subsub, RNA_boolean_get(&fileptr, "override_frame"));
uiItemR(subsub, &fileptr, "frame", 0, "", ICON_NONE);
uiItemDecoratorR(row, &fileptr, "frame", 0);
uiLayoutSetActive(subsub, RNA_boolean_get(fileptr, "override_frame"));
uiItemR(subsub, fileptr, "frame", 0, "", ICON_NONE);
uiItemDecoratorR(row, fileptr, "frame", 0);
row = uiLayoutRow(layout, false);
uiItemR(row, &fileptr, "frame_offset", 0, NULL, ICON_NONE);
uiLayoutSetActive(row, !RNA_boolean_get(&fileptr, "is_sequence"));
uiItemR(row, fileptr, "frame_offset", 0, NULL, ICON_NONE);
uiLayoutSetActive(row, !RNA_boolean_get(fileptr, "is_sequence"));
}
bool uiTemplateCacheFilePointer(PointerRNA *ptr, const char *propname, PointerRNA *r_file_ptr)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
if (!prop) {
printf(
"%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
return false;
}
if (RNA_property_type(prop) != PROP_POINTER) {
printf("%s: expected pointer property for %s.%s\n",
__func__,
RNA_struct_identifier(ptr->type),
propname);
return false;
}
*r_file_ptr = RNA_property_pointer_get(ptr, prop);
return true;
}
void uiTemplateCacheFile(uiLayout *layout,
const bContext *C,
PointerRNA *ptr,
const char *propname)
{
if (!ptr->data) {
return;
}
PointerRNA fileptr;
if (!uiTemplateCacheFilePointer(ptr, propname, &fileptr)) {
return;
}
CacheFile *file = fileptr.data;
uiLayoutSetContextPointer(layout, "edit_cachefile", &fileptr);
uiTemplateID(layout,
C,
ptr,
propname,
NULL,
"CACHEFILE_OT_open",
NULL,
UI_TEMPLATE_ID_FILTER_ALL,
false,
NULL);
if (!file) {
return;
}
SpaceProperties *sbuts = CTX_wm_space_properties(C);
uiLayout *row, *sub;
uiLayoutSetPropSep(layout, true);
row = uiLayoutRow(layout, true);
uiItemR(row, &fileptr, "filepath", 0, NULL, ICON_NONE);
sub = uiLayoutRow(row, true);
uiItemO(sub, "", ICON_FILE_REFRESH, "cachefile.reload");
if (sbuts->mainb == BCONTEXT_CONSTRAINT) {
row = uiLayoutRow(layout, false);
uiItemR(row, &fileptr, "scale", 0, IFACE_("Manual Scale"), ICON_NONE);
}
uiItemR(layout, &fileptr, "velocity_name", 0, NULL, ICON_NONE);
uiItemR(layout, &fileptr, "velocity_unit", 0, NULL, ICON_NONE);
/* TODO: unused for now, so no need to expose. */
#if 0
row = uiLayoutRow(layout, false);

View File

@ -582,6 +582,43 @@ static void rna_uiTemplateCacheFile(uiLayout *layout,
uiTemplateCacheFile(layout, C, ptr, propname);
}
static void rna_uiTemplateCacheFileVelocity(uiLayout *layout,
PointerRNA *ptr,
const char *propname)
{
PointerRNA fileptr;
if (!uiTemplateCacheFilePointer(ptr, propname, &fileptr)) {
return;
}
uiTemplateCacheFileVelocity(layout, &fileptr);
}
static void rna_uiTemplateCacheFileProcedural(uiLayout *layout,
bContext *C,
PointerRNA *ptr,
const char *propname)
{
PointerRNA fileptr;
if (!uiTemplateCacheFilePointer(ptr, propname, &fileptr)) {
return;
}
uiTemplateCacheFileProcedural(layout, C, &fileptr);
}
static void rna_uiTemplateCacheFileTimeSettings(uiLayout *layout,
PointerRNA *ptr,
const char *propname)
{
PointerRNA fileptr;
if (!uiTemplateCacheFilePointer(ptr, propname, &fileptr)) {
return;
}
uiTemplateCacheFileTimeSettings(layout, &fileptr);
}
static void rna_uiTemplatePathBuilder(uiLayout *layout,
PointerRNA *ptr,
const char *propname,
@ -1795,6 +1832,21 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
api_ui_item_rna_common(func);
func = RNA_def_function(srna, "template_cache_file_velocity", "rna_uiTemplateCacheFileVelocity");
RNA_def_function_ui_description(func, "Show cache files velocity properties");
api_ui_item_rna_common(func);
func = RNA_def_function(
srna, "template_cache_file_procedural", "rna_uiTemplateCacheFileProcedural");
RNA_def_function_ui_description(func, "Show cache files render procedural properties");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
api_ui_item_rna_common(func);
func = RNA_def_function(
srna, "template_cache_file_time_settings", "rna_uiTemplateCacheFileTimeSettings");
RNA_def_function_ui_description(func, "Show cache files time settings");
api_ui_item_rna_common(func);
func = RNA_def_function(srna, "template_recent_files", "uiTemplateRecentFiles");
RNA_def_function_ui_description(func, "Show list of recently saved .blend files");
RNA_def_int(func, "rows", 5, 1, INT_MAX, "", "Maximum number of items to show", 1, INT_MAX);

View File

@ -328,14 +328,71 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, ptr, "use_vertex_interpolation", 0, NULL, ICON_NONE);
}
uiItemR(layout, ptr, "velocity_scale", 0, NULL, ICON_NONE);
modifier_panel_end(layout, ptr);
}
static void velocity_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA ob_ptr;
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
PointerRNA fileptr;
if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) {
return;
}
uiLayoutSetPropSep(layout, true);
uiTemplateCacheFileVelocity(layout, &fileptr);
uiItemR(layout, ptr, "velocity_scale", 0, NULL, ICON_NONE);
}
static void time_panel_draw(const bContext *UNUSED(C), Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA ob_ptr;
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
PointerRNA fileptr;
if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) {
return;
}
uiLayoutSetPropSep(layout, true);
uiTemplateCacheFileTimeSettings(layout, &fileptr);
}
static void render_procedural_panel_draw(const bContext *C, Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA ob_ptr;
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
PointerRNA fileptr;
if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) {
return;
}
uiLayoutSetPropSep(layout, true);
uiTemplateCacheFileProcedural(layout, C, &fileptr);
}
static void panelRegister(ARegionType *region_type)
{
modifier_panel_register(region_type, eModifierType_MeshSequenceCache, panel_draw);
PanelType *panel_type = modifier_panel_register(
region_type, eModifierType_MeshSequenceCache, panel_draw);
modifier_subpanel_register(region_type, "time", "Time", NULL, time_panel_draw, panel_type);
modifier_subpanel_register(region_type,
"render_procedural",
"Render Procedural",
NULL,
render_procedural_panel_draw,
panel_type);
modifier_subpanel_register(
region_type, "velocity", "Velocity", NULL, velocity_panel_draw, panel_type);
}
static void blendRead(BlendDataReader *UNUSED(reader), ModifierData *md)