Sculpt: Brush settings panel editor
* Moved brush settings (in sculpt mode) to (for now) a new properties editor tab. * Brush settings can now be individually configured to show up in the workspace buttons. * Brush settings can also be reordered. * The new brush tab has a "preview" subpanel to preview the workspace settings layout. This is where settings are reordered.
This commit is contained in:
parent
0e2ec88e6b
commit
36d5b6e959
|
@ -97,7 +97,7 @@ _modules = [
|
|||
"space_view3d_toolbar",
|
||||
|
||||
# XXX, keep last so panels show after all other tool options.
|
||||
"properties_workspace",
|
||||
"properties_workspace"
|
||||
]
|
||||
|
||||
import bpy
|
||||
|
|
|
@ -29,6 +29,7 @@ channel_name_map = {
|
|||
"autosmooth_fset_slide": "fset_slide",
|
||||
"topology_rake_factor": "topology_rake"
|
||||
};
|
||||
expand_channels = {"direction"}
|
||||
|
||||
class UnifiedPaintPanel:
|
||||
# subclass must set
|
||||
|
@ -109,12 +110,15 @@ class UnifiedPaintPanel:
|
|||
|
||||
@staticmethod
|
||||
def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=True, text=None,
|
||||
slider=False, header=False, expand=None, toolsettings_only=False):
|
||||
slider=False, header=False, show_reorder=False, expand=None, toolsettings_only=False, ui_editing=True):
|
||||
""" Generalized way of adding brush options to the UI,
|
||||
along with their pen pressure setting and global toggle, if they exist. """
|
||||
ch = brush.channels.channels[prop_name]
|
||||
finalch = ch
|
||||
|
||||
if prop_name in expand_channels:
|
||||
expand = True
|
||||
|
||||
l1 = layout
|
||||
|
||||
#if ch.ui_expanded:
|
||||
|
@ -161,6 +165,21 @@ class UnifiedPaintPanel:
|
|||
path = "tool_settings.sculpt.channels.channels[\"%s\"]" % ch.idname
|
||||
else:
|
||||
path = "tool_settings.sculpt.brush.channels.channels[\"%s\"]" % ch.idname
|
||||
|
||||
if show_reorder:
|
||||
props = row.operator("brush.change_channel_order", text="", icon="TRIA_UP")
|
||||
props.channel = ch.idname
|
||||
props.filterkey = "show_in_workspace"
|
||||
props.direction = -1
|
||||
|
||||
props = row.operator("brush.change_channel_order", text="", icon="TRIA_DOWN")
|
||||
props.filterkey = "show_in_workspace"
|
||||
props.channel = ch.idname
|
||||
props.direction = 1
|
||||
|
||||
if ui_editing:
|
||||
row.prop(ch, "show_in_workspace", text="", icon="HIDE_OFF")
|
||||
#row.prop(ch, "ui_order", text="")
|
||||
|
||||
if ch.type == "BITMASK":
|
||||
row.label(text=text)
|
||||
|
@ -186,6 +205,8 @@ class UnifiedPaintPanel:
|
|||
|
||||
if pressure:
|
||||
row.prop(finalch.mappings["PRESSURE"], "enabled", text="", icon="STYLUS_PRESSURE")
|
||||
|
||||
|
||||
#if pressure_name:
|
||||
# row.prop(brush, pressure_name, text="")
|
||||
|
||||
|
@ -202,6 +223,9 @@ class UnifiedPaintPanel:
|
|||
if ch.type == "BITMASK" or ch.type == "BOOL":
|
||||
return
|
||||
|
||||
if not ui_editing and not show_reorder:
|
||||
return
|
||||
|
||||
row.prop(ch, "ui_expanded", text="", icon="TRIA_DOWN" if ch.ui_expanded else "TRIA_RIGHT")
|
||||
|
||||
if ch.ui_expanded:
|
||||
|
@ -1075,9 +1099,6 @@ def brush_settings(layout, context, brush, popover=False):
|
|||
layout.row().prop(brush, "mask_tool", expand=True)
|
||||
|
||||
|
||||
layout.template_curve_mapping(brush, "pressure_size_curve")
|
||||
layout.template_curve_mapping(brush, "pressure_strength_curve", brush=True)
|
||||
|
||||
# End sculpt_tool interface.
|
||||
|
||||
# 3D and 2D Texture Paint Mode.
|
||||
|
@ -1226,6 +1247,91 @@ def brush_shared_settings(layout, context, brush, popover=False):
|
|||
"direction", expand=True)
|
||||
#layout.row().prop(brush, "direction", expand=True)
|
||||
|
||||
from bpy.types import Operator
|
||||
from bpy.props import IntProperty, StringProperty
|
||||
|
||||
def get_ui_channels(channels, filterkeys=["show_in_workspace"]):
|
||||
ret = []
|
||||
for ch in channels:
|
||||
ok = len(filterkeys) == 0
|
||||
for key in filterkeys:
|
||||
if getattr(ch, key):
|
||||
ok = True
|
||||
break
|
||||
if ok:
|
||||
ret.append(ch)
|
||||
|
||||
ret.sort(key = lambda x: x.ui_order)
|
||||
|
||||
return ret
|
||||
|
||||
class ReorderBrushChannel(Operator):
|
||||
"""Tooltip"""
|
||||
bl_idname = "brush.change_channel_order"
|
||||
bl_label = "Change Channel Order"
|
||||
bl_options = {"UNDO"}
|
||||
|
||||
direction : IntProperty()
|
||||
channel : StringProperty()
|
||||
filterkey : StringProperty()
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.mode == "SCULPT" and context.tool_settings.sculpt.brush
|
||||
|
||||
def execute(self, context):
|
||||
ts = context.tool_settings
|
||||
|
||||
brush = ts.sculpt.brush
|
||||
|
||||
channels = brush.channels.channels
|
||||
if self.channel not in channels:
|
||||
print("bad channel ", self.channel)
|
||||
return {'CANCELLED'}
|
||||
|
||||
uinames = get_ui_channels(channels, [self.filterkey])
|
||||
uinames = set(map(lambda x: x.idname, uinames))
|
||||
|
||||
channel = channels[self.channel]
|
||||
|
||||
channels = list(channels)
|
||||
channels.sort(key = lambda x: x.ui_order)
|
||||
|
||||
i = channels.index(channel)
|
||||
i2 = i + self.direction
|
||||
|
||||
print("ORDERING", i, i2, self.direction, i2 < 0 or i2 >= len(channels))
|
||||
|
||||
if i2 < 0 or i2 >= len(channels):
|
||||
return {'CANCELLED'}
|
||||
|
||||
while i2 >= 0 and i2 < len(channels) and channels[i2].idname not in uinames:
|
||||
i2 += self.direction
|
||||
|
||||
i2 = min(max(i2, 0), len(channels)-1)
|
||||
|
||||
tmp = channels[i2]
|
||||
channels[i2] = channels[i]
|
||||
channels[i] = tmp
|
||||
|
||||
#ensure ui_order is 1-to-1
|
||||
for i, ch in enumerate(channels):
|
||||
ch.ui_order = i
|
||||
print(ch.idname, i)
|
||||
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
def brush_settings_channels(layout, context, brush, ui_editing=False, popover=False, filterkey="show_in_workspace"):
|
||||
channels = get_ui_channels(brush.channels.channels, [filterkey])
|
||||
|
||||
for ch in channels:
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout.column(),
|
||||
context,
|
||||
brush,
|
||||
ch.idname, show_reorder = ui_editing, expand=False, ui_editing=False)
|
||||
|
||||
|
||||
def brush_settings_advanced(layout, context, brush, popover=False):
|
||||
"""Draw advanced brush settings for Sculpt, Texture/Vertex/Weight Paint modes."""
|
||||
|
@ -1709,6 +1815,7 @@ def brush_basic_gpencil_vertex_settings(layout, _context, brush, *, compact=Fals
|
|||
|
||||
classes = (
|
||||
VIEW3D_MT_tools_projectpaint_clone,
|
||||
ReorderBrushChannel
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
from bpy.types import Menu, Panel, UIList, WindowManager
|
||||
from bpy.types import Menu, Panel, UIList, WindowManager, SpaceProperties
|
||||
from bl_ui.properties_grease_pencil_common import (
|
||||
GreasePencilSculptOptionsPanel,
|
||||
GreasePencilDisplayPanel,
|
||||
|
@ -37,6 +37,7 @@ from bl_ui.properties_paint_common import (
|
|||
brush_mask_texture_settings,
|
||||
brush_settings,
|
||||
brush_settings_advanced,
|
||||
brush_settings_channels,
|
||||
draw_color_settings,
|
||||
)
|
||||
from bl_ui.utils import PresetPanel
|
||||
|
@ -378,7 +379,9 @@ class VIEW3D_PT_tools_brush_select(Panel, View3DPaintBrushPanel, BrushSelectPane
|
|||
bl_label = "Brushes"
|
||||
|
||||
|
||||
# TODO, move to space_view3d.py
|
||||
def is_brush_editor(context):
|
||||
return type(context.space_data) == SpaceProperties and context.space_data.context == "BRUSH_EDITOR"
|
||||
|
||||
class VIEW3D_PT_tools_brush_settings(Panel, View3DPaintBrushPanel):
|
||||
bl_context = ".paint_common"
|
||||
bl_label = "Brush Settings"
|
||||
|
@ -386,7 +389,11 @@ class VIEW3D_PT_tools_brush_settings(Panel, View3DPaintBrushPanel):
|
|||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = cls.paint_settings(context)
|
||||
return settings and settings.brush is not None
|
||||
|
||||
ok = settings and settings.brush is not None
|
||||
ok = ok and not (context.mode == "SCULPT" and not is_brush_editor(context))
|
||||
|
||||
return ok
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@ -399,6 +406,54 @@ class VIEW3D_PT_tools_brush_settings(Panel, View3DPaintBrushPanel):
|
|||
|
||||
brush_settings(layout.column(), context, brush, popover=self.is_popover)
|
||||
|
||||
class VIEW3D_PT_tools_brush_settings_channels(Panel, View3DPaintBrushPanel):
|
||||
bl_context = ".paint_common"
|
||||
bl_label = "Brush Settings"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = cls.paint_settings(context)
|
||||
|
||||
ok = settings and settings.brush is not None
|
||||
ok = ok and context.mode == "SCULPT" and not is_brush_editor(context)
|
||||
|
||||
return ok
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
brush_settings_channels(layout.column(), context, brush, popover=self.is_popover)
|
||||
|
||||
class VIEW3D_PT_tools_brush_settings_channels_preview(Panel, View3DPaintBrushPanel):
|
||||
bl_context = ".paint_common"
|
||||
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
|
||||
bl_label = "Settings Preview"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
settings = cls.paint_settings(context)
|
||||
|
||||
ok = settings and settings.brush is not None
|
||||
ok = ok and context.mode == "SCULPT" and is_brush_editor(context)
|
||||
|
||||
return ok
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False # No animation.
|
||||
|
||||
settings = self.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
brush_settings_channels(layout.column(), context, brush, ui_editing=True, popover=self.is_popover)
|
||||
|
||||
class VIEW3D_PT_tools_brush_settings_advanced(Panel, View3DPaintBrushPanel):
|
||||
bl_context = ".paint_common"
|
||||
|
@ -756,7 +811,7 @@ class VIEW3D_PT_tools_brush_falloff_normal(View3DPaintPanel, Panel):
|
|||
|
||||
# TODO, move to space_view3d.py
|
||||
class VIEW3D_PT_sculpt_dyntopo_advanced(Panel, View3DPaintPanel):
|
||||
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
|
||||
bl_context = ".brush_editor"
|
||||
bl_label = "Dyntopo (Advanced)"
|
||||
#bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_ui_units_x = 12
|
||||
|
@ -764,7 +819,11 @@ class VIEW3D_PT_sculpt_dyntopo_advanced(Panel, View3DPaintPanel):
|
|||
@classmethod
|
||||
def poll(cls, context):
|
||||
paint_settings = cls.paint_settings(context)
|
||||
return (context.sculpt_object and context.tool_settings.sculpt and paint_settings)
|
||||
|
||||
ok = is_brush_editor(context)
|
||||
ok = ok and (context.sculpt_object and context.tool_settings.sculpt and paint_settings)
|
||||
|
||||
return ok
|
||||
|
||||
def draw_header(self, context):
|
||||
pass
|
||||
|
@ -2307,6 +2366,8 @@ classes = (
|
|||
VIEW3D_PT_slots_projectpaint,
|
||||
VIEW3D_PT_tools_brush_select,
|
||||
VIEW3D_PT_tools_brush_settings,
|
||||
VIEW3D_PT_tools_brush_settings_channels,
|
||||
VIEW3D_PT_tools_brush_settings_channels_preview,
|
||||
VIEW3D_PT_tools_brush_color,
|
||||
VIEW3D_PT_tools_brush_swatches,
|
||||
VIEW3D_PT_tools_brush_settings_advanced,
|
||||
|
|
|
@ -101,7 +101,7 @@ typedef struct BrushEnumDef {
|
|||
} BrushEnumDef;
|
||||
|
||||
typedef struct BrushChannelType {
|
||||
char name[64], idname[64], tooltip[512];
|
||||
char name[128], idname[64], tooltip[512];
|
||||
float min, max, soft_min, soft_max;
|
||||
BrushMappingPreset mappings;
|
||||
|
||||
|
@ -274,6 +274,7 @@ bool BKE_brush_mapping_ensure_write(BrushMapping *mp);
|
|||
|
||||
void BKE_brush_channelset_apply_mapping(BrushChannelSet *chset, BrushMappingData *mapdata);
|
||||
void BKE_brush_check_toolsettings(struct Sculpt *sd);
|
||||
void BKE_brush_channelset_ui_init(struct Brush *brush, int tool);
|
||||
|
||||
/*
|
||||
set up static type checker for BRUSHSET_XXX macros
|
||||
|
|
|
@ -321,6 +321,7 @@ static void brush_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
}
|
||||
else {
|
||||
BKE_brush_builtin_create(brush, brush->sculpt_tool);
|
||||
BKE_brush_channelset_ui_init(brush, brush->sculpt_tool);
|
||||
}
|
||||
|
||||
if (brush->dyntopo.radius_scale == 0.0f) {
|
||||
|
@ -1799,6 +1800,7 @@ void BKE_brush_sculpt_reset(Brush *br)
|
|||
// BKE_brush_debug_print_state(br);
|
||||
|
||||
BKE_brush_builtin_create(br, br->sculpt_tool);
|
||||
|
||||
BrushChannel *ch;
|
||||
|
||||
for (ch = (BrushChannel *)br->channels->channels.first; ch; ch = ch->next) {
|
||||
|
@ -1808,6 +1810,8 @@ void BKE_brush_sculpt_reset(Brush *br)
|
|||
BKE_brush_channel_init(ch, def);
|
||||
}
|
||||
|
||||
BKE_brush_channelset_ui_init(br, br->sculpt_tool);
|
||||
|
||||
brush_defaults(br);
|
||||
BKE_brush_curve_preset(br, CURVE_PRESET_SMOOTH);
|
||||
BKE_brush_default_input_curves_set(br);
|
||||
|
|
|
@ -1,4 +1,19 @@
|
|||
// static name checking stuff
|
||||
/* Builtin brush channels are defined in this file.
|
||||
|
||||
When adding a new channel, the following other
|
||||
places in rna_engine_codebase are relevent:
|
||||
|
||||
- brush_settings_map: use to convert to/from settings structures in Brush
|
||||
- dyntopo_settings_map: same as above but for DynTopoSettings
|
||||
- brush_flags_map: used to convert bitflags
|
||||
- BKE_brush_builtin_patch(): adds missing channels to channelsets
|
||||
- BKE_brush_builtin_create(): adds channels to brushes based on brush type (Brush->sculpt_tool)
|
||||
- BKE_brush_check_toolsettings: adds missing channels to tool settings
|
||||
- BKE_brush_channelset_ui_init: Configures UI visibility for channels based on brush type
|
||||
|
||||
*/
|
||||
|
||||
/* static name checking stuff */
|
||||
#if defined(BRUSH_CHANNEL_DEFINE_TYPES) || defined(BRUSH_CHANNEL_DEFINE_EXTERNAL)
|
||||
# ifdef MAKE_FLOAT
|
||||
# undef MAKE_FLOAT
|
||||
|
@ -199,6 +214,56 @@ MAKE_BOOL(use_multiplane_scrape_dynamic, "Dynamic Mode", "The angle between the
|
|||
MAKE_BOOL(show_multiplane_scrape_planes_preview, "Show Cursor Preview", "Preview the scrape planes in the cursor during the stroke", true)
|
||||
MAKE_FLOAT(multiplane_scrape_angle, "Plane Angle", "Angle between the planes of the crease", 60.0f, 0.0f, 160.0f)
|
||||
|
||||
MAKE_BOOL(use_persistent, "Persistent", "Sculpt on a persistent layer of the mesh", false)
|
||||
MAKE_ENUM(cloth_deform_type, "Deformation", "Deformation type that is used in the brush", BRUSH_CLOTH_DEFORM_DRAG, _({
|
||||
{BRUSH_CLOTH_DEFORM_DRAG, "DRAG", 0, "Drag", ""},
|
||||
{BRUSH_CLOTH_DEFORM_PUSH, "PUSH", 0, "Push", ""},
|
||||
{BRUSH_CLOTH_DEFORM_PINCH_POINT, "PINCH_POINT", 0, "Pinch Point", ""},
|
||||
{BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR,
|
||||
"PINCH_PERPENDICULAR",
|
||||
0,
|
||||
"Pinch Perpendicular",
|
||||
""},
|
||||
{BRUSH_CLOTH_DEFORM_INFLATE, "INFLATE", 0, "Inflate", ""},
|
||||
{BRUSH_CLOTH_DEFORM_GRAB, "GRAB", 0, "Grab", ""},
|
||||
{BRUSH_CLOTH_DEFORM_EXPAND, "EXPAND", 0, "Expand", ""},
|
||||
{BRUSH_CLOTH_DEFORM_SNAKE_HOOK, "SNAKE_HOOK", 0, "Snake Hook", ""},
|
||||
{BRUSH_CLOTH_DEFORM_ELASTIC_DRAG, "ELASTIC", 0, "Elastic Drag", ""},
|
||||
{-1}
|
||||
}))
|
||||
|
||||
MAKE_ENUM(cloth_simulation_area_type, "Simulation Area", "Part of the mesh that is going to be simulated when the stroke is active", BRUSH_CLOTH_SIMULATION_AREA_LOCAL, _({
|
||||
{BRUSH_CLOTH_SIMULATION_AREA_LOCAL,
|
||||
"LOCAL",
|
||||
0,
|
||||
"Local",
|
||||
"Simulates only a specific area around the brush limited by a fixed radius"},
|
||||
{BRUSH_CLOTH_SIMULATION_AREA_GLOBAL, "GLOBAL", 0, "Global", "Simulates the entire mesh"},
|
||||
{BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC,
|
||||
"DYNAMIC",
|
||||
0,
|
||||
"Dynamic",
|
||||
"The active simulation area moves with the brush"},
|
||||
{-1}
|
||||
}))
|
||||
|
||||
MAKE_ENUM(cloth_force_falloff_type, "Force Falloff", "Shape used in the brush to apply force to the cloth",
|
||||
BRUSH_CLOTH_FORCE_FALLOFF_RADIAL, _({
|
||||
{BRUSH_CLOTH_FORCE_FALLOFF_RADIAL, "RADIAL", 0, "Radial", ""},
|
||||
{BRUSH_CLOTH_FORCE_FALLOFF_PLANE, "PLANE", 0, "Plane", ""},
|
||||
{-1}
|
||||
}))
|
||||
|
||||
MAKE_FLOAT(cloth_mass, "Cloth Mass", "Mass of each simulation particle", 1.0f, 0.0f, 2.0f)
|
||||
MAKE_FLOAT(cloth_damping, "Cloth Damping", "How much the applied forces are propagated through the cloth", 0.01f, 0.01f, 1.0f)
|
||||
MAKE_FLOAT(cloth_sim_limit, "Simulation Limit",
|
||||
"Factor added relative to the size of the radius to limit the cloth simulation effects", 2.5f, 0.1f, 10.0f)
|
||||
MAKE_FLOAT(cloth_sim_falloff, "Simulation Falloff",
|
||||
"Area to apply deformation falloff to the effects of the simulation", 0.75f, 0.0f, 1.0f)
|
||||
MAKE_FLOAT(cloth_constraint_softbody_strength, "Soft Body Plasticity",
|
||||
"How much the cloth preserves the original shape, acting as a soft body", 0.0f, 0.0f, 1.0f)
|
||||
MAKE_BOOL(use_frontface, "Use Front-Face", "Brush only affects vertexes that face the viewer", false)
|
||||
|
||||
/* clang-format on */
|
||||
#if defined(BRUSH_CHANNEL_DEFINE_TYPES) || defined(BRUSH_CHANNEL_DEFINE_EXTERNAL)
|
||||
# ifdef MAKE_FLOAT
|
||||
|
|
|
@ -243,6 +243,7 @@ ATTR_NO_OPT void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
|
|||
strcpy(ch->idname, def->idname);
|
||||
|
||||
ch->flag = def->flag;
|
||||
|
||||
ch->fvalue = def->fvalue;
|
||||
ch->ivalue = def->ivalue;
|
||||
|
||||
|
|
|
@ -162,7 +162,6 @@ BrushChannelType brush_builtin_channels[] = {
|
|||
#include "brush_channel_define.h"
|
||||
};
|
||||
|
||||
//BRUSH_INVERT_TO_SCRAPE_FILL
|
||||
/* clang-format on */
|
||||
const int brush_builtin_channel_len = ARRAY_SIZE(brush_builtin_channels);
|
||||
|
||||
|
@ -263,6 +262,14 @@ static BrushSettingsMap brush_settings_map[] = {
|
|||
DEF(secondary_rgb, secondary_color, FLOAT3, FLOAT3)
|
||||
DEF(vcol_boundary_factor, vcol_boundary_factor, FLOAT, FLOAT)
|
||||
DEF(vcol_boundary_exponent, vcol_boundary_exponent, FLOAT, FLOAT)
|
||||
DEF(cloth_deform_type, cloth_deform_type, INT, INT)
|
||||
DEF(cloth_simulation_area_type, cloth_simulation_area_type, INT, INT)
|
||||
DEF(cloth_force_falloff_type, cloth_force_falloff_type, INT, INT)
|
||||
DEF(cloth_mass, cloth_mass, FLOAT, FLOAT)
|
||||
DEF(cloth_damping, cloth_damping, FLOAT, FLOAT)
|
||||
DEF(cloth_sim_limit, cloth_sim_limit, FLOAT, FLOAT)
|
||||
DEF(cloth_sim_falloff, cloth_sim_falloff, FLOAT, FLOAT)
|
||||
DEF(cloth_constraint_softbody_strength, cloth_constraint_softbody_strength, FLOAT, FLOAT)
|
||||
};
|
||||
|
||||
static const int brush_settings_map_len = ARRAY_SIZE(brush_settings_map);
|
||||
|
@ -316,6 +323,8 @@ BrushFlagMap brush_flags_map[] = {
|
|||
DEF(flag, invert_to_scrape_fill, BRUSH_INVERT_TO_SCRAPE_FILL)
|
||||
DEF(flag2, use_multiplane_scrape_dynamic, BRUSH_MULTIPLANE_SCRAPE_DYNAMIC)
|
||||
DEF(flag2, show_multiplane_scrape_planes_preview, BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW)
|
||||
DEF(flag, use_persistent, BRUSH_PERSISTENT)
|
||||
DEF(flag, use_frontface, BRUSH_FRONTFACE)
|
||||
};
|
||||
|
||||
int brush_flags_map_len = ARRAY_SIZE(brush_flags_map);
|
||||
|
@ -598,8 +607,11 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
|
|||
|
||||
namestack_push(__func__);
|
||||
|
||||
bool setup_ui = false;
|
||||
|
||||
if (!brush->channels) {
|
||||
brush->channels = BKE_brush_channelset_create();
|
||||
setup_ui = true;
|
||||
}
|
||||
|
||||
BrushChannelSet *chset = brush->channels;
|
||||
|
@ -670,12 +682,105 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
|
|||
}
|
||||
case SCULPT_TOOL_SLIDE_RELAX:
|
||||
ADDCH(slide_deform_type);
|
||||
break;
|
||||
case SCULPT_TOOL_CLOTH:
|
||||
ADDCH(cloth_mass);
|
||||
ADDCH(cloth_damping);
|
||||
ADDCH(cloth_sim_limit);
|
||||
ADDCH(cloth_sim_falloff);
|
||||
ADDCH(cloth_deform_type);
|
||||
ADDCH(cloth_force_falloff_type);
|
||||
ADDCH(cloth_simulation_area_type);
|
||||
ADDCH(cloth_deform_type);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (setup_ui) {
|
||||
BKE_brush_channelset_ui_init(brush, tool);
|
||||
}
|
||||
namestack_pop();
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_brush_channelset_ui_init(Brush *brush, int tool)
|
||||
{
|
||||
namestack_push(__func__);
|
||||
|
||||
BrushChannelSet *chset = brush->channels;
|
||||
|
||||
#ifdef SHOWHDR
|
||||
# undef SHOWHDR
|
||||
#endif
|
||||
#ifdef SHOWWRK
|
||||
# undef SHOWPROPS
|
||||
#endif
|
||||
#ifdef SHOWALL
|
||||
# undef SHOWALL
|
||||
#endif
|
||||
|
||||
#ifdef SETFLAG_SAFE
|
||||
# undef SETFLAG_SAFE
|
||||
#endif
|
||||
|
||||
BrushChannel *ch;
|
||||
|
||||
#define SETFLAG_SAFE(idname, flag1) \
|
||||
if (ch = BRUSHSET_LOOKUP(chset, idname)) \
|
||||
ch->flag |= (flag1)
|
||||
|
||||
#define SHOWHDR(idname) SETFLAG_SAFE(idname, BRUSH_CHANNEL_SHOW_IN_HEADER)
|
||||
#define SHOWWRK(idname) SETFLAG_SAFE(idname, BRUSH_CHANNEL_SHOW_IN_WORKSPACE)
|
||||
#define SHOWALL(idname) \
|
||||
SETFLAG_SAFE(idname, BRUSH_CHANNEL_SHOW_IN_WORKSPACE | BRUSH_CHANNEL_SHOW_IN_HEADER)
|
||||
|
||||
SHOWALL(radius);
|
||||
SHOWALL(strength);
|
||||
SHOWALL(color);
|
||||
SHOWALL(secondary_color);
|
||||
SHOWALL(accumulate);
|
||||
|
||||
SHOWWRK(use_frontface);
|
||||
|
||||
SHOWWRK(autosmooth);
|
||||
SHOWWRK(topology_rake);
|
||||
SHOWWRK(normal_radius_factor);
|
||||
SHOWWRK(hardness);
|
||||
|
||||
switch (tool) {
|
||||
case SCULPT_TOOL_SCRAPE:
|
||||
case SCULPT_TOOL_FILL:
|
||||
SHOWWRK(plane_offset);
|
||||
SHOWWRK(invert_to_scrape_fill);
|
||||
SHOWWRK(area_radius_factor);
|
||||
break;
|
||||
case SCULPT_TOOL_CLAY:
|
||||
case SCULPT_TOOL_CLAY_STRIPS:
|
||||
case SCULPT_TOOL_CLAY_THUMB:
|
||||
case SCULPT_TOOL_FLATTEN:
|
||||
SHOWWRK(plane_offset);
|
||||
break;
|
||||
case SCULPT_TOOL_MULTIPLANE_SCRAPE:
|
||||
SHOWWRK(plane_offset);
|
||||
SHOWWRK(use_multiplane_scrape_dynamic);
|
||||
SHOWWRK(multiplane_scrape_angle);
|
||||
|
||||
break;
|
||||
case SCULPT_TOOL_LAYER:
|
||||
SHOWWRK(use_persistent);
|
||||
break;
|
||||
case SCULPT_TOOL_CLOTH:
|
||||
SHOWWRK(cloth_deform_type);
|
||||
SHOWWRK(cloth_force_falloff_type);
|
||||
SHOWWRK(cloth_simulation_area_type);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#undef SHOWALL
|
||||
#undef SHOWHDR
|
||||
#undef SHOWPROPS
|
||||
namestack_pop();
|
||||
}
|
||||
ATTR_NO_OPT void BKE_brush_builtin_create(Brush *brush, int tool)
|
||||
{
|
||||
namestack_push(__func__);
|
||||
|
@ -787,6 +892,10 @@ ATTR_NO_OPT void BKE_brush_builtin_create(Brush *brush, int tool)
|
|||
GETCH(strength)->fvalue = 1.0;
|
||||
GETCH(dyntopo_disabled)->ivalue = true;
|
||||
break;
|
||||
case SCULPT_TOOL_CLOTH:
|
||||
GETCH(radius)->mappings[BRUSH_MAPPING_PRESSURE].flag &= ~BRUSH_MAPPING_ENABLED;
|
||||
GETCH(strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &= ~BRUSH_MAPPING_ENABLED;
|
||||
break;
|
||||
default: {
|
||||
// implement me!
|
||||
// BKE_brush_channelset_free(chset);
|
||||
|
@ -796,6 +905,8 @@ ATTR_NO_OPT void BKE_brush_builtin_create(Brush *brush, int tool)
|
|||
}
|
||||
|
||||
namestack_pop();
|
||||
|
||||
BKE_brush_channelset_ui_init(brush, tool);
|
||||
}
|
||||
|
||||
void BKE_brush_init_toolsettings(Sculpt *sd)
|
||||
|
|
|
@ -572,7 +572,7 @@ static bool buttons_context_path(
|
|||
path->len++;
|
||||
}
|
||||
/* No pinned root, use scene as initial root. */
|
||||
else if (mainb != BCONTEXT_TOOL) {
|
||||
else if (!ELEM(mainb, BCONTEXT_TOOL, BCONTEXT_BRUSH_EDITOR)) {
|
||||
RNA_id_pointer_create(&scene->id, &path->ptr[0]);
|
||||
path->len++;
|
||||
|
||||
|
@ -613,6 +613,7 @@ static bool buttons_context_path(
|
|||
case BCONTEXT_COLLECTION: /* This is for Line Art collection flags */
|
||||
found = buttons_context_path_collection(C, path, window);
|
||||
break;
|
||||
case BCONTEXT_BRUSH_EDITOR:
|
||||
case BCONTEXT_TOOL:
|
||||
found = true;
|
||||
break;
|
||||
|
@ -871,7 +872,7 @@ int /*eContextResult*/ buttons_context(const bContext *C,
|
|||
return CTX_RESULT_MEMBER_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (sbuts->mainb == BCONTEXT_TOOL) {
|
||||
if (ELEM(sbuts->mainb, BCONTEXT_TOOL, BCONTEXT_BRUSH_EDITOR)) {
|
||||
return CTX_RESULT_MEMBER_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
@ -1184,7 +1185,7 @@ int /*eContextResult*/ buttons_context(const bContext *C,
|
|||
static bool buttons_panel_context_poll(const bContext *C, PanelType *UNUSED(pt))
|
||||
{
|
||||
SpaceProperties *sbuts = CTX_wm_space_properties(C);
|
||||
return sbuts->mainb != BCONTEXT_TOOL;
|
||||
return !ELEM(sbuts->mainb, BCONTEXT_TOOL, BCONTEXT_BRUSH_EDITOR);
|
||||
}
|
||||
|
||||
static void buttons_panel_context_draw(const bContext *C, Panel *panel)
|
||||
|
|
|
@ -178,6 +178,10 @@ int ED_buttons_tabs_list(SpaceProperties *sbuts, short *context_tabs_array)
|
|||
context_tabs_array[length] = BCONTEXT_TOOL;
|
||||
length++;
|
||||
}
|
||||
if (sbuts->pathflag & (1 << BCONTEXT_BRUSH_EDITOR)) {
|
||||
context_tabs_array[length] = BCONTEXT_BRUSH_EDITOR;
|
||||
length++;
|
||||
}
|
||||
if (length != 0) {
|
||||
context_tabs_array[length] = -1;
|
||||
length++;
|
||||
|
@ -305,6 +309,8 @@ static const char *buttons_main_region_context_string(const short mainb)
|
|||
return "bone_constraint";
|
||||
case BCONTEXT_TOOL:
|
||||
return "tool";
|
||||
case BCONTEXT_BRUSH_EDITOR:
|
||||
return "brush_editor";
|
||||
}
|
||||
|
||||
/* All the cases should be handled. */
|
||||
|
@ -359,7 +365,7 @@ static bool property_search_for_context(const bContext *C, ARegion *region, Spac
|
|||
{
|
||||
const char *contexts[2] = {buttons_main_region_context_string(sbuts->mainb), NULL};
|
||||
|
||||
if (sbuts->mainb == BCONTEXT_TOOL) {
|
||||
if (sbuts->mainb == BCONTEXT_TOOL || sbuts->mainb == BCONTEXT_BRUSH_EDITOR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -372,7 +378,7 @@ static void property_search_move_to_next_tab_with_results(SpaceProperties *sbuts
|
|||
const int tabs_len)
|
||||
{
|
||||
/* As long as all-tab search in the tool is disabled in the tool context, don't move from it. */
|
||||
if (sbuts->mainb == BCONTEXT_TOOL) {
|
||||
if (sbuts->mainb == BCONTEXT_TOOL || sbuts->mainb == BCONTEXT_BRUSH_EDITOR) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -513,6 +519,9 @@ static void buttons_main_region_layout(const bContext *C, ARegion *region)
|
|||
if (sbuts->mainb == BCONTEXT_TOOL) {
|
||||
ED_view3d_buttons_region_layout_ex(C, region, "Tool");
|
||||
}
|
||||
else if (sbuts->mainb == BCONTEXT_BRUSH_EDITOR) {
|
||||
ED_view3d_buttons_region_layout_ex(C, region, "Tool");
|
||||
}
|
||||
else {
|
||||
buttons_main_region_layout_properties(C, sbuts, region);
|
||||
}
|
||||
|
@ -597,7 +606,7 @@ static void buttons_header_region_message_subscribe(const wmRegionMessageSubscri
|
|||
WM_msg_subscribe_rna_anon_prop(mbus, ViewLayer, name, &msg_sub_value_region_tag_redraw);
|
||||
}
|
||||
|
||||
if (sbuts->mainb == BCONTEXT_TOOL) {
|
||||
if (ELEM(sbuts->mainb, BCONTEXT_TOOL, BCONTEXT_BRUSH_EDITOR)) {
|
||||
WM_msg_subscribe_rna_anon_prop(mbus, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
|
||||
}
|
||||
}
|
||||
|
@ -786,6 +795,7 @@ static void buttons_area_listener(const wmSpaceTypeListenerParams *params)
|
|||
case NC_BRUSH:
|
||||
buttons_area_redraw(area, BCONTEXT_TEXTURE);
|
||||
buttons_area_redraw(area, BCONTEXT_TOOL);
|
||||
buttons_area_redraw(area, BCONTEXT_BRUSH_EDITOR);
|
||||
sbuts->preview = 1;
|
||||
break;
|
||||
case NC_TEXTURE:
|
||||
|
|
|
@ -1351,9 +1351,16 @@ void ED_view3d_buttons_region_layout_ex(const bContext *C,
|
|||
case CTX_MODE_POSE:
|
||||
ARRAY_SET_ITEMS(contexts, ".posemode");
|
||||
break;
|
||||
case CTX_MODE_SCULPT:
|
||||
ARRAY_SET_ITEMS(contexts, ".paint_common", ".sculpt_mode");
|
||||
case CTX_MODE_SCULPT: {
|
||||
SpaceProperties *sbuts = CTX_wm_space_properties(C);
|
||||
if (sbuts && sbuts->mainb == BCONTEXT_BRUSH_EDITOR) {
|
||||
ARRAY_SET_ITEMS(contexts, ".paint_common", ".brush_editor");
|
||||
}
|
||||
else {
|
||||
ARRAY_SET_ITEMS(contexts, ".paint_common", ".sculpt_mode");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CTX_MODE_PAINT_WEIGHT:
|
||||
ARRAY_SET_ITEMS(contexts, ".paint_common", ".weightpaint");
|
||||
break;
|
||||
|
|
|
@ -53,7 +53,8 @@ typedef struct BrushChannel {
|
|||
float vector[4];
|
||||
BrushMapping mappings[5]; // should always be BRUSH_MAPPING_MAX
|
||||
|
||||
int type, flag;
|
||||
short type, ui_order;
|
||||
int flag;
|
||||
} BrushChannel;
|
||||
|
||||
typedef struct BrushChannelSet {
|
||||
|
@ -95,7 +96,9 @@ enum {
|
|||
BRUSH_CHANNEL_NO_MAPPINGS = 1 << 2,
|
||||
BRUSH_CHANNEL_UI_EXPANDED = 1 << 3,
|
||||
BRUSH_CHANNEL_APPLY_MAPPING_TO_ALPHA = 1 << 4,
|
||||
BRUSH_CHANNEL_COLOR = 1 << 5
|
||||
BRUSH_CHANNEL_COLOR = 1 << 5,
|
||||
BRUSH_CHANNEL_SHOW_IN_WORKSPACE = 1 << 6,
|
||||
BRUSH_CHANNEL_SHOW_IN_HEADER = 1 << 7
|
||||
};
|
||||
|
||||
// BrushChannelType->type
|
||||
|
|
|
@ -230,6 +230,7 @@ typedef enum eSpaceButtons_Context {
|
|||
BCONTEXT_SHADERFX = 15,
|
||||
BCONTEXT_OUTPUT = 16,
|
||||
BCONTEXT_COLLECTION = 17,
|
||||
BCONTEXT_BRUSH_EDITOR = 18,
|
||||
|
||||
/* Keep last. */
|
||||
BCONTEXT_TOT,
|
||||
|
|
|
@ -378,6 +378,11 @@ void RNA_def_brush_channel(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Value", "Current value");
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
|
||||
prop = RNA_def_property(srna, "ui_order", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, "BrushChannel", "ui_order");
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
RNA_def_property_ui_text(prop, "Ordering", "Order of brush channel in panels and the header");
|
||||
|
||||
prop = RNA_def_property(srna, "int_value", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, "BrushChannel", "ivalue");
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
|
@ -421,6 +426,16 @@ void RNA_def_brush_channel(BlenderRNA *brna)
|
|||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
RNA_def_property_ui_text(prop, "Inherit", "Inherit from scene defaults");
|
||||
|
||||
prop = RNA_def_property(srna, "show_in_header", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, "BrushChannel", "flag", BRUSH_CHANNEL_SHOW_IN_HEADER);
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
RNA_def_property_ui_text(prop, "In Header", "Show in header");
|
||||
|
||||
prop = RNA_def_property(srna, "show_in_workspace", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, "BrushChannel", "flag", BRUSH_CHANNEL_SHOW_IN_WORKSPACE);
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
RNA_def_property_ui_text(prop, "In Workspace", "Show in workspace");
|
||||
|
||||
prop = RNA_def_property(srna, "is_color", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, "BrushChannel", "flag", BRUSH_CHANNEL_COLOR);
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
|
|
|
@ -458,6 +458,7 @@ const EnumPropertyItem rna_enum_clip_editor_mode_items[] = {
|
|||
* but helps for context-less access (e.g. doc, i18n...). */
|
||||
static const EnumPropertyItem buttons_context_items[] = {
|
||||
{BCONTEXT_TOOL, "TOOL", ICON_TOOL_SETTINGS, "Tool", "Active Tool and Workspace settings"},
|
||||
{BCONTEXT_BRUSH_EDITOR, "BRUSH_EDITOR", ICON_BRUSH_DATA, "Brush", "Brush Settings"},
|
||||
{BCONTEXT_SCENE, "SCENE", ICON_SCENE_DATA, "Scene", "Scene Properties"},
|
||||
{BCONTEXT_RENDER, "RENDER", ICON_SCENE, "Render", "Render Properties"},
|
||||
{BCONTEXT_OUTPUT, "OUTPUT", ICON_OUTPUT, "Output", "Output Properties"},
|
||||
|
|
Loading…
Reference in New Issue