UI: Use property split layout and decorators for material properties

Use the automatic property split layout (hence, change to the new 40/60% split
ratio) and add decorator buttons for animatable properties.
This actually applies to all node input buttons in the properties, e.g. world shading,
light shading, texture nodes.

Doing this makes the layout more consistent with other layouts in the
properties. But the decorators are also a useful hint for users that these
options can be animated. Previously using decorators and the automatic split
layout wasn't possible, I've done a number of changes now to have it supported.
Before I moved the socket icons to the left side, the decorators also looked
weird (two circle icons next to each other).

{F8497704} With nested items: {F8497708}

Reviewed By: William Reynish, Pablo Vazquez

Differential Revision: https://developer.blender.org/D7544
This commit is contained in:
Julian Eisel 2020-05-01 15:21:41 +02:00
parent 2188175891
commit 4cc8123377
6 changed files with 507 additions and 476 deletions

View File

@ -1410,6 +1410,8 @@ class CYCLES_LIGHT_PT_nodes(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
light = context.light
panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface')
@ -1459,6 +1461,8 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
world = context.world
if not panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Surface'):
@ -1478,6 +1482,8 @@ class CYCLES_WORLD_PT_volume(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
world = context.world
panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
@ -1665,6 +1671,8 @@ class CYCLES_MATERIAL_PT_surface(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
mat = context.material
if not panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Surface'):
layout.prop(mat, "diffuse_color")
@ -1683,6 +1691,8 @@ class CYCLES_MATERIAL_PT_volume(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
mat = context.material
# cmat = mat.cycles
@ -1701,6 +1711,8 @@ class CYCLES_MATERIAL_PT_displacement(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
mat = context.material
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Displacement')

View File

@ -172,10 +172,11 @@ class EEVEE_MATERIAL_PT_surface(MaterialButtonsPanel, Panel):
layout.prop(mat, "use_nodes", icon='NODETREE')
layout.separator()
layout.use_property_split = True
if mat.use_nodes:
panel_node_draw(layout, mat.node_tree, 'OUTPUT_MATERIAL', "Surface")
else:
layout.use_property_split = True
layout.prop(mat, "diffuse_color", text="Base Color")
layout.prop(mat, "metallic")
layout.prop(mat, "specular_intensity", text="Specular")
@ -197,6 +198,8 @@ class EEVEE_MATERIAL_PT_volume(MaterialButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
mat = context.material
panel_node_draw(layout, mat.node_tree, 'OUTPUT_MATERIAL', "Volume")

View File

@ -163,6 +163,8 @@ class TEXTURE_PT_node(TextureButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
layout.use_property_split = True
node = context.texture_node
ntree = node.id_data
layout.template_node_view(ntree, node, None)

View File

@ -105,6 +105,8 @@ class EEVEE_WORLD_PT_surface(WorldButtonsPanel, Panel):
layout.prop(world, "use_nodes", icon='NODETREE')
layout.separator()
layout.use_property_split = True
if world.use_nodes:
ntree = world.node_tree
node = ntree.get_output_node('EEVEE')
@ -139,6 +141,8 @@ class EEVEE_WORLD_PT_volume(WorldButtonsPanel, Panel):
ntree = world.node_tree
node = ntree.get_output_node('EEVEE')
layout.use_property_split = True
if node:
input = find_node_input(node, 'Volume')
if input:

File diff suppressed because it is too large Load Diff

View File

@ -716,18 +716,14 @@ static void ui_node_draw_node(
uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, int depth)
{
bNodeSocket *input;
uiLayout *col, *split;
PointerRNA nodeptr;
RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
if (node->typeinfo->draw_buttons) {
if (node->type != NODE_GROUP) {
split = uiLayoutSplit(layout, 0.5f, false);
col = uiLayoutColumn(split, false);
col = uiLayoutColumn(split, false);
node->typeinfo->draw_buttons(col, C, &nodeptr);
uiLayoutSetPropSep(layout, true);
node->typeinfo->draw_buttons(layout, C, &nodeptr);
}
}
@ -741,12 +737,9 @@ static void ui_node_draw_input(
{
PointerRNA inputptr, nodeptr;
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *bt;
uiLayout *split, *row, *col;
uiLayout *row = NULL;
bNode *lnode;
char label[UI_MAX_NAME_STR];
int i, indent = (depth > 1) ? 2 * (depth - 1) : 0;
int dependency_loop;
bool dependency_loop;
if (input->flag & SOCK_UNAVAIL) {
return;
@ -765,48 +758,43 @@ static void ui_node_draw_input(
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr);
RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
/* indented label */
for (i = 0; i < indent; i++) {
label[i] = ' ';
}
label[indent] = '\0';
BLI_snprintf(label + indent, UI_MAX_NAME_STR - indent, "%s", IFACE_(input->name));
row = uiLayoutRow(layout, true);
/* Decorations are added manually here. */
uiLayoutSetPropDecorate(row, false);
/* split in label and value */
split = uiLayoutSplit(layout, 0.5f, false);
uiPropertySplitWrapper split_wrapper = uiItemPropertySplitWrapperCreate(row);
/* Empty decorator item for alignment. */
bool add_dummy_decorator = false;
row = uiLayoutRow(split, true);
{
uiLayout *sub = uiLayoutRow(split_wrapper.label_column, true);
if (depth > 0) {
UI_block_emboss_set(block, UI_EMBOSS_NONE);
if (depth > 0) {
UI_block_emboss_set(block, UI_EMBOSS_NONE);
if (lnode &&
(lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) {
int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT :
ICON_DISCLOSURE_TRI_DOWN;
uiItemR(row, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon);
}
else {
uiItemL(row, "", ICON_BLANK1);
if (lnode &&
(lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) {
int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT :
ICON_DISCLOSURE_TRI_DOWN;
uiItemR(sub, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon);
}
UI_block_emboss_set(block, UI_EMBOSS);
}
bt = block->buttons.last;
bt->rect.xmax = UI_UNIT_X / 2;
UI_block_emboss_set(block, UI_EMBOSS);
sub = uiLayoutRow(sub, true);
uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT);
uiItemL(sub, IFACE_(input->name), ICON_NONE);
}
uiItemL(row, label, ICON_NONE);
bt = block->buttons.last;
bt->drawflag = UI_BUT_TEXT_RIGHT;
if (dependency_loop) {
row = uiLayoutRow(split, false);
uiItemL(row, IFACE_("Dependency Loop"), ICON_ERROR);
add_dummy_decorator = true;
}
else if (lnode) {
/* input linked to a node */
uiTemplateNodeLink(split, C, ntree, node, input);
uiTemplateNodeLink(row, C, ntree, node, input);
add_dummy_decorator = true;
if (depth == 0 || !(input->flag & SOCK_COLLAPSED)) {
if (depth == 0) {
@ -817,29 +805,43 @@ static void ui_node_draw_input(
}
}
else {
row = uiLayoutRow(split, true);
row = uiLayoutRow(row, true);
uiTemplateNodeLink(row, C, ntree, node, input);
if (input->flag & SOCK_HIDE_VALUE) {
add_dummy_decorator = true;
}
/* input not linked, show value */
if (!(input->flag & SOCK_HIDE_VALUE)) {
else {
uiLayout *sub = row;
switch (input->type) {
case SOCK_VECTOR:
if (input->type == SOCK_VECTOR) {
uiItemS(row);
sub = uiLayoutColumn(row, true);
}
ATTR_FALLTHROUGH;
case SOCK_FLOAT:
case SOCK_INT:
case SOCK_BOOLEAN:
case SOCK_RGBA:
case SOCK_STRING:
uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE);
break;
case SOCK_VECTOR:
uiItemS(row);
col = uiLayoutColumn(row, false);
uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE);
uiItemR(sub, &inputptr, "default_value", 0, "", ICON_NONE);
uiItemDecoratorR(
split_wrapper.decorate_column, &inputptr, "default_value", RNA_NO_INDEX);
break;
default:
add_dummy_decorator = true;
}
}
}
if (add_dummy_decorator) {
uiItemDecoratorR(split_wrapper.decorate_column, NULL, NULL, 0);
}
/* clear */
node->flag &= ~NODE_TEST;
}