forked from bartvdbraak/blender
GPencil: Add Opacity y Onion switch to Dopesheet
Add new icons and panels Grease Pencil Dopesheet to manage layers without having the properties panel visible. Also, the icons are in the same order in Dopesheet, Layers and Material list to keep consistency. As the number of columns for icons is limited to 3 and we also need use a factor, I have impleted the change using slider area. Also, the slider option is enabled by default for 2D Template. See T72026 for more info. Reviewed By: mendio, pepeland, billreynish Differential Revision: https://developer.blender.org/D6328
This commit is contained in:
parent
541d0fdba6
commit
98ff6cfa57
@ -21,6 +21,12 @@ import bpy
|
||||
from bpy.types import Menu, Panel, UIList
|
||||
from rna_prop_ui import PropertyPanel
|
||||
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
GreasePencilLayerAdjustmentsPanel,
|
||||
GreasePencilLayerRelationsPanel,
|
||||
GreasePencilLayerDisplayPanel,
|
||||
)
|
||||
|
||||
###############################
|
||||
# Base-Classes (for shared stuff - e.g. poll, attributes, etc.)
|
||||
|
||||
@ -152,8 +158,8 @@ class DATA_PT_gpencil_layers(DataButtonsPanel, Panel):
|
||||
col.separator()
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
|
||||
sub.operator("gpencil.layer_isolate", icon='RESTRICT_VIEW_ON', text="").affect_visibility = True
|
||||
sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
|
||||
|
||||
# Layer main properties
|
||||
row = layout.row()
|
||||
@ -173,83 +179,23 @@ class DATA_PT_gpencil_layers(DataButtonsPanel, Panel):
|
||||
col.prop(gpl, "opacity", text="Opacity", slider=True)
|
||||
|
||||
|
||||
class DATA_PT_gpencil_layer_adjustments(LayerDataButtonsPanel, Panel):
|
||||
class DATA_PT_gpencil_layer_adjustments(LayerDataButtonsPanel, GreasePencilLayerAdjustmentsPanel, Panel):
|
||||
bl_label = "Adjustments"
|
||||
bl_parent_id = 'DATA_PT_gpencil_layers'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
scene = context.scene
|
||||
|
||||
gpd = context.gpencil
|
||||
gpl = gpd.layers.active
|
||||
layout.active = not gpl.lock
|
||||
|
||||
# Layer options
|
||||
# Offsets - Color Tint
|
||||
layout.enabled = not gpl.lock
|
||||
col = layout.column(align=True)
|
||||
col.prop(gpl, "tint_color")
|
||||
col.prop(gpl, "tint_factor", text="Factor", slider=True)
|
||||
|
||||
# Offsets - Thickness
|
||||
col = layout.row(align=True)
|
||||
col.prop(gpl, "line_change", text="Stroke Thickness")
|
||||
|
||||
col = layout.row(align=True)
|
||||
col.prop(gpl, "pass_index")
|
||||
|
||||
col = layout.row(align=True)
|
||||
col.prop_search(gpl, "viewlayer_render", scene, "view_layers", text="View Layer")
|
||||
|
||||
col = layout.row(align=True)
|
||||
col.prop(gpl, "lock_material")
|
||||
|
||||
|
||||
class DATA_PT_gpencil_layer_relations(LayerDataButtonsPanel, Panel):
|
||||
class DATA_PT_gpencil_layer_relations(LayerDataButtonsPanel, GreasePencilLayerRelationsPanel, Panel):
|
||||
bl_label = "Relations"
|
||||
bl_parent_id = 'DATA_PT_gpencil_layers'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
gpd = context.gpencil
|
||||
gpl = gpd.layers.active
|
||||
|
||||
col = layout.column()
|
||||
col.active = not gpl.lock
|
||||
col.prop(gpl, "parent")
|
||||
col.prop(gpl, "parent_type", text="Type")
|
||||
parent = gpl.parent
|
||||
|
||||
if parent and gpl.parent_type == 'BONE' and parent.type == 'ARMATURE':
|
||||
col.prop_search(gpl, "parent_bone", parent.data, "bones", text="Bone")
|
||||
|
||||
|
||||
class DATA_PT_gpencil_layer_display(LayerDataButtonsPanel, Panel):
|
||||
class DATA_PT_gpencil_layer_display(LayerDataButtonsPanel, GreasePencilLayerDisplayPanel, Panel):
|
||||
bl_label = "Display"
|
||||
bl_parent_id = 'DATA_PT_gpencil_layers'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
gpd = context.gpencil
|
||||
gpl = gpd.layers.active
|
||||
|
||||
col = layout.row(align=True)
|
||||
col.prop(gpl, "channel_color")
|
||||
|
||||
col = layout.row(align=True)
|
||||
col.prop(gpl, "use_solo_mode", text="Show Only On Keyframed")
|
||||
|
||||
|
||||
class DATA_PT_gpencil_onion_skinning(DataButtonsPanel, Panel):
|
||||
bl_label = "Onion Skinning"
|
||||
|
@ -871,8 +871,8 @@ class GreasePencilMaterialsPanel:
|
||||
col.separator()
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.operator("gpencil.color_isolate", icon='LOCKED', text="").affect_visibility = False
|
||||
sub.operator("gpencil.color_isolate", icon='RESTRICT_VIEW_ON', text="").affect_visibility = True
|
||||
sub.operator("gpencil.color_isolate", icon='LOCKED', text="").affect_visibility = False
|
||||
|
||||
if show_full_ui:
|
||||
row = layout.row()
|
||||
@ -935,8 +935,6 @@ class GPENCIL_UL_layer(UIList):
|
||||
icon='MOD_MASK' if gpl.mask_layer else 'LAYER_ACTIVE',
|
||||
emboss=False)
|
||||
|
||||
row.prop(gpl, "lock", text="", emboss=False)
|
||||
row.prop(gpl, "hide", text="", emboss=False)
|
||||
subrow = row.row(align=True)
|
||||
subrow.prop(
|
||||
gpl,
|
||||
@ -945,6 +943,8 @@ class GPENCIL_UL_layer(UIList):
|
||||
icon='ONIONSKIN_ON' if gpl.use_onion_skinning else 'ONIONSKIN_OFF',
|
||||
emboss=False,
|
||||
)
|
||||
row.prop(gpl, "hide", text="", emboss=False)
|
||||
row.prop(gpl, "lock", text="", emboss=False)
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.label(
|
||||
@ -981,6 +981,87 @@ class GreasePencilSimplifyPanel:
|
||||
sub.prop(rd, "simplify_gpencil_remove_lines", text="Lines")
|
||||
|
||||
|
||||
class GreasePencilLayerAdjustmentsPanel:
|
||||
bl_label = "Adjustments"
|
||||
bl_parent_id = 'DOPESHEET_PT_gpencil_mode'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
scene = context.scene
|
||||
|
||||
ob = context.object
|
||||
gpd = ob.data
|
||||
gpl = gpd.layers.active
|
||||
layout.active = not gpl.lock
|
||||
|
||||
# Layer options
|
||||
# Offsets - Color Tint
|
||||
layout.enabled = not gpl.lock
|
||||
col = layout.column(align=True)
|
||||
col.prop(gpl, "tint_color")
|
||||
col.prop(gpl, "tint_factor", text="Factor", slider=True)
|
||||
|
||||
# Offsets - Thickness
|
||||
col = layout.row(align=True)
|
||||
col.prop(gpl, "line_change", text="Stroke Thickness")
|
||||
|
||||
col = layout.row(align=True)
|
||||
col.prop(gpl, "pass_index")
|
||||
|
||||
col = layout.row(align=True)
|
||||
col.prop_search(gpl, "viewlayer_render", scene, "view_layers", text="View Layer")
|
||||
|
||||
col = layout.row(align=True)
|
||||
col.prop(gpl, "lock_material")
|
||||
|
||||
|
||||
class GreasePencilLayerRelationsPanel:
|
||||
bl_label = "Relations"
|
||||
bl_parent_id = 'DOPESHEET_PT_gpencil_mode'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
ob = context.object
|
||||
gpd = ob.data
|
||||
gpl = gpd.layers.active
|
||||
|
||||
col = layout.column()
|
||||
col.active = not gpl.lock
|
||||
col.prop(gpl, "parent")
|
||||
col.prop(gpl, "parent_type", text="Type")
|
||||
parent = gpl.parent
|
||||
|
||||
if parent and gpl.parent_type == 'BONE' and parent.type == 'ARMATURE':
|
||||
col.prop_search(gpl, "parent_bone", parent.data, "bones", text="Bone")
|
||||
|
||||
|
||||
class GreasePencilLayerDisplayPanel:
|
||||
bl_label = "Display"
|
||||
bl_parent_id = 'DOPESHEET_PT_gpencil_mode'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
ob = context.object
|
||||
gpd = ob.data
|
||||
gpl = gpd.layers.active
|
||||
|
||||
col = layout.row(align=True)
|
||||
col.prop(gpl, "channel_color")
|
||||
|
||||
col = layout.row(align=True)
|
||||
col.prop(gpl, "use_solo_mode", text="Show Only On Keyframed")
|
||||
|
||||
|
||||
classes = (
|
||||
GPENCIL_MT_pie_tool_palette,
|
||||
GPENCIL_MT_pie_settings_palette,
|
||||
|
@ -65,13 +65,13 @@ class GPENCIL_UL_matslots(UIList):
|
||||
row.prop(ma, "name", text="", emboss=False, icon_value=icon)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(gpcolor, "lock", text="", emboss=False)
|
||||
row.prop(gpcolor, "hide", text="", emboss=False)
|
||||
if gpcolor.ghost is True:
|
||||
icon = 'ONIONSKIN_OFF'
|
||||
else:
|
||||
icon = 'ONIONSKIN_ON'
|
||||
row.prop(gpcolor, "ghost", text="", icon=icon, emboss=False)
|
||||
row.prop(gpcolor, "hide", text="", emboss=False)
|
||||
row.prop(gpcolor, "lock", text="", emboss=False)
|
||||
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
|
@ -25,6 +25,12 @@ from bpy.types import (
|
||||
Panel,
|
||||
)
|
||||
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
GreasePencilLayerAdjustmentsPanel,
|
||||
GreasePencilLayerRelationsPanel,
|
||||
GreasePencilLayerDisplayPanel,
|
||||
)
|
||||
|
||||
#######################################
|
||||
# DopeSheet Filtering - Header Buttons
|
||||
|
||||
@ -243,6 +249,18 @@ class DOPESHEET_HT_editor_buttons(Header):
|
||||
|
||||
layout.template_ID(st, "action", new="action.new", unlink="action.unlink")
|
||||
|
||||
# Layer management
|
||||
if st.mode == 'GPENCIL':
|
||||
row = layout.row(align=True)
|
||||
row.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP'
|
||||
row.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN'
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("gpencil.layer_add", icon='ADD', text="")
|
||||
row.operator("gpencil.layer_remove", icon='REMOVE', text="")
|
||||
|
||||
layout.separator_spacer()
|
||||
|
||||
layout.separator_spacer()
|
||||
|
||||
if st.mode == 'DOPESHEET':
|
||||
@ -639,6 +657,65 @@ class DOPESHEET_MT_snap_pie(Menu):
|
||||
pie.operator("action.snap", text="Nearest Second").type = 'NEAREST_SECOND'
|
||||
pie.operator("action.snap", text="Nearest Marker").type = 'NEAREST_MARKER'
|
||||
|
||||
class LayersDopeSheetPanel:
|
||||
bl_space_type = 'DOPESHEET_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "View"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
st = context.space_data
|
||||
ob = context.object
|
||||
if st.mode != 'GPENCIL' or ob is None or ob.type != 'GPENCIL':
|
||||
return False
|
||||
|
||||
gpd = ob.data
|
||||
gpl = gpd.layers.active
|
||||
if gpl:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class DOPESHEET_PT_gpencil_mode(LayersDopeSheetPanel, Panel):
|
||||
# bl_space_type = 'DOPESHEET_EDITOR'
|
||||
# bl_region_type = 'UI'
|
||||
# bl_category = "View"
|
||||
bl_label = "Layer"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
ob = context.object
|
||||
gpd = ob.data
|
||||
gpl = gpd.layers.active
|
||||
if gpl:
|
||||
row = layout.row(align=True)
|
||||
row.prop(gpl, "blend_mode", text="Blend")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(gpl, "opacity", text="Opacity", slider=True)
|
||||
|
||||
|
||||
class DOPESHEET_PT_gpencil_layer_adjustments(LayersDopeSheetPanel, GreasePencilLayerAdjustmentsPanel, Panel):
|
||||
bl_label = "Adjustments"
|
||||
bl_parent_id = 'DOPESHEET_PT_gpencil_mode'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
|
||||
class DOPESHEET_PT_gpencil_layer_relations(LayersDopeSheetPanel, GreasePencilLayerRelationsPanel, Panel):
|
||||
bl_label = "Relations"
|
||||
bl_parent_id = 'DOPESHEET_PT_gpencil_mode'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
|
||||
class DOPESHEET_PT_gpencil_layer_display(LayersDopeSheetPanel, GreasePencilLayerDisplayPanel, Panel):
|
||||
bl_label = "Display"
|
||||
bl_parent_id = 'DOPESHEET_PT_gpencil_mode'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
|
||||
classes = (
|
||||
DOPESHEET_HT_header,
|
||||
@ -657,6 +734,10 @@ classes = (
|
||||
DOPESHEET_MT_channel_context_menu,
|
||||
DOPESHEET_MT_snap_pie,
|
||||
DOPESHEET_PT_filters,
|
||||
DOPESHEET_PT_gpencil_mode,
|
||||
DOPESHEET_PT_gpencil_layer_adjustments,
|
||||
DOPESHEET_PT_gpencil_layer_relations,
|
||||
DOPESHEET_PT_gpencil_layer_display,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
@ -146,8 +146,8 @@ class TOPBAR_PT_gpencil_layers(Panel):
|
||||
col.separator()
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
|
||||
sub.operator("gpencil.layer_isolate", icon='HIDE_OFF', text="").affect_visibility = True
|
||||
sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
|
||||
|
||||
|
||||
class TOPBAR_MT_editor_menus(Menu):
|
||||
|
@ -218,6 +218,19 @@ static void blo_update_defaults_screen(bScreen *screen,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 2D animation template. */
|
||||
if (app_template && STREQ(app_template, "2D_Animation")) {
|
||||
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
|
||||
for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
|
||||
if (sa->spacetype == SPACE_ACTION) {
|
||||
SpaceAction *saction = sa->spacedata.first;
|
||||
/* Enable Sliders. */
|
||||
saction->flag |= SACTION_SLIDERS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BLO_update_defaults_workspace(WorkSpace *workspace, const char *app_template)
|
||||
|
@ -4222,7 +4222,8 @@ void ANIM_channel_draw(
|
||||
* - Slider should start before the toggles (if they're visible)
|
||||
* to keep a clean line down the side.
|
||||
*/
|
||||
if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY)) {
|
||||
if ((draw_sliders) &&
|
||||
ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY, ANIMTYPE_GPLAYER)) {
|
||||
/* adjust offset */
|
||||
offset += SLIDER_WIDTH;
|
||||
}
|
||||
@ -4992,7 +4993,8 @@ void ANIM_channel_draw_widgets(const bContext *C,
|
||||
* - Slider should start before the toggles (if they're visible)
|
||||
* to keep a clean line down the side.
|
||||
*/
|
||||
if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY)) {
|
||||
if ((draw_sliders) &&
|
||||
ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY, ANIMTYPE_GPLAYER)) {
|
||||
/* adjust offset */
|
||||
/* TODO: make slider width dynamic,
|
||||
* so that they can be easier to use when the view is wide enough. */
|
||||
@ -5053,8 +5055,70 @@ void ANIM_channel_draw_widgets(const bContext *C,
|
||||
rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
|
||||
free_path = 1;
|
||||
}
|
||||
/* Special for Grease Pencil Layer. */
|
||||
else if (ale->type == ANIMTYPE_GPLAYER) {
|
||||
/* Add some offset to make it more pleasing to the eye. */
|
||||
offset += SLIDER_WIDTH / 2.1f;
|
||||
|
||||
/* only if RNA-Path found */
|
||||
char *gp_rna_path = NULL;
|
||||
bGPDlayer *gpl = (bGPDlayer *)ale->data;
|
||||
const short width = SLIDER_WIDTH / 5;
|
||||
|
||||
/* Create the RNA pointers. */
|
||||
RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, &ptr);
|
||||
RNA_id_pointer_create(ale->id, &id_ptr);
|
||||
int icon;
|
||||
|
||||
/* Mask Layer. */
|
||||
UI_block_emboss_set(block, UI_EMBOSS_NONE);
|
||||
prop = RNA_struct_find_property(&ptr, "mask_layer");
|
||||
gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
|
||||
if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
|
||||
icon = (gpl->flag & GP_LAYER_USE_MASK) ? ICON_MOD_MASK : ICON_LAYER_ACTIVE;
|
||||
uiDefAutoButR(
|
||||
block, &ptr, prop, array_index, "", icon, offset, ymid, width, channel_height);
|
||||
}
|
||||
MEM_freeN(gp_rna_path);
|
||||
|
||||
/* Layer opacity. */
|
||||
UI_block_emboss_set(block, UI_EMBOSS);
|
||||
prop = RNA_struct_find_property(&ptr, "opacity");
|
||||
gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
|
||||
if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
|
||||
uiDefAutoButR(block,
|
||||
&ptr,
|
||||
prop,
|
||||
array_index,
|
||||
"",
|
||||
ICON_NONE,
|
||||
offset + width,
|
||||
ymid,
|
||||
width * 3,
|
||||
channel_height);
|
||||
}
|
||||
MEM_freeN(gp_rna_path);
|
||||
|
||||
/* Layer onion skinning switch. */
|
||||
UI_block_emboss_set(block, UI_EMBOSS_NONE);
|
||||
prop = RNA_struct_find_property(&ptr, "use_onion_skinning");
|
||||
gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
|
||||
if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
|
||||
icon = (gpl->onion_flag & GP_LAYER_ONIONSKIN) ? ICON_ONIONSKIN_ON : ICON_ONIONSKIN_OFF;
|
||||
uiDefAutoButR(block,
|
||||
&ptr,
|
||||
prop,
|
||||
array_index,
|
||||
"",
|
||||
icon,
|
||||
offset + (width * 4),
|
||||
ymid,
|
||||
width,
|
||||
channel_height);
|
||||
}
|
||||
MEM_freeN(gp_rna_path);
|
||||
}
|
||||
|
||||
/* Only if RNA-Path found. */
|
||||
if (rna_path) {
|
||||
/* get RNA pointer, and resolve the path */
|
||||
RNA_id_pointer_create(ale->id, &id_ptr);
|
||||
|
@ -105,6 +105,7 @@ bGPdata **ED_gpencil_data_get_pointers_direct(
|
||||
/* XXX: Should we reduce reliance on context.gpencil_data for these cases? */
|
||||
case SPACE_PROPERTIES: /* properties */
|
||||
case SPACE_INFO: /* header info (needed after workspaces merge) */
|
||||
case SPACE_ACTION: /* Dopesheet header. */
|
||||
{
|
||||
if (ob && (ob->type == OB_GPENCIL)) {
|
||||
/* GP Object */
|
||||
|
Loading…
Reference in New Issue
Block a user