Compare commits

...

22 Commits

Author SHA1 Message Date
c88597a7c5 Merge branch 'master' into temp-sculpt-brush-channel 2022-11-13 19:24:44 -08:00
e59ebfef3c Merge branch 'master' into temp-sculpt-brush-channel 2022-11-08 09:13:59 -08:00
fe7088c99f Merge remote-tracking branch 'origin' into temp-sculpt-brush-channel 2022-10-22 16:33:47 -07:00
b5a69061e7 Merge branch 'master' into temp-sculpt-brush-channel 2022-10-22 16:33:25 -07:00
c51beeb56a Merge branch 'master' into temp-sculpt-brush-channel 2022-08-17 08:55:39 -07:00
c8fff5d50b temp-sculpt-brush-channel: Enable input mapping for strength 2022-08-16 17:18:09 -07:00
269adfdf23 temp-sculpt-brush-channel: Refactor MAKE_PROP macro
* MAKE_PROP macro now defines which properties belong to
  which brush tools and where in the UI (workspace, header,
  right-click menu) they are visible in.
* Added all brush RNA properties to brush_channel_define.h,
  still have to add the code for evaluating input mappings
  (except radius). NOTE: the categories are a work in progress.
* The brush channel API now takes a ePaintMode in addition to a
  tool integer.
* Added a second Brush Settings panel that's dynamically generated
  from the ui visiblity flags and categories.
* Adding support for PROP_BOOLEAN to the RNA wrapper.
2022-08-16 16:59:23 -07:00
83cefb3134 Merge remote-tracking branch 'origin' into temp-sculpt-brush-channel 2022-08-16 00:59:10 -07:00
0e4854604f Merge branch 'master' into temp-sculpt-brush-channel 2022-08-15 17:24:51 -07:00
c5d508c362 temp-sculpt-brush-channel: Implement new input mapping UI 2022-08-14 14:02:58 -07:00
0940b35755 temp-sculpt-brush-channel: Fix broken BrushMapping custom curves 2022-08-10 16:31:38 -07:00
efaade3b30 temp-sculpt-brush-channel: Add missing RNA callbacks
the RNA properties for controlling brush property visibility
now properly sets their XXX_USER_SET flags.

Also rewrote a few comments.
2022-08-10 16:22:58 -07:00
4c3cf3ad17 temp-sculpt-brush-channel: Better unified property api and api cleanup
* There are now API functions to directly evaluate brush channel
  values from their underlying RNA.
* New API functions to evaluate unified channels; currently used
  in BKE_brush_size_get/set and BKE_brush_alpha_get/set.
* Removed _channelset_ from API functions that operator on a higher
  level.  So BKE_brush_channelset_rna_int_get turned into
  BKE_brush_int_get, similar for BKE_brush_int_get_unified.
2022-08-10 16:11:05 -07:00
1ef3c59beb tmep-sculpt-brush-channel: Fix unified size 2022-08-09 16:18:59 -07:00
f913f0cb42 temp-sculpt-brush-channel: Improve implementation
* StrokeCache now has a BrushChannelSet with final
  channel values after taking input mappings and
  unified/inheritance flags into account.
2022-08-09 15:44:53 -07:00
aa2a2e18c4 Merge branch 'master' into temp-sculpt-brush-channel 2022-08-09 13:08:40 -07:00
b4cb9b9b9f temp-sculpt-brush-channel: Fix RNA bugs and add UI 2022-08-08 02:35:34 -07:00
ba281da583 Merge branch 'master' into temp-sculpt-brush-channel 2022-08-07 18:13:23 -07:00
ecf5f2b118 temp-sculpt-brush-channel: Commit current code 2022-08-06 16:28:10 -07:00
45b0332034 temp-sculpt-brush-channel: Flesh out rna backend a bit 2022-08-05 16:36:00 -07:00
272df645d6 Merge branch 'master' into temp-sculpt-brush-channel 2022-08-05 15:34:31 -07:00
8e8d9779b7 temp-sculpt-brush-channel: Brush channel system
This branch is slimmed down version of sculpt-dev's
BrushChannel API.  The main differences are:

* BrushChannel wraps RNA properties instead of
  being a fully-formed property system on its
  own.  The exception are BrushCurve properties which
  don't exist in RNA.
* The brush command queue has been removed.
* BrushChannels still store data (so the .fvalue
  .ivalue .vector .curve members are still there),
  but except for curves these are mere runtime
  caches filled in from RNA.
* brush_channel_define.h still exists but no longer has
  all the property definitions; instead it merely defines
  which RNA properties are brush properties.
* There is no global CurveMapping cache, that's really
  only needed for the command queue sytem.
* Got rid of the awkward BRUSHSET_ macros.  Instead,
  brush channel API methods that takes channel names
  are prefixed with _ and wrapped in unprefixed versions
  that do the compile-time name checking.

Note that this is a work in progress
2022-08-02 16:40:26 -07:00
43 changed files with 4955 additions and 326 deletions

View File

@@ -4672,18 +4672,26 @@ def km_curve(params):
def radial_control_properties(paint, prop, secondary_prop, secondary_rotation=False, color=False, zoom=False):
brush_path = 'tool_settings.' + paint + '.brush'
unified_path = 'tool_settings.unified_paint_settings'
unified_path = 'tool_settings.unified_properties'
channel_path = 'tool_settings.unified_channels'
rotation = 'mask_texture_slot.angle' if secondary_rotation else 'texture_slot.angle'
def idprop(key):
return '["%s"]' % key
def rnaprop(key):
return "." + key
return {
"properties": [
("data_path_primary", brush_path + '.' + prop),
("data_path_secondary", unified_path + '.' + prop if secondary_prop else ''),
("use_secondary", unified_path + '.' + secondary_prop if secondary_prop else ''),
("rotation_path", brush_path + '.' + rotation),
("color_path", brush_path + '.cursor_color_add'),
("fill_color_path", brush_path + '.color' if color else ''),
("fill_color_override_path", unified_path + '.color' if color else ''),
("fill_color_override_test_path", unified_path + '.use_unified_color' if color else ''),
("data_path_secondary", unified_path + idprop(prop) if secondary_prop else ''),
("use_secondary", channel_path + idprop(prop) + '.unified' if secondary_prop else ''),
("rotation_path", brush_path + rnaprop(rotation)),
("color_path", brush_path + rnaprop('cursor_color_add')),
("fill_color_path", brush_path + rnaprop('color') if color else ''),
("fill_color_override_path", unified_path + idprop('color') if color else ''),
("fill_color_override_test_path", channel_path + idprop('color') + '.unified' if color else ''),
("zoom_path", 'space_data.zoom' if zoom else ''),
("image_id", brush_path + ''),
("secondary_tex", secondary_rotation),

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,7 @@ from bpy.types import (
from bl_ui.properties_paint_common import (
UnifiedPaintPanel,
brush_basic_texpaint_settings,
brush_settings_channels,
)
from bl_ui.properties_grease_pencil_common import (
AnnotationDataPanel,
@@ -236,27 +237,38 @@ class _draw_tool_settings_context_mode:
if size_owner.use_locked_size == 'SCENE':
size = "unprojected_radius"
UnifiedPaintPanel.prop_unified(
layout,
context,
brush,
size,
pressure_name="use_pressure_size",
unified_name="use_unified_size",
text="Radius",
slider=True,
header=True,
)
if 0:
UnifiedPaintPanel.prop_unified(
layout,
context,
brush,
size,
pressure_name="use_pressure_size",
unified_name="use_unified_size",
text="Radius",
slider=True,
header=True,
)
else:
UnifiedPaintPanel.channel_unified(
layout,
context,
brush,
size,
text="Radius",
slider=True,
header=True,
)
# strength, use_strength_pressure
pressure_name = "use_pressure_strength" if capabilities.has_strength_pressure else None
UnifiedPaintPanel.prop_unified(
UnifiedPaintPanel.channel_unified(
layout,
context,
brush,
"strength",
pressure_name=pressure_name,
unified_name="use_unified_strength",
#pressure_name=pressure_name,
#unified_name="use_unified_strength",
text="Strength",
header=True,
)

View File

@@ -20,6 +20,7 @@ from bl_ui.properties_paint_common import (
brush_settings,
brush_settings_advanced,
draw_color_settings,
brush_settings_channels,
)
from bl_ui.utils import PresetPanel
@@ -345,6 +346,29 @@ class VIEW3D_PT_tools_brush_select(Panel, View3DPaintBrushPanel, BrushSelectPane
bl_context = ".paint_common"
bl_label = "Brushes"
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
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
ui_editing = context.tool_settings.brush_editor_mode
brush_settings_channels(layout.column(), context, brush, popover=self.is_popover, ui_editing=ui_editing)
# TODO, move to space_view3d.py
class VIEW3D_PT_tools_brush_settings(Panel, View3DPaintBrushPanel):
@@ -365,6 +389,8 @@ class VIEW3D_PT_tools_brush_settings(Panel, View3DPaintBrushPanel):
settings = self.paint_settings(context)
brush = settings.brush
layout.prop(context.tool_settings, "brush_editor_mode")
brush_settings(layout.column(), context, brush, popover=self.is_popover)
@@ -421,6 +447,55 @@ class VIEW3D_PT_tools_brush_color(Panel, View3DPaintPanel):
draw_color_settings(context, layout, brush, color_type=not context.vertex_paint_object)
class VIEW3D_PT_tools_persistent_base_channels(Panel, View3DPaintPanel):
bl_context = ".paint_common"
#bl_parent_id = "VIEW3D_PT_tools_brush_settings_channels"
bl_label = "Persistent Base"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
settings = cls.paint_settings(context)
if not settings:
return False
brush = settings.brush
ch = UnifiedPaintPanel.get_channel(context, brush, "use_persistent")
capabilities = brush.sculpt_capabilities
ok = context.mode == "SCULPT"
ok = ok and ch and ch.show_in_workspace
ok = ok or capabilities.has_persistence
return ok
def draw(self, context):
layout = self.layout
settings = self.paint_settings(context)
brush = settings.brush
sculpt = context.tool_settings.sculpt
UnifiedPaintPanel.channel_unified(layout,
context,
brush,
"use_persistent",
#text="Weight By Face Area",
ui_editing=False)
layout.operator("sculpt.set_persistent_base")
if sculpt.has_persistent_base():
layout.label(text="Persistent base exists")
else:
layout.label(text="No persisent base data")
class VIEW3D_PT_tools_brush_swatches_channels(Panel, View3DPaintPanel, ColorPalettePanel):
bl_context = ".paint_common"
bl_parent_id = "VIEW3D_PT_tools_brush_settings_channels"
bl_label = "Color Palette"
bl_options = {'DEFAULT_CLOSED'}
class VIEW3D_PT_tools_brush_swatches(Panel, View3DPaintPanel, ColorPalettePanel):
bl_context = ".paint_common"
@@ -2450,6 +2525,9 @@ classes = (
VIEW3D_PT_tools_grease_pencil_brush_vertex_color,
VIEW3D_PT_tools_grease_pencil_brush_vertex_palette,
VIEW3D_PT_tools_grease_pencil_brush_vertex_falloff,
VIEW3D_PT_tools_brush_settings_channels,
VIEW3D_PT_tools_persistent_base_channels,
VIEW3D_PT_tools_brush_swatches_channels,
)
if __name__ == "__main__": # only for live edit.

View File

@@ -88,6 +88,7 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_workspace_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_world_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_xr_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_brush_channel_types.h
)
set(SRC_DNA_DEFAULTS_INC

View File

@@ -99,7 +99,11 @@ float BKE_brush_curve_strength_clamped(const struct Brush *br, float p, float le
* Uses the brush curve control to find a strength value.
*/
float BKE_brush_curve_strength(const struct Brush *br, float p, float len);
float BKE_brush_curve_strength_ex(int curve_preset,
const struct CurveMapping *curve,
float p,
const float len,
const bool invert);
/* Sampling. */
/**
@@ -168,7 +172,7 @@ void BKE_brush_weight_set(const struct Scene *scene, struct Brush *brush, float
bool BKE_brush_use_locked_size(const struct Scene *scene, const struct Brush *brush);
bool BKE_brush_use_alpha_pressure(const struct Brush *brush);
bool BKE_brush_use_size_pressure(const struct Brush *brush);
bool BKE_brush_use_size_pressure(const struct Scene *scene, const struct Brush *brush);
bool BKE_brush_sculpt_has_secondary_color(const struct Brush *brush);

View File

@@ -0,0 +1,330 @@
#pragma once
#pragma once
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*/
/** \file
* \ingroup bke
* \brief New brush engine for sculpt
*/
#include "BKE_paint.h"
#include "RNA_types.h"
/*
The new brush engine is based on command lists. These lists
will eventually be created by a node editor.
Key is the concept of BrushChannels. A brush channel is
a logical parameter with a type, input settings (e.g. pen),
a falloff curve, etc.
Brush channels have a concept of inheritance. There is a
BrushChannelSet (collection of channels) in ToolSettings,
and in Brush (Brush.channels and ToolSettings.unified_channels).
Unified properties are stored in ToolSettings.unified_properties
as IDProperties.
Note: Many API functions start with an underscore. These functions
support compile-time property name checking. This is done via macros;
if you call the function without the underscore you'll go through a macro
that will transform the property name into a global variable. If that
global variable does not exist you'll get an error.
For example `BKE_brush_channelset_lookup(chset, size)` compiles down to
`_BKE_brush_channelset_lookup(chset, BRUSH_BUILTIN_size)`
*/
#include "BLI_compiler_compat.h"
#include "DNA_brush_channel_types.h"
#include "DNA_texture_types.h"
#ifdef __cplusplus
extern "C" {
#endif
struct BrushChannel;
struct BlendWriter;
struct StructRNA;
struct BlendDataReader;
struct BlendLibReader;
struct ID;
struct BlendExpander;
struct Brush;
struct Sculpt;
struct LibraryForeachIDData;
struct ToolSettings;
struct UnifiedPaintSettings;
#define make_builtin_ch_name(idname) BRUSH_BUILTIN_##idname
typedef void (*BrushChannelIDCallback)(void *userdata,
struct ID *id,
BrushChannelSet *chset,
BrushChannel *ch);
/* TODO: clean up this struct */
typedef struct BrushMappingDef {
int curve;
bool enabled;
bool inv;
bool inherit;
float min, max;
int blendmode;
float func_cutoff;
float factor; // if 0, will default to 1.0
bool no_default;
} BrushMappingDef;
typedef struct BrushMappingPreset {
// must match order of BRUSH_MAPPING_XXX enums
struct BrushMappingDef pressure, xtilt, ytilt, angle, speed, random, stroke_t;
} BrushMappingPreset;
/* input mapping data */
typedef struct BrushMappingData {
float pressure, xtilt, ytilt, angle, speed, random, stroke_t;
} BrushMappingData;
#define MAX_BRUSH_ENUM_DEF 32
/* copy of PropertyEnumItem only with static char arrays instead of pointers
for strings */
typedef struct BrushEnumDef {
int value;
const char identifier[64];
char icon[32]; // don't forget when writing literals that icon here is a string, not an int!
const char name[64];
const char description[512];
} BrushEnumDef;
typedef struct BrushUIFlagDef {
int tools[100];
} BrushUIFlagDef;
/*
Defines a brush channel. Includes limits, UI data,
default values, etc.
*/
typedef struct BrushChannelType {
char uiname[128], idname[64], tooltip[512], category[128];
float min, max, soft_min, soft_max;
BrushMappingPreset mappings;
BrushUIFlagDef paint_mode_uiflags[PAINT_MODE_INVALID];
int type, flag, ui_flag;
int subtype;
bool user_defined; /* this is a user-defined channel; currently unused */
} BrushChannelType;
BrushChannelSet *BKE_brush_channelset_create();
void BKE_brush_channelset_free(BrushChannelSet *chset);
void BKE_brush_channelset_ensure_channels(BrushChannelSet *chset, ePaintMode mode, int tool);
/* Calls BKE_brush_channelset_ensure_channels for every paint mode with a tool inside of brush. */
void BKE_brush_channelset_ensure_all_modes(struct Brush *brush);
void BKE_brush_channelset_blend_read(BrushChannelSet *chset, struct BlendDataReader *reader);
void BKE_brush_channelset_blend_write(BrushChannelSet *chset, struct BlendWriter *writer);
/*
set up static type checker for BKE_brush_channel_XXX name-checking macros
*/
#define BRUSH_CHANNEL_DEFINE_EXTERNAL
#include "intern/brush_channel_define.h"
#undef BRUSH_CHANNEL_DEFINE_EXTERNAL
/* Remember that calling these without the leading underscore and with no
* quotes around idname will perform compile-time name checking.
*/
BrushChannel *_BKE_brush_channelset_ensure(BrushChannelSet *chset, const char *idname);
BrushChannel *_BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *idname);
bool _BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname);
/* Flags all channels with BRUSH_CHANNEL_NEEDS_EVALUATE so we
reevaluate values from RNA */
void BKE_brush_channelset_begin(BrushChannelSet *chset, BrushChannelType *type);
/* Evaluates a channel, taking unified channel inheritance into account. Result
* is cached in channel, to force update call BKE_brush_channelset_mark_update. */
float _BKE_brush_eval_float(const struct Brush *br,
const struct Scene *scene,
const char *idname,
BrushMappingData *mapping);
int _BKE_brush_eval_int(const struct Brush *br,
const struct Scene *scene,
const char *idname,
BrushMappingData *mapping);
/* Get and set internal cached values in brush channels. */
float _BKE_brush_channelset_float_get(BrushChannelSet *chset, const char *idname);
void _BKE_brush_channelset_float_set(BrushChannelSet *chset, const char *idname, float f);
int _BKE_brush_channelset_int_get(BrushChannelSet *chset, const char *idname);
void _BKE_brush_channelset_int_set(BrushChannelSet *chset, const char *idname, int i);
/* Get and set channels' real values from RNA. ID can be either a Brush or a Scene.
* If a Scene the unified properties in Scene.toolsettings->unified_properties
* will be used.
*/
int _BKE_brush_int_get(const struct ID *id, BrushChannelSet *chset, const char *idname);
void _BKE_brush_int_set(struct ID *id, BrushChannelSet *chset, const char *idname, int i);
float _BKE_brush_float_get(const struct ID *id, BrushChannelSet *chset, const char *idname);
void _BKE_brush_float_set(struct ID *id, BrushChannelSet *chset, const char *idname, float f);
int _BKE_brush_int_get_unified(const struct Scene *scene,
const struct Brush *brush,
const char *idname);
void _BKE_brush_int_set_unified(struct Scene *scene,
struct Brush *brush,
const char *idname,
int i);
float _BKE_brush_float_get_unified(const struct Scene *scene,
const struct Brush *brush,
const char *idname);
void _BKE_brush_float_set_unified(struct Scene *scene,
struct Brush *brush,
const char *idname,
float i);
BrushChannelSet *BKE_brush_channelset_copy(BrushChannelSet *chset);
/* Create a (copied) final brush channel set with all inheritance and unified flags
and input mappings taken into account. */
BrushChannelSet *BKE_brush_channelset_create_final(const struct Brush *brush,
const struct Scene *scene,
BrushMappingData *mapdata);
BLI_INLINE const char *BKE_brush_mapping_type_to_typename(eBrushMappingType type)
{
switch (type) {
case BRUSH_MAPPING_PRESSURE:
return "PRESSURE";
case BRUSH_MAPPING_ANGLE:
return "ANGLE";
case BRUSH_MAPPING_SPEED:
return "SPEED";
case BRUSH_MAPPING_XTILT:
return "XTILT";
case BRUSH_MAPPING_YTILT:
return "YTILT";
case BRUSH_MAPPING_RANDOM:
return "RANDOM";
case BRUSH_MAPPING_STROKE_T:
return "DISTANCE";
default:
return "Error";
}
}
const char *BKE_brush_channel_category_get(BrushChannel *ch);
const void BKE_brush_channel_category_set(BrushChannel *ch, const char *category);
bool BKE_brush_channel_inherits(const struct Brush *brush,
const struct ToolSettings *tool_settings,
BrushChannel *ch);
BrushChannelSet *BKE_brush_channelset_get_final(const struct Brush *brush,
const struct ToolSettings *tool_settings);
void BKE_brush_channelset_toolsettings_init(struct ToolSettings *ts);
/* Get rna path for brush channel. Calling code should call MEM_SAFE_FREE on result. */
char *BKE_brush_channel_rna_path(const ID *owner, const BrushChannel *ch);
void _BKE_brush_channelset_mark_update(BrushChannelSet *chset, const char *idname);
#define BKE_brush_channelset_mark_update(chset, idname) \
_BKE_brush_channelset_mark_update(chset, make_builtin_ch_name(idname))
/* Ensure BrushChannel.ui_order for all the channels inside chset are rational, i.e.
* they go from 0 to chset->channels_num-1.
*/
void BKE_brush_channelset_ui_order_check(BrushChannelSet *chset);
void BKE_brush_channelset_ui_order_move(BrushChannelSet *chset,
BrushChannel *ch,
int uiflag,
int dir);
bool _BKE_brush_mapping_enabled(const struct Scene *scene,
const struct Brush *brush,
const char *idname,
eBrushMappingType mapping_type);
#define BKE_brush_mapping_enabled(scene, brush, idname, mapping_type) \
_BKE_brush_mapping_enabled(scene, brush, make_builtin_ch_name(idname), mapping_type)
#if 0
/* Call when active brush changes. */
void BKE_brush_channels_update(struct Brush *active_brush, struct Scene *scene);
#endif
#define BKE_brush_channelset_ensure(chset, idname) \
_BKE_brush_channelset_ensure(chset, make_builtin_ch_name(idname))
#define BKE_brush_channelset_lookup(chset, channel) \
_BKE_brush_channelset_lookup(chset, make_builtin_ch_name(channel))
#define BKE_brush_channelset_has(chset, channel) \
_BKE_brush_channelset_has(chset, make_builtin_ch_name(channel))
#define BKE_brush_int_set_unified(scene, brush, idname, i) \
_BKE_brush_int_set_unified(scene, brush, make_builtin_ch_name(idname), i)
#define BKE_brush_int_get_unified(scene, brush, idname) \
_BKE_brush_int_get_unified(scene, brush, make_builtin_ch_name(idname))
#define BKE_brush_float_set_unified(scene, brush, idname, f) \
_BKE_brush_float_set_unified(scene, brush, make_builtin_ch_name(idname), f)
#define BKE_brush_float_get_unified(scene, brush, idname) \
_BKE_brush_float_get_unified(scene, brush, make_builtin_ch_name(idname))
#define BKE_brush_eval_float(br, scene, channel, mapdata) \
_BKE_brush_eval_float(br, scene, make_builtin_ch_name(channel), mapdata)
#define BKE_brush_eval_int(br, scene, channel, mapdata) \
_BKE_brush_eval_int(br, scene, make_builtin_ch_name(channel), mapdata)
#define BKE_brush_channelset_float_get(chset, idname) \
_BKE_brush_channelset_float_get(chset, make_builtin_ch_name(idname))
#define BKE_brush_channelset_float_set(chset, idname, f) \
_BKE_brush_channelset_float_set(chset, make_builtin_ch_name(idname), f)
#define BKE_brush_channelset_int_get(chset, idname) \
_BKE_brush_channelset_int_get(chset, make_builtin_ch_name(idname))
#define BKE_brush_channelset_int_set(chset, idname, f) \
_BKE_brush_channelset_int_set(chset, make_builtin_ch_name(idname), f)
#define BKE_brush_int_get(id, chset, idname) \
_BKE_brush_int_get(id, chset, make_builtin_ch_name(idname))
#define BKE_brush_int_set(id, chset, idname, f) \
_BKE_brush_int_set(id, chset, make_builtin_ch_name(idname), f)
#define BKE_brush_float_get(id, chset, idname) \
_BKE_brush_float_get(id, chset, make_builtin_ch_name(idname))
#define BKE_brush_float_set(id, chset, idname, f) \
_BKE_brush_float_set(id, chset, make_builtin_ch_name(idname), f)
/* Disable optimization for a function (for debugging use only!)*/
#ifdef __clang__
# define ATTR_NO_OPT __attribute__((optnone))
#elif defined(_MSC_VER)
# define ATTR_NO_OPT __pragma(optimize("", off))
#elif defined(__GNUC__)
# define ATTR_NO_OPT __attribute__((optimize("O0")))
#else
# define ATTR_NO_OPT
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -86,6 +86,7 @@ set(SRC
intern/blender_user_menu.c
intern/blendfile.c
intern/blendfile_link_append.c
intern/brush_channel.cc
intern/boids.c
intern/bpath.c
intern/brush.cc
@@ -341,6 +342,7 @@ set(SRC
BKE_boids.h
BKE_bpath.h
BKE_brush.h
BKE_brush_channel.h
BKE_bvhutils.h
BKE_cachefile.h
BKE_callbacks.h
@@ -500,6 +502,7 @@ set(SRC
nla_private.h
particle_private.h
tracking_private.h
intern/brush_channel_define.h
intern/CCGSubSurf.h
intern/CCGSubSurf_inline.h
intern/CCGSubSurf_intern.h

View File

@@ -21,6 +21,7 @@
#include "BKE_bpath.h"
#include "BKE_brush.h"
#include "BKE_brush_channel.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
@@ -34,6 +35,11 @@
#include "BKE_paint.h"
#include "BKE_texture.h"
#include "RNA_access.h"
#include "RNA_path.h"
#include "RNA_prototypes.h"
#include "RNA_types.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -54,6 +60,9 @@ static void brush_init_data(ID *id)
/* the default alpha falloff curve */
BKE_brush_curve_preset(brush, CURVE_PRESET_SMOOTH);
brush->channels = BKE_brush_channelset_create();
BKE_brush_channelset_ensure_channels(brush->channels, PAINT_MODE_INVALID, 0);
}
static void brush_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
@@ -100,6 +109,10 @@ static void brush_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, cons
brush_dst->curves_sculpt_settings = MEM_cnew(__func__, *(brush_src->curves_sculpt_settings));
}
if (brush_src->channels) {
brush_dst->channels = BKE_brush_channelset_copy(brush_src->channels);
}
/* enable fake user by default */
id_fake_user_set(&brush_dst->id);
}
@@ -134,6 +147,10 @@ static void brush_free_data(ID *id)
MEM_SAFE_FREE(brush->gradient);
BKE_previewimg_free(&(brush->preview));
if (brush->channels) {
BKE_brush_channelset_free(brush->channels);
}
}
static void brush_make_local(Main *bmain, ID *id, const int flags)
@@ -256,6 +273,10 @@ static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_addres
if (brush->gradient) {
BLO_write_struct(writer, ColorBand, brush->gradient);
}
if (brush->channels) {
BKE_brush_channelset_blend_write(brush->channels, writer);
}
}
static void brush_blend_read_data(BlendDataReader *reader, ID *id)
@@ -337,6 +358,14 @@ static void brush_blend_read_data(BlendDataReader *reader, ID *id)
brush->preview = nullptr;
brush->icon_imbuf = nullptr;
BLO_read_data_address(reader, &brush->channels);
if (brush->channels) {
BKE_brush_channelset_blend_read(brush->channels, reader);
}
BKE_brush_channelset_ensure_all_modes(brush);
}
static void brush_blend_read_lib(BlendLibReader *reader, ID *id)
@@ -1707,6 +1736,14 @@ void BKE_brush_sculpt_reset(Brush *br)
brush_defaults(br);
BKE_brush_curve_preset(br, CURVE_PRESET_SMOOTH);
/* Reset brush channels */
if (br->channels) {
BKE_brush_channelset_free(br->channels);
}
br->channels = BKE_brush_channelset_create();
BKE_brush_channelset_ensure_channels(br->channels, PAINT_MODE_SCULPT, br->sculpt_tool);
/* Use the curve presets by default */
br->curve_preset = BRUSH_CURVE_SMOOTH;
@@ -2269,6 +2306,9 @@ void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float c
void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
{
BKE_brush_int_set_unified(scene, brush, size, size);
#if 0
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
/* make sure range is sane */
@@ -2280,14 +2320,20 @@ void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
else {
brush->size = size;
}
#endif
}
int BKE_brush_size_get(const Scene *scene, const Brush *brush)
{
return BKE_brush_int_get_unified(scene, brush, size);
/* theoretically faster: return BKE_brush_eval_int(brush, scene, size, NULL); */
#if 0
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
int size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
return size;
#endif
}
bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush)
@@ -2298,9 +2344,16 @@ bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush)
(brush->flag & BRUSH_LOCK_SIZE);
}
bool BKE_brush_use_size_pressure(const Brush *brush)
bool BKE_brush_use_size_pressure(const Scene *scene, const Brush *brush)
{
return brush->flag & BRUSH_SIZE_PRESSURE;
if (!BKE_brush_use_locked_size(scene, brush)) {
return BKE_brush_mapping_enabled(scene, brush, size, BRUSH_MAPPING_PRESSURE);
}
else {
return BKE_brush_mapping_enabled(scene, brush, unprojected_radius, BRUSH_MAPPING_PRESSURE);
}
// return brush->flag & BRUSH_SIZE_PRESSURE;
}
bool BKE_brush_use_alpha_pressure(const Brush *brush)
@@ -2348,21 +2401,27 @@ float BKE_brush_unprojected_radius_get(const Scene *scene, const Brush *brush)
void BKE_brush_alpha_set(Scene *scene, Brush *brush, float alpha)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
BKE_brush_float_set_unified(scene, brush, strength, alpha);
#if 0
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
if (ups->flag & UNIFIED_PAINT_ALPHA) {
ups->alpha = alpha;
}
else {
brush->alpha = alpha;
}
#endif
}
float BKE_brush_alpha_get(const Scene *scene, const Brush *brush)
{
return BKE_brush_float_get_unified(scene, brush, strength);
#if 0
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
return (ups->flag & UNIFIED_PAINT_ALPHA) ? ups->alpha : brush->alpha;
#endif
}
float BKE_brush_weight_get(const Scene *scene, const Brush *brush)
@@ -2558,3 +2617,54 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool
return im;
}
float BKE_brush_curve_strength_ex(
int curve_preset, const CurveMapping *curve, float p, const float len, const bool invert)
{
float strength = 1.0f;
if (p >= len) {
return invert ? 0.0f : 1.0f;
}
p = p / len;
if (invert) {
p = 1.0f - p;
}
switch (curve_preset) {
case BRUSH_CURVE_CUSTOM:
strength = BKE_curvemapping_evaluateF(curve, 0, p);
break;
case BRUSH_CURVE_SHARP:
strength = p * p;
break;
case BRUSH_CURVE_SMOOTH:
strength = 3.0f * p * p - 2.0f * p * p * p;
break;
case BRUSH_CURVE_SMOOTHER:
strength = pow3f(p) * (p * (p * 6.0f - 15.0f) + 10.0f);
break;
case BRUSH_CURVE_ROOT:
strength = sqrtf(p);
break;
case BRUSH_CURVE_LIN:
strength = p;
break;
case BRUSH_CURVE_CONSTANT:
strength = 1.0f;
break;
case BRUSH_CURVE_SPHERE:
strength = sqrtf(2 * p - p * p);
break;
case BRUSH_CURVE_POW4:
strength = p * p * p * p;
break;
case BRUSH_CURVE_INVSQUARE:
strength = p * (2.0f - p);
break;
}
return strength;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
#if defined(BRUSH_CHANNEL_DEFINE_EXTERNAL) || defined(BRUSH_CHANNEL_DEFINE_INTERNAL_NAMES) || \
defined(BRUSH_CHANNEL_DEFINE_INTERNAL)
# ifdef MAKE_PROP
# undef MAKE_PROP
# endif
# ifdef MAKE_PROP_EX
# undef MAKE_PROP_EX
# endif
#endif
#ifdef BRUSH_CHANNEL_DEFINE_EXTERNAL
# define MAKE_PROP_EX(idname, category, flag, ...) MAKE_PROP(idname, category, uiflags)
# define MAKE_PROP(idname, category, ...) extern const char *BRUSH_BUILTIN_##idname;
#elif defined(BRUSH_CHANNEL_DEFINE_INTERNAL_NAMES)
# define MAKE_PROP_EX(idname, category, flag, ...) MAKE_PROP(idname, category)
# define MAKE_PROP(idname, category, ...) const char *BRUSH_BUILTIN_##idname = # idname;
#elif defined(BRUSH_CHANNEL_DEFINE_INTERNAL)
# define MAKE_PROP(idname, category, ...) {# idname, category, {__VA_ARGS__}, 0, {}},
# define MAKE_PROP_EX(idname, category, flag, ...) {# idname, category, {__VA_ARGS__}, flag, {}},
#endif
#ifdef SHOW_WORKSPACE
# undef SHOW_WORKSPACE
#endif
#ifdef SHOW_CONTEXT
# undef SHOW_CONTEXT
#endif
#ifdef SHOW_CONTEXT
# undef SHOW_CONTEXT
#endif
#ifdef SHOW_ALL
# undef SHOW_ALL
#endif
/*
UI visibility flags. Note that some brush types
may override these in their own channels, see BKE_brush_channelset_ensure_channels
*/
#define SHOW_WORKSPACE BRUSH_CHANNEL_SHOW_IN_WORKSPACE
#define SHOW_CONTEXT BRUSH_CHANNEL_SHOW_IN_CONTEXT_MENU
#define SHOW_HEADER BRUSH_CHANNEL_SHOW_IN_HEADER
#define SHOW_ALL (SHOW_WORKSPACE | SHOW_CONTEXT | SHOW_HEADER)
/* Note that channel sets for individual brush types are built in
* BKE_brush_channelset_ensure_channels
*/
#define SCULPT_GEO_TOOLS \
SCULPT_TOOL_DRAW, SCULPT_TOOL_CLAY, SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_FLATTEN, \
SCULPT_TOOL_PINCH, SCULPT_TOOL_FILL, SCULPT_TOOL_INFLATE, SCULPT_TOOL_THUMB, \
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_CREASE, SCULPT_TOOL_BLOB, SCULPT_TOOL_CLAY_STRIPS, \
SCULPT_TOOL_LAYER
#ifdef GEOMETRY
#undef GEOMETRY
#endif
#define GEOMETRY(flag) UI(PAINT_MODE_SCULPT, flag, {SCULPT_GEO_TOOLS})
#ifdef AUTOMASKING
# undef AUTOMASKING
#endif
#define AUTOMASKING UI(PAINT_MODE_SCULPT, SHOW_WORKSPACE)
#ifdef SCULPT_PAINT
# undef SCULPT_PAINT
#endif
#ifdef SCULPT_CLOTHABLE_TOOLS
# undef SCULPT_CLOTHABLE_TOOLS
#endif
#define SCULPT_CLOTHABLE_TOOLS \
SCULPT_TOOL_CLOTH, SCULPT_TOOL_BOUNDARY, SCULPT_TOOL_ELASTIC_DEFORM, SCULPT_TOOL_POSE
#define SCULPT_PAINT UI(PAINT_MODE_SCULPT, SHOW_CONTEXT | SHOW_WORKSPACE, {SCULPT_TOOL_PAINT})
MAKE_PROP(size, "Basic", UI(SHOW_ALL))
MAKE_PROP(unprojected_radius, "Basic", UI(SHOW_ALL))
MAKE_PROP(strength, "Basic", UI(SHOW_ALL))
MAKE_PROP(automasking_boundary_edges_propagation_steps, "Automasking", AUTOMASKING)
MAKE_PROP(use_automasking_boundary_edges, "Automasking", AUTOMASKING)
MAKE_PROP(use_automasking_boundary_face_sets, "Automasking", AUTOMASKING)
MAKE_PROP(use_automasking_face_sets, "Automasking", AUTOMASKING)
MAKE_PROP(use_automasking_topology, "Automasking", AUTOMASKING)
MAKE_PROP(area_radius_factor, "Basic", GEOMETRY(SHOW_WORKSPACE|SHOW_CONTEXT))
MAKE_PROP(blur_kernel_radius, "Basic")
MAKE_PROP(boundary_offset, "Basic", UI(PAINT_MODE_SCULPT, SHOW_ALL, {SCULPT_TOOL_BOUNDARY}))
MAKE_PROP(clone_alpha,
"Basic",
UI(PAINT_MODE_TEXTURE_2D, SHOW_WORKSPACE),
UI(PAINT_MODE_TEXTURE_3D, SHOW_WORKSPACE))
MAKE_PROP(clone_offset,
"Basic",
UI(PAINT_MODE_TEXTURE_2D, SHOW_WORKSPACE),
UI(PAINT_MODE_TEXTURE_3D, SHOW_WORKSPACE))
MAKE_PROP(crease_pinch_factor, "Basic")
MAKE_PROP(cursor_color_add, "Basic")
MAKE_PROP(cursor_color_subtract, "Basic")
MAKE_PROP(cursor_overlay_alpha, "Basic")
MAKE_PROP(disconnected_distance_max, "Basic")
MAKE_PROP(elastic_deform_volume_preservation,
"Basic",
UI(PAINT_MODE_SCULPT,
SHOW_WORKSPACE,
{SCULPT_TOOL_ELASTIC_DEFORM | SCULPT_TOOL_BOUNDARY | SCULPT_TOOL_CLOTH}))
MAKE_PROP(falloff_angle, "Basic")
MAKE_PROP(fill_threshold, "Basic")
MAKE_PROP(flow, "Basic")
MAKE_PROP(grad_spacing, "Basic")
MAKE_PROP(hardness, "Basic")
MAKE_PROP(height, "Basic", UI(PAINT_MODE_SCULPT, SHOW_ALL, {SCULPT_TOOL_LAYER}))
MAKE_PROP(invert_to_scrape_fill, "Basic")
MAKE_PROP(mask_overlay_alpha, "Basic")
MAKE_PROP(mask_stencil_dimension, "Basic")
MAKE_PROP(mask_stencil_pos, "Basic")
MAKE_PROP(multiplane_scrape_angle, "Basic")
MAKE_PROP(normal_radius_factor, "Basic")
MAKE_PROP(normal_weight, "Basic")
MAKE_PROP(plane_offset, "Basic")
MAKE_PROP(plane_trim, "Basic")
MAKE_PROP(rake_factor, "Basic")
MAKE_PROP(sharp_threshold, "Basic")
MAKE_PROP(show_multiplane_scrape_planes_preview, "Basic")
MAKE_PROP(stencil_dimension, "Basic")
MAKE_PROP(stencil_pos, "Basic")
MAKE_PROP(surface_smooth_current_vertex, "Basic")
MAKE_PROP(surface_smooth_iterations, "Basic")
MAKE_PROP(surface_smooth_shape_preservation, "Basic")
MAKE_PROP(texture_overlay_alpha, "Basic")
MAKE_PROP(texture_sample_bias, "Basic")
MAKE_PROP(tilt_strength_factor, "Basic")
MAKE_PROP(tip_roundness, "Basic")
MAKE_PROP(tip_scale_x, "Basic")
MAKE_PROP(use_accumulate, "Basic", UI(SHOW_ALL))
MAKE_PROP(use_adaptive_space, "Basic")
MAKE_PROP(use_airbrush, "Basic")
MAKE_PROP(use_alpha, "Basic")
MAKE_PROP(use_anchor, "Basic")
MAKE_PROP(use_connected_only, "Basic")
MAKE_PROP(use_cursor_overlay, "Basic")
MAKE_PROP(use_cursor_overlay_override, "Basic")
MAKE_PROP(use_curve, "Basic")
MAKE_PROP(use_custom_icon, "Basic")
MAKE_PROP(use_edge_to_edge, "Basic")
MAKE_PROP(use_frontface, "Basic")
MAKE_PROP(use_frontface_falloff, "Basic")
MAKE_PROP(use_grab_active_vertex, "Basic")
MAKE_PROP(use_grab_silhouette, "Basic")
MAKE_PROP(use_line, "Basic")
MAKE_PROP(use_multiplane_scrape_dynamic, "Basic")
MAKE_PROP(use_original_normal, "Basic")
MAKE_PROP(use_original_plane, "Basic")
MAKE_PROP(use_persistent, "Basic")
MAKE_PROP(use_plane_trim, "Basic")
MAKE_PROP(use_primary_overlay, "Basic")
MAKE_PROP(use_primary_overlay_override, "Basic")
MAKE_PROP(use_restore_mesh, "Basic")
MAKE_PROP(use_secondary_overlay, "Basic")
MAKE_PROP(use_secondary_overlay_override, "Basic")
MAKE_PROP(use_smooth_stroke, "Basic", UI(SHOW_WORKSPACE))
MAKE_PROP(use_space, "Basic", UI(SHOW_WORKSPACE))
MAKE_PROP(use_space_attenuation, "Basic", UI(SHOW_WORKSPACE))
MAKE_PROP(use_vertex_grease_pencil, "Basic")
MAKE_PROP(weight, "Basic")
MAKE_PROP(wet_paint_radius_factor, "Basic")
MAKE_PROP(cloth_constraint_softbody_strength,
"Cloth",
UI(PAINT_MODE_SCULPT, SHOW_WORKSPACE, {SCULPT_CLOTHABLE_TOOLS}))
MAKE_PROP(cloth_damping, "Cloth", UI(PAINT_MODE_SCULPT, SHOW_WORKSPACE, {SCULPT_CLOTHABLE_TOOLS}))
MAKE_PROP(cloth_mass, "Cloth", UI(PAINT_MODE_SCULPT, SHOW_WORKSPACE, {SCULPT_CLOTHABLE_TOOLS}))
MAKE_PROP(cloth_sim_falloff,
"Cloth",
UI(PAINT_MODE_SCULPT, SHOW_WORKSPACE, {SCULPT_CLOTHABLE_TOOLS}))
MAKE_PROP(cloth_sim_limit,
"Cloth",
UI(PAINT_MODE_SCULPT, SHOW_WORKSPACE, {SCULPT_CLOTHABLE_TOOLS}))
MAKE_PROP(use_cloth_collision,
"Cloth",
UI(PAINT_MODE_SCULPT, SHOW_WORKSPACE, {SCULPT_CLOTHABLE_TOOLS}))
MAKE_PROP(use_cloth_pin_simulation_boundary,
"Cloth",
UI(PAINT_MODE_SCULPT, SHOW_WORKSPACE, {SCULPT_CLOTHABLE_TOOLS}))
MAKE_PROP(color,
"Paint",
UI(PAINT_MODE_SCULPT, SHOW_ALL, {SCULPT_TOOL_PAINT}),
UI(PAINT_MODE_TEXTURE_2D, SHOW_ALL),
UI(PAINT_MODE_TEXTURE_3D, SHOW_ALL),
UI(PAINT_MODE_VERTEX, SHOW_ALL))
MAKE_PROP(density, "Paint", SCULPT_PAINT)
MAKE_PROP(rate, "Paint")
MAKE_PROP(secondary_color,
"Paint",
UI(PAINT_MODE_SCULPT, SHOW_ALL, {SCULPT_TOOL_PAINT}),
UI(PAINT_MODE_TEXTURE_2D, SHOW_ALL),
UI(PAINT_MODE_TEXTURE_3D, SHOW_ALL),
UI(PAINT_MODE_VERTEX, SHOW_ALL))
MAKE_PROP(use_paint_antialiasing, "Paint", UI(PAINT_MODE_TEXTURE_2D, SHOW_WORKSPACE))
MAKE_PROP(use_paint_weight, "Paint")
MAKE_PROP(wet_mix, "Paint", SCULPT_PAINT)
MAKE_PROP(wet_persistence, "Paint", SCULPT_PAINT)
MAKE_PROP(pose_ik_segments, "Pose", UI(PAINT_MODE_SCULPT, SHOW_WORKSPACE, {SCULPT_TOOL_POSE}))
MAKE_PROP(pose_offset, "Pose", UI(PAINT_MODE_SCULPT, SHOW_WORKSPACE, {SCULPT_TOOL_POSE}))
MAKE_PROP(pose_smooth_iterations,
"Pose",
UI(PAINT_MODE_SCULPT, SHOW_WORKSPACE, {SCULPT_TOOL_POSE}))
MAKE_PROP(use_pose_ik_anchored, "Pose", UI(PAINT_MODE_SCULPT, SHOW_WORKSPACE, {SCULPT_TOOL_POSE}))
MAKE_PROP(use_pose_lock_rotation,
"Pose",
UI(PAINT_MODE_SCULPT, SHOW_WORKSPACE, {SCULPT_TOOL_POSE}))
MAKE_PROP(auto_smooth_factor, "Smooth", GEOMETRY(SHOW_WORKSPACE | SHOW_CONTEXT))
MAKE_PROP(topology_rake_factor, "Smooth", GEOMETRY(SHOW_WORKSPACE))
MAKE_PROP(dash_ratio, "Stroke", UI(SHOW_WORKSPACE))
MAKE_PROP(dash_samples, "Stroke", UI(SHOW_WORKSPACE))
MAKE_PROP(jitter, "Stroke", UI(SHOW_WORKSPACE))
MAKE_PROP(jitter_absolute, "Stroke", UI(SHOW_WORKSPACE))
MAKE_PROP(smooth_stroke_factor, "Stroke", UI(SHOW_WORKSPACE))
MAKE_PROP(smooth_stroke_radius, "Stroke", UI(SHOW_WORKSPACE))
MAKE_PROP(spacing, "Stroke", UI(SHOW_WORKSPACE))
// tst
#undef MAKE_PROP
#undef MAKE_PROP_EX
#undef SHOW_WORKSPACE
#undef SHOW_HEADER
#undef SHOW_CONTEXT
#undef SHOW_ALL
#undef AUTOMASKING
#undef SCULPT_GEO_TOOLS
#undef SCULPT_PAINT
#undef SCULPT_CLOTHABLE_TOOLS
#undef GEOMETRY

View File

@@ -56,6 +56,7 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_bpath.h"
#include "BKE_brush_channel.h"
#include "BKE_cachefile.h"
#include "BKE_collection.h"
#include "BKE_colortools.h"
@@ -162,6 +163,7 @@ static void scene_init_data(ID *id)
CURVEMAP_SLOPE_POS_NEG);
scene->toolsettings = DNA_struct_default_alloc(ToolSettings);
BKE_brush_channelset_toolsettings_init(scene->toolsettings);
scene->toolsettings->autokey_mode = uchar(U.autokey_mode);
@@ -1108,6 +1110,10 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
BKE_screen_view3d_shading_blend_write(writer, &sce->display.shading);
if (sce->toolsettings && sce->toolsettings->unified_channels) {
BKE_brush_channelset_blend_write(sce->toolsettings->unified_channels, writer);
}
/* Freed on `do_versions()`. */
BLI_assert(sce->layer_properties == nullptr);
}
@@ -1165,6 +1171,16 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
BLO_read_data_address(reader, &sce->toolsettings);
if (sce->toolsettings) {
BLO_read_data_address(reader, &sce->toolsettings->unified_channels);
BLO_read_data_address(reader, &sce->toolsettings->unified_properties);
IDP_BlendDataRead(reader, &sce->toolsettings->unified_properties);
if (sce->toolsettings->unified_channels) {
BKE_brush_channelset_blend_read(sce->toolsettings->unified_channels, reader);
}
BKE_brush_channelset_toolsettings_init(sce->toolsettings);
/* Reset last_location and last_hit, so they are not remembered across sessions. In some files
* these are also NaN, which could lead to crashes in painting. */

View File

@@ -125,7 +125,7 @@ struct CombOperationExecutor {
curves_sculpt_ = ctx_.scene->toolsettings->curves_sculpt;
brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint);
brush_radius_base_re_ = BKE_brush_size_get(ctx_.scene, brush_);
brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
brush_radius_factor_ = brush_radius_factor(*ctx_.scene, *brush_, stroke_extension);
brush_strength_ = brush_strength_get(*ctx_.scene, *brush_, stroke_extension);
falloff_shape_ = static_cast<eBrushFalloffShape>(brush_->falloff_shape);

View File

@@ -102,7 +102,7 @@ struct DeleteOperationExecutor {
curves_sculpt_ = ctx_.scene->toolsettings->curves_sculpt;
brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint);
brush_radius_base_re_ = BKE_brush_size_get(ctx_.scene, brush_);
brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
brush_radius_factor_ = brush_radius_factor(*ctx_.scene, *brush_, stroke_extension);
brush_pos_re_ = stroke_extension.mouse_position;

View File

@@ -555,7 +555,7 @@ struct DensitySubtractOperationExecutor {
curves_sculpt_ = ctx_.scene->toolsettings->curves_sculpt;
brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint);
brush_radius_base_re_ = BKE_brush_size_get(ctx_.scene, brush_);
brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
brush_radius_factor_ = brush_radius_factor(*ctx_.scene, *brush_, stroke_extension);
brush_strength_ = brush_strength_get(*ctx_.scene, *brush_, stroke_extension);
brush_pos_re_ = stroke_extension.mouse_position;

View File

@@ -288,7 +288,7 @@ struct CurvesEffectOperationExecutor {
brush_strength_ = brush_strength_get(*ctx_.scene, *brush_, stroke_extension);
brush_radius_base_re_ = BKE_brush_size_get(ctx_.scene, brush_);
brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
brush_radius_factor_ = brush_radius_factor(*ctx_.scene, *brush_, stroke_extension);
brush_strength_ = brush_strength_get(*ctx_.scene, *brush_, stroke_extension);
falloff_shape_ = eBrushFalloffShape(brush_->falloff_shape);

View File

@@ -39,7 +39,9 @@ struct StrokeExtension {
ReportList *reports = nullptr;
};
float brush_radius_factor(const Brush &brush, const StrokeExtension &stroke_extension);
float brush_radius_factor(const Scene &scene,
const Brush &brush,
const StrokeExtension &stroke_extension);
float brush_radius_get(const Scene &scene,
const Brush &brush,
const StrokeExtension &stroke_extension);

View File

@@ -79,9 +79,11 @@ using blender::bke::CurvesGeometry;
/** \name Brush Stroke Operator
* \{ */
float brush_radius_factor(const Brush &brush, const StrokeExtension &stroke_extension)
float brush_radius_factor(const Scene &scene,
const Brush &brush,
const StrokeExtension &stroke_extension)
{
if (BKE_brush_use_size_pressure(&brush)) {
if (BKE_brush_use_size_pressure(&scene, &brush)) {
return stroke_extension.pressure;
}
return 1.0f;
@@ -91,7 +93,7 @@ float brush_radius_get(const Scene &scene,
const Brush &brush,
const StrokeExtension &stroke_extension)
{
return BKE_brush_size_get(&scene, &brush) * brush_radius_factor(brush, stroke_extension);
return BKE_brush_size_get(&scene, &brush) * brush_radius_factor(scene, brush, stroke_extension);
}
float brush_strength_factor(const Brush &brush, const StrokeExtension &stroke_extension)

View File

@@ -98,7 +98,7 @@ struct PinchOperationExecutor {
curves_sculpt_ = ctx_.scene->toolsettings->curves_sculpt;
brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint);
brush_radius_base_re_ = BKE_brush_size_get(ctx_.scene, brush_);
brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
brush_radius_factor_ = brush_radius_factor(*ctx_.scene, *brush_, stroke_extension);
brush_strength_ = BKE_brush_alpha_get(ctx_.scene, brush_);
invert_factor_ = self_->invert_pinch_ ? -1.0f : 1.0f;

View File

@@ -98,7 +98,7 @@ struct PuffOperationExecutor {
curves_sculpt_ = ctx_.scene->toolsettings->curves_sculpt;
brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint);
brush_radius_base_re_ = BKE_brush_size_get(ctx_.scene, brush_);
brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
brush_radius_factor_ = brush_radius_factor(*ctx_.scene, *brush_, stroke_extension);
brush_strength_ = brush_strength_get(*ctx_.scene, *brush_, stroke_extension);
brush_pos_re_ = stroke_extension.mouse_position;

View File

@@ -88,7 +88,7 @@ struct SelectionPaintOperationExecutor {
brush_ = BKE_paint_brush_for_read(&ctx_.scene->toolsettings->curves_sculpt->paint);
brush_radius_base_re_ = BKE_brush_size_get(ctx_.scene, brush_);
brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
brush_radius_factor_ = brush_radius_factor(*ctx_.scene, *brush_, stroke_extension);
brush_strength_ = BKE_brush_alpha_get(ctx_.scene, brush_);
brush_pos_re_ = stroke_extension.mouse_position;

View File

@@ -154,7 +154,7 @@ struct SlideOperationExecutor {
curves_sculpt_ = ctx_.scene->toolsettings->curves_sculpt;
brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint);
brush_radius_base_re_ = BKE_brush_size_get(ctx_.scene, brush_);
brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
brush_radius_factor_ = brush_radius_factor(*ctx_.scene, *brush_, stroke_extension);
brush_strength_ = brush_strength_get(*ctx_.scene, *brush_, stroke_extension);
curve_factors_ = get_curves_selection(*curves_id_orig_);

View File

@@ -74,7 +74,7 @@ struct SmoothOperationExecutor {
curves_sculpt_ = ctx_.scene->toolsettings->curves_sculpt;
brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint);
brush_radius_base_re_ = BKE_brush_size_get(ctx_.scene, brush_);
brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
brush_radius_factor_ = brush_radius_factor(*ctx_.scene, *brush_, stroke_extension);
brush_strength_ = brush_strength_get(*ctx_.scene, *brush_, stroke_extension);
brush_pos_re_ = stroke_extension.mouse_position;

View File

@@ -112,7 +112,7 @@ struct SnakeHookOperatorExecutor {
brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint);
brush_radius_base_re_ = BKE_brush_size_get(ctx_.scene, brush_);
brush_radius_factor_ = brush_radius_factor(*brush_, stroke_extension);
brush_radius_factor_ = brush_radius_factor(*ctx_.scene, *brush_, stroke_extension);
brush_strength_ = brush_strength_get(*ctx_.scene, *brush_, stroke_extension);
falloff_shape_ = static_cast<eBrushFalloffShape>(brush_->falloff_shape);

View File

@@ -524,7 +524,8 @@ static int project_brush_radius(ViewContext *vc, float radius, const float locat
/* Draw an overlay that shows what effect the brush's texture will
* have on brush strength. */
static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
static bool paint_draw_tex_overlay(Scene *scene,
UnifiedPaintSettings *ups,
Brush *brush,
ViewContext *vc,
int x,
@@ -573,7 +574,7 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
GPU_matrix_translate_2f(-center[0], -center[1]);
/* Scale based on tablet pressure. */
if (primary && ups->stroke_active && BKE_brush_use_size_pressure(brush)) {
if (primary && ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) {
const float scale = ups->size_pressure_value;
GPU_matrix_translate_2fv(center);
GPU_matrix_scale_2f(scale, scale);
@@ -674,8 +675,13 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
/* Draw an overlay that shows what effect the brush's texture will
* have on brush strength. */
static bool paint_draw_cursor_overlay(
UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, int y, float zoom)
static bool paint_draw_cursor_overlay(Scene *scene,
UnifiedPaintSettings *ups,
Brush *brush,
ViewContext *vc,
int x,
int y,
float zoom)
{
rctf quad;
/* Check for overlay mode. */
@@ -710,7 +716,7 @@ static bool paint_draw_cursor_overlay(
}
/* Scale based on tablet pressure. */
if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) {
if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) {
do_pop = true;
GPU_matrix_push();
GPU_matrix_translate_2fv(center);
@@ -756,7 +762,8 @@ static bool paint_draw_cursor_overlay(
return true;
}
static bool paint_draw_alpha_overlay(UnifiedPaintSettings *ups,
static bool paint_draw_alpha_overlay(Scene *scene,
UnifiedPaintSettings *ups,
Brush *brush,
ViewContext *vc,
int x,
@@ -783,22 +790,24 @@ static bool paint_draw_alpha_overlay(UnifiedPaintSettings *ups,
/* Colored overlay should be drawn separately. */
if (col) {
if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY)) {
alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, mode, true, true);
alpha_overlay_active = paint_draw_tex_overlay(
scene, ups, brush, vc, x, y, zoom, mode, true, true);
}
if (!(flags & PAINT_OVERLAY_OVERRIDE_SECONDARY)) {
alpha_overlay_active = paint_draw_tex_overlay(
ups, brush, vc, x, y, zoom, mode, false, false);
scene, ups, brush, vc, x, y, zoom, mode, false, false);
}
if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR)) {
alpha_overlay_active = paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
alpha_overlay_active = paint_draw_cursor_overlay(scene, ups, brush, vc, x, y, zoom);
}
}
else {
if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY) && (mode != PAINT_MODE_WEIGHT)) {
alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, mode, false, true);
alpha_overlay_active = paint_draw_tex_overlay(
scene, ups, brush, vc, x, y, zoom, mode, false, true);
}
if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR)) {
alpha_overlay_active = paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
alpha_overlay_active = paint_draw_cursor_overlay(scene, ups, brush, vc, x, y, zoom);
}
}
@@ -1011,7 +1020,7 @@ static void paint_cursor_update_unprojected_radius(UnifiedPaintSettings *ups,
unprojected_radius = paint_calc_object_space_radius(vc, location, projected_radius);
/* Scale 3D brush radius by pressure. */
if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) {
if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
unprojected_radius *= ups->size_pressure_value;
}
@@ -1406,7 +1415,7 @@ static void paint_draw_2D_view_brush_cursor(PaintCursorContext *pcontext)
immUniformColor3fvAlpha(pcontext->outline_col, pcontext->outline_alpha);
/* Draw brush outline. */
if (pcontext->ups->stroke_active && BKE_brush_use_size_pressure(pcontext->brush)) {
if (pcontext->ups->stroke_active && BKE_brush_use_size_pressure(pcontext->scene, pcontext->brush)) {
imm_draw_circle_wire_2d(pcontext->pos,
pcontext->translation[0],
pcontext->translation[1],
@@ -1846,7 +1855,8 @@ static void paint_cursor_update_rake_rotation(PaintCursorContext *pcontext)
static void paint_cursor_check_and_draw_alpha_overlays(PaintCursorContext *pcontext)
{
pcontext->alpha_overlay_drawn = paint_draw_alpha_overlay(pcontext->ups,
pcontext->alpha_overlay_drawn = paint_draw_alpha_overlay(pcontext->scene,
pcontext->ups,
pcontext->brush,
&pcontext->vc,
pcontext->x,

View File

@@ -370,6 +370,7 @@ void paint_sample_color(
void paint_stroke_operator_properties(struct wmOperatorType *ot);
void BRUSH_OT_curve_preset(struct wmOperatorType *ot);
void BRUSH_OT_curve_preset_load(struct wmOperatorType *ot);
void PAINT_OT_face_select_linked(struct wmOperatorType *ot);
void PAINT_OT_face_select_linked_pick(struct wmOperatorType *ot);

View File

@@ -1378,6 +1378,78 @@ static void BRUSH_OT_stencil_reset_transform(wmOperatorType *ot)
ot->srna, "mask", 0, "Modify Mask Stencil", "Modify either the primary or mask stencil");
}
static bool change_channel_order_poll(bContext *C)
{
Paint *paint = BKE_paint_get_active_from_context(C);
if (!paint) {
return false;
}
Brush *brush = BKE_paint_brush(paint);
return brush != NULL;
}
static int change_channel_order_exec(bContext *C, wmOperator *op)
{
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
char idname[BRUSH_CHANNEL_MAX_IDNAME];
RNA_string_get(op->ptr, "channel", idname);
if (!_BKE_brush_channelset_has(brush->channels, idname)) {
static char error[128];
sprintf(error, "Invalid brush channel \"%s\"", idname);
BKE_reportf(op->reports, RPT_ERROR_INVALID_INPUT, error);
return OPERATOR_CANCELLED;
}
BrushChannel *dest_ch = _BKE_brush_channelset_lookup(brush->channels, idname);
int neworder = dest_ch->ui_order;
BKE_brush_channelset_ui_order_check(brush->channels);
char filterkey[64];
int uiflag = 0;
RNA_string_get(op->ptr, "filterkey", filterkey);
if (STREQ(filterkey, "show_in_workspace")) {
uiflag = BRUSH_CHANNEL_SHOW_IN_WORKSPACE;
}
else if (STREQ(filterkey, "show_in_header")) {
uiflag = BRUSH_CHANNEL_SHOW_IN_HEADER;
}
else if (STREQ(filterkey, "show_in_context_menu")) {
uiflag = BRUSH_CHANNEL_SHOW_IN_CONTEXT_MENU;
}
int dir = RNA_int_get(op->ptr, "direction");
BKE_brush_channelset_ui_order_move(brush->channels, dest_ch, uiflag, dir);
return OPERATOR_FINISHED;
}
void BRUSH_OT_change_channel_order(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Change Brush Channel Order";
ot->description = "Move brush channels up or down";
ot->idname = "BRUSH_OT_change_channel_order";
/* api callbacks */
ot->exec = change_channel_order_exec;
ot->poll = change_channel_order_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_string(ot->srna, "channel", "", BRUSH_CHANNEL_MAX_IDNAME, "Brush Channel", "");
RNA_def_int(ot->srna, "direction", 1, -1, 1, "Direction", "", -1, 1);
RNA_def_string(ot->srna, "filterkey", NULL, 64, "filterkey", "filterkey");
}
/**************************** registration **********************************/
void ED_operatormacros_paint(void)
@@ -1422,6 +1494,7 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(BRUSH_OT_add_gpencil);
WM_operatortype_append(BRUSH_OT_scale_size);
WM_operatortype_append(BRUSH_OT_curve_preset);
WM_operatortype_append(BRUSH_OT_curve_preset_load);
WM_operatortype_append(BRUSH_OT_reset);
WM_operatortype_append(BRUSH_OT_stencil_control);
WM_operatortype_append(BRUSH_OT_stencil_fit_image_aspect);
@@ -1486,6 +1559,8 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_mask_lasso_gesture);
WM_operatortype_append(PAINT_OT_mask_box_gesture);
WM_operatortype_append(PAINT_OT_mask_line_gesture);
WM_operatortype_append(BRUSH_OT_change_channel_order);
}
void ED_keymap_paint(wmKeyConfig *keyconf)

View File

@@ -14,6 +14,7 @@
#include "PIL_time.h"
#include "DNA_brush_channel_types.h"
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
@@ -22,6 +23,7 @@
#include "RNA_access.h"
#include "BKE_brush.h"
#include "BKE_brush_channel.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -312,6 +314,7 @@ static bool paint_brush_update(bContext *C,
copy_v2_v2(ups->last_rake, mouse);
copy_v2_v2(ups->tex_mouse, mouse);
copy_v2_v2(ups->mask_tex_mouse, mouse);
stroke->cached_size_pressure = pressure;
ups->do_linear_conversion = false;
@@ -346,7 +349,7 @@ static bool paint_brush_update(bContext *C,
ups->pixel_radius = BKE_brush_size_get(scene, brush);
ups->initial_pixel_radius = BKE_brush_size_get(scene, brush);
if (BKE_brush_use_size_pressure(brush) && paint_supports_dynamic_size(brush, mode)) {
if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, mode)) {
ups->pixel_radius *= stroke->cached_size_pressure;
}
@@ -535,7 +538,7 @@ static void paint_brush_stroke_add_step(
if (tablet && (pressure >= 0.99f) &&
((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) ||
BKE_brush_use_alpha_pressure(pop->s.brush) ||
BKE_brush_use_size_pressure(pop->s.brush))) {
BKE_brush_use_size_pressure(scene, pop->s.brush))) {
return;
}
@@ -548,7 +551,7 @@ static void paint_brush_stroke_add_step(
if (tablet && (pressure < 0.0002f) &&
((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) ||
BKE_brush_use_alpha_pressure(pop->s.brush) ||
BKE_brush_use_size_pressure(pop->s.brush))) {
BKE_brush_use_size_pressure(scene, pop->s.brush))) {
return;
}
#endif
@@ -677,7 +680,20 @@ static float paint_space_stroke_spacing(bContext *C,
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
float size_clamp = 0.0f;
float size = BKE_brush_size_get(scene, stroke->brush) * size_pressure;
// float size = BKE_brush_size_get(scene, stroke->brush) * size_pressure;
BrushMappingData mapdata = {0};
mapdata.pressure = size_pressure;
#if 1
BKE_brush_channelset_mark_update(scene->toolsettings->unified_channels, size);
BKE_brush_channelset_mark_update(brush->channels, size);
BKE_brush_channelset_mark_update(scene->toolsettings->unified_channels, unprojected_radius);
BKE_brush_channelset_mark_update(brush->channels, unprojected_radius);
#endif
float size = BKE_brush_eval_int(brush, scene, size, &mapdata);
if (paint_stroke_use_scene_spacing(brush, mode)) {
if (!BKE_brush_use_locked_size(scene, brush)) {
float last_object_space_position[3];
@@ -687,7 +703,8 @@ static float paint_space_stroke_spacing(bContext *C,
size_clamp = paint_calc_object_space_radius(&stroke->vc, last_object_space_position, size);
}
else {
size_clamp = BKE_brush_unprojected_radius_get(scene, brush) * size_pressure;
// size_clamp = BKE_brush_unprojected_radius_get(scene, brush) * size_pressure;
size_clamp = BKE_brush_eval_float(brush, scene, unprojected_radius, &mapdata);
}
}
else {
@@ -773,7 +790,7 @@ static float paint_space_stroke_spacing_variable(bContext *C,
float dpressure,
float length)
{
if (BKE_brush_use_size_pressure(stroke->brush)) {
if (BKE_brush_use_size_pressure(scene, stroke->brush)) {
/* use pressure to modify size. set spacing so that at 100%, the circles
* are aligned nicely with no overlap. for this the spacing needs to be
* the average of the previous and next size. */

View File

@@ -8,6 +8,8 @@
#include <math.h>
#include <stdlib.h>
#include "MEM_guardedalloc.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -34,6 +36,7 @@
#include "BKE_mesh_runtime.h"
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_colortools.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -41,6 +44,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_prototypes.h"
#include "RNA_path.h"
#include "GPU_framebuffer.h"
#include "GPU_matrix.h"
@@ -609,6 +613,130 @@ void BRUSH_OT_curve_preset(wmOperatorType *ot)
BLT_I18NCONTEXT_ID_CURVE_LEGACY); /* Abusing id_curve :/ */
}
/**
* Attempt to retrieve the rna pointer/property from an rna path.
*
* \return 0 for failure, 1 for success, and also 1 if property is not set.
*/
static int curvemapping_preset_get_path(
PointerRNA *ctx_ptr, wmOperator *op, const char *name, PointerRNA *r_ptr, PropertyRNA **r_prop)
{
PropertyRNA *unused_prop;
/* get an rna string path from the operator's properties */
char *str;
if (!(str = RNA_string_get_alloc(op->ptr, name, NULL, 0, NULL))) {
return 1;
}
if (str[0] == '\0') {
if (r_prop) {
*r_prop = NULL;
}
MEM_freeN(str);
return 1;
}
if (!r_prop) {
r_prop = &unused_prop;
}
/* get rna from path */
if (!RNA_path_resolve(ctx_ptr, str, r_ptr, r_prop)) {
MEM_freeN(str);
BKE_reportf(op->reports, RPT_ERROR, "Could not resolve path '%s'", name);
return 0;
}
if (*r_prop) {
PropertyType prop_type = RNA_property_type(*r_prop);
if (!*r_prop || prop_type != PROP_POINTER) {
MEM_freeN(str);
BKE_reportf(op->reports, RPT_ERROR, "Property from path '%s' is not a curve", name);
return 0;
}
if (RNA_property_pointer_type(r_ptr, *r_prop) != &RNA_CurveMapping) {
MEM_freeN(str);
BKE_reportf(op->reports, RPT_ERROR, "Property from path '%s' is not a curve", name);
return 0;
}
}
else if (r_ptr->type != &RNA_CurveMapping) {
MEM_freeN(str);
BKE_reportf(op->reports, RPT_ERROR, "Property from path '%s' is not a curve", name);
return 0;
}
/* success */
MEM_freeN(str);
return 1;
}
static int curvemapping_preset_exec(bContext *C, wmOperator *op)
{
PointerRNA ctx_ptr;
RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr);
PointerRNA ptr;
PropertyRNA *prop;
if (!curvemapping_preset_get_path(&ctx_ptr, op, "path", &ptr, &prop)) {
return OPERATOR_CANCELLED;
}
CurveMapping *cumap = prop ? RNA_property_pointer_get(&ptr, prop).data : ptr.data;
int preset = RNA_enum_get(op->ptr, "shape");
cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
cumap->preset = preset;
CurveMap *cuma = cumap->cm;
int slope = RNA_boolean_get(op->ptr, "invert") ? CURVEMAP_SLOPE_NEGATIVE :
CURVEMAP_SLOPE_POSITIVE;
BKE_curvemap_reset(cuma, &cumap->clipr, cumap->preset, slope);
BKE_curvemapping_changed(cumap, false);
return OPERATOR_FINISHED;
}
static bool curvemapping_preset_poll(bContext *C)
{
return true;
}
void BRUSH_OT_curve_preset_load(wmOperatorType *ot)
{
PropertyRNA *prop;
static const EnumPropertyItem prop_shape_items[] = {
{CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""},
{CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""},
{CURVE_PRESET_MAX, "MAX", 0, "Max", ""},
{CURVE_PRESET_LINE, "LINE", 0, "Line", ""},
{CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""},
{CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""},
{0, NULL, 0, NULL, NULL},
};
ot->name = "Preset";
ot->description = "Load Curve Preset";
ot->idname = "BRUSH_OT_curve_preset_load";
ot->exec = curvemapping_preset_exec;
ot->poll = curvemapping_preset_poll;
prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
RNA_def_property_translation_context(prop,
BLT_I18NCONTEXT_ID_CURVE_LEGACY); /* Abusing id_curve :/ */
prop = RNA_def_string(ot->srna, "path", NULL, 256, "rna path", "RNA path to curve mapping");
prop = RNA_def_boolean(ot->srna, "invert", false, "invert", "Invert curve");
}
/* face-select ops */
static int paint_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
{

View File

@@ -1691,7 +1691,7 @@ static void vwpaint_update_cache_variants(bContext *C, VPaint *vp, Object *ob, P
BKE_brush_unprojected_radius_set(scene, brush, cache->initial_radius);
}
if (BKE_brush_use_size_pressure(brush) &&
if (BKE_brush_use_size_pressure(scene, brush) &&
paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) {
cache->radius = cache->initial_radius * cache->pressure;
}
@@ -1869,7 +1869,7 @@ static void get_brush_alpha_data(const Scene *scene,
float *r_brush_alpha_pressure)
{
*r_brush_size_pressure = BKE_brush_size_get(scene, brush) *
(BKE_brush_use_size_pressure(brush) ? ss->cache->pressure : 1.0f);
(BKE_brush_use_size_pressure(scene, brush) ? ss->cache->pressure : 1.0f);
*r_brush_alpha_value = BKE_brush_alpha_get(scene, brush);
*r_brush_alpha_pressure = (BKE_brush_use_alpha_pressure(brush) ? ss->cache->pressure : 1.0f);
}

View File

@@ -17,9 +17,12 @@
#include "BLI_ghash.h"
#include "BLI_gsqueue.h"
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "PIL_time.h"
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
#include "DNA_mesh_types.h"
@@ -30,6 +33,7 @@
#include "BKE_attribute.h"
#include "BKE_brush.h"
#include "BKE_brush_channel.h"
#include "BKE_ccg.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
@@ -2298,7 +2302,8 @@ void SCULPT_calc_area_normal_and_center(
* values pull vertices, negative values push. Uses tablet pressure and a
* special multiplier found experimentally to scale the strength factor.
*/
static float brush_strength(const Sculpt *sd,
static float brush_strength(const SculptSession *ss,
const Sculpt *sd,
const StrokeCache *cache,
const float feather,
const UnifiedPaintSettings *ups,
@@ -2308,10 +2313,12 @@ static float brush_strength(const Sculpt *sd,
const Brush *brush = BKE_paint_brush((Paint *)&sd->paint);
/* Primary strength input; square it to make lower values more sensitive. */
const float root_alpha = BKE_brush_alpha_get(scene, brush);
// float root_alpha = BKE_brush_alpha_get(scene, brush);
float root_alpha = BKE_brush_channelset_float_get(ss->cache->channels, strength);
const float alpha = root_alpha * root_alpha;
const float dir = (brush->flag & BRUSH_DIR_IN) ? -1.0f : 1.0f;
const float pressure = BKE_brush_use_alpha_pressure(brush) ? cache->pressure : 1.0f;
const float pen_flip = cache->pen_flip ? -1.0f : 1.0f;
const float invert = cache->invert ? -1.0f : 1.0f;
float overlap = ups->overlap_factor;
@@ -2323,112 +2330,109 @@ static float brush_strength(const Sculpt *sd,
flip = 1.0f;
}
/* Pressure final value after being tweaked depending on the brush. */
float final_pressure;
switch (brush->sculpt_tool) {
case SCULPT_TOOL_CLAY:
final_pressure = pow4f(pressure);
// pressure = pow4f(pressure);
overlap = (1.0f + overlap) / 2.0f;
return 0.25f * alpha * flip * final_pressure * overlap * feather;
return 0.25f * alpha * flip * overlap * feather;
case SCULPT_TOOL_DRAW:
case SCULPT_TOOL_DRAW_SHARP:
case SCULPT_TOOL_LAYER:
return alpha * flip * pressure * overlap * feather;
return alpha * flip * overlap * feather;
case SCULPT_TOOL_DISPLACEMENT_ERASER:
return alpha * pressure * overlap * feather;
return alpha * overlap * feather;
case SCULPT_TOOL_CLOTH:
if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) {
/* Grab deform uses the same falloff as a regular grab brush. */
return root_alpha * feather;
}
else if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK) {
return root_alpha * feather * pressure * overlap;
return root_alpha * feather * overlap;
}
else if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_EXPAND) {
/* Expand is more sensible to strength as it keeps expanding the cloth when sculpting over
* the same vertices. */
return 0.1f * alpha * flip * pressure * overlap * feather;
return 0.1f * alpha * flip * overlap * feather;
}
else {
/* Multiply by 10 by default to get a larger range of strength depending on the size of the
* brush and object. */
return 10.0f * alpha * flip * pressure * overlap * feather;
return 10.0f * alpha * flip * overlap * feather;
}
case SCULPT_TOOL_DRAW_FACE_SETS:
return alpha * pressure * overlap * feather;
return alpha * overlap * feather;
case SCULPT_TOOL_SLIDE_RELAX:
return alpha * pressure * overlap * feather * 2.0f;
return alpha * overlap * feather * 2.0f;
case SCULPT_TOOL_PAINT:
final_pressure = pressure * pressure;
return final_pressure * overlap * feather;
// pressure = pressure * pressure;
return overlap * feather;
case SCULPT_TOOL_SMEAR:
case SCULPT_TOOL_DISPLACEMENT_SMEAR:
return alpha * pressure * overlap * feather;
return alpha * overlap * feather;
case SCULPT_TOOL_CLAY_STRIPS:
/* Clay Strips needs less strength to compensate the curve. */
final_pressure = powf(pressure, 1.5f);
return alpha * flip * final_pressure * overlap * feather * 0.3f;
// pressure = powf(pressure, 1.5f);
return alpha * flip * overlap * feather * 0.3f;
case SCULPT_TOOL_CLAY_THUMB:
final_pressure = pressure * pressure;
return alpha * flip * final_pressure * overlap * feather * 1.3f;
// pressure = pressure * pressure;
return alpha * flip * overlap * feather * 1.3f;
case SCULPT_TOOL_MASK:
overlap = (1.0f + overlap) / 2.0f;
switch ((BrushMaskTool)brush->mask_tool) {
case BRUSH_MASK_DRAW:
return alpha * flip * pressure * overlap * feather;
return alpha * flip * overlap * feather;
case BRUSH_MASK_SMOOTH:
return alpha * pressure * feather;
return alpha * feather;
}
BLI_assert_msg(0, "Not supposed to happen");
return 0.0f;
case SCULPT_TOOL_CREASE:
case SCULPT_TOOL_BLOB:
return alpha * flip * pressure * overlap * feather;
return alpha * flip * overlap * feather;
case SCULPT_TOOL_INFLATE:
if (flip > 0.0f) {
return 0.250f * alpha * flip * pressure * overlap * feather;
return 0.250f * alpha * flip * overlap * feather;
}
else {
return 0.125f * alpha * flip * pressure * overlap * feather;
return 0.125f * alpha * flip * overlap * feather;
}
case SCULPT_TOOL_MULTIPLANE_SCRAPE:
overlap = (1.0f + overlap) / 2.0f;
return alpha * flip * pressure * overlap * feather;
return alpha * flip * overlap * feather;
case SCULPT_TOOL_FILL:
case SCULPT_TOOL_SCRAPE:
case SCULPT_TOOL_FLATTEN:
if (flip > 0.0f) {
overlap = (1.0f + overlap) / 2.0f;
return alpha * flip * pressure * overlap * feather;
return alpha * flip * overlap * feather;
}
else {
/* Reduce strength for DEEPEN, PEAKS, and CONTRAST. */
return 0.5f * alpha * flip * pressure * overlap * feather;
return 0.5f * alpha * flip * overlap * feather;
}
case SCULPT_TOOL_SMOOTH:
return flip * alpha * pressure * feather;
return flip * alpha * feather;
case SCULPT_TOOL_PINCH:
if (flip > 0.0f) {
return alpha * flip * pressure * overlap * feather;
return alpha * flip * overlap * feather;
}
else {
return 0.25f * alpha * flip * pressure * overlap * feather;
return 0.25f * alpha * flip * overlap * feather;
}
case SCULPT_TOOL_NUDGE:
overlap = (1.0f + overlap) / 2.0f;
return alpha * pressure * overlap * feather;
return alpha * overlap * feather;
case SCULPT_TOOL_THUMB:
return alpha * pressure * feather;
return alpha * feather;
case SCULPT_TOOL_SNAKE_HOOK:
return root_alpha * feather;
@@ -2437,7 +2441,7 @@ static float brush_strength(const Sculpt *sd,
return root_alpha * feather;
case SCULPT_TOOL_ROTATE:
return alpha * pressure * feather;
return alpha * feather;
case SCULPT_TOOL_ELASTIC_DEFORM:
case SCULPT_TOOL_POSE:
@@ -4018,7 +4022,7 @@ static void do_symmetrical_brush_actions(Sculpt *sd,
float feather = calc_symmetry_feather(sd, ss->cache);
cache->bstrength = brush_strength(sd, cache, feather, ups, paint_mode_settings);
cache->bstrength = brush_strength(ss, sd, cache, feather, ups, paint_mode_settings);
cache->symmetry = symm;
/* `symm` is a bit combination of XYZ -
@@ -4281,6 +4285,8 @@ static void sculpt_update_cache_invariants(
ss->cache = cache;
cache->rng = BLI_rng_new((int)(PIL_check_seconds_timer() * 10000.0));
/* Set scaling adjustment. */
max_scale = 0.0f;
for (int i = 0; i < 3; i++) {
@@ -4635,7 +4641,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
sculpt_rake_data_update(&cache->rake_data, grab_location);
}
static void sculpt_update_cache_paint_variants(StrokeCache *cache, const Brush *brush)
ATTR_NO_OPT static void sculpt_update_cache_paint_variants(StrokeCache *cache, const Brush *brush)
{
cache->paint_brush.hardness = brush->hardness;
if (brush->paint_flags & BRUSH_PAINT_HARDNESS_PRESSURE) {
@@ -4721,6 +4727,34 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
}
}
if (!cache->first_time && cache->radius != 0.0f) {
float mouse[2];
RNA_float_get_array(ptr, "mouse", mouse);
sub_v2_v2(mouse, cache->mouse);
cache->speed = len_v2(mouse) / cache->radius;
cache->angle = atan2(mouse[1], mouse[0]);
}
BrushMappingData mapdata;
mapdata.pressure = RNA_float_get(ptr, "pressure");
mapdata.xtilt = RNA_float_get(ptr, "x_tilt");
mapdata.ytilt = RNA_float_get(ptr, "y_tilt");
mapdata.stroke_t = cache->stroke_distance;
mapdata.random = BLI_rng_get_float(cache->rng);
mapdata.angle = cache->angle;
mapdata.speed = cache->speed;
printf("pressure: %.4f\n", mapdata.pressure);
if (cache->channels) {
BKE_brush_channelset_free(cache->channels);
}
cache->channels = BKE_brush_channelset_create_final(brush, scene, &mapdata);
cache->mapdata = mapdata;
/* Clay stabilized pressure. */
if (brush->sculpt_tool == SCULPT_TOOL_CLAY_THUMB) {
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
@@ -4738,7 +4772,8 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
}
}
if (BKE_brush_use_size_pressure(brush) &&
#if 0
if (BKE_brush_use_size_pressure(scene, brush) &&
paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) {
cache->radius = sculpt_brush_dynamic_size_get(brush, cache, cache->initial_radius);
cache->dyntopo_pixel_radius = sculpt_brush_dynamic_size_get(
@@ -4748,6 +4783,19 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
cache->radius = cache->initial_radius;
cache->dyntopo_pixel_radius = ups->initial_pixel_radius;
}
#else
if (!BKE_brush_use_locked_size(scene, brush)) {
int radius = BKE_brush_channelset_int_get(cache->channels, size);
cache->radius = paint_calc_object_space_radius(
cache->vc, cache->true_initial_location, radius);
printf("radius: %d\n", radius);
}
else {
cache->radius = BKE_brush_channelset_float_get(cache->channels, unprojected_radius);
}
#endif
sculpt_update_cache_paint_variants(cache, brush);
@@ -5196,7 +5244,7 @@ static void sculpt_brush_stroke_init(bContext *C, wmOperator *op)
ED_paint_tool_update_sticky_shading_color(C, ob);
}
static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
static void sculpt_restore_mesh(Scene *scene, Sculpt *sd, Object *ob)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -5210,7 +5258,7 @@ static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
/* Restore the mesh before continuing with anchored stroke. */
if ((brush->flag & BRUSH_ANCHORED) ||
(ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ELASTIC_DEFORM) &&
BKE_brush_use_size_pressure(brush)) ||
BKE_brush_use_size_pressure(scene, brush)) ||
(brush->flag & BRUSH_DRAG_DOT)) {
SculptUndoNode *unode = SCULPT_undo_get_first_node();
@@ -5505,7 +5553,7 @@ static void sculpt_stroke_update_step(bContext *C,
SCULPT_stroke_modifiers_check(C, ob, brush);
sculpt_update_cache_variants(C, sd, ob, itemptr);
sculpt_restore_mesh(sd, ob);
sculpt_restore_mesh(CTX_data_scene(C), sd, ob);
if (sd->flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL)) {
float object_space_constant_detail = 1.0f / (sd->constant_detail *

View File

@@ -7,6 +7,7 @@
#pragma once
#include "DNA_brush_channel_types.h"
#include "DNA_brush_types.h"
#include "DNA_key_types.h"
#include "DNA_listBase.h"
@@ -14,6 +15,7 @@
#include "DNA_scene_types.h"
#include "DNA_vec_types.h"
#include "BKE_brush_channel.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
#include "BLI_bitmap.h"
@@ -35,6 +37,8 @@ struct Object;
struct SculptUndoNode;
struct bContext;
struct PaintModeSettings;
struct RNG;
struct BrushChannelSet;
struct wmKeyConfig;
struct wmOperator;
struct wmOperatorType;
@@ -485,6 +489,7 @@ typedef struct FilterCache {
typedef struct StrokeCache {
/* Invariants */
float initial_radius;
float initial_raw_radius;
float scale[3];
int flag;
float clip_tolerance[3];
@@ -647,6 +652,11 @@ typedef struct StrokeCache {
rcti current_r; /* current redraw rectangle */
int stroke_id;
struct BrushChannelSet *channels;
struct RNG *rng;
float angle, speed;
BrushMappingData mapdata;
} StrokeCache;
/* -------------------------------------------------------------------- */

View File

@@ -0,0 +1,206 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2011 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup DNA
*
* Structs used for the sculpt brush system
*/
#pragma once
#include "DNA_color_types.h"
#include "DNA_listBase.h"
#include "BLI_assert.h"
struct GHash;
typedef struct BrushCurve {
CurveMapping *curve;
/** curve preset, see eBrushCurvePreset.
Note: this differs from BrushMappingDef's preset field
*/
int preset;
char preset_slope_negative;
char _pad[3];
} BrushCurve;
/* Input mapping struct. An input mapping transform
stroke inputs intos outputs. Inputs can be device
events (like pen pressure/tilt) or synethesize
(cumulative stroke distance, random, etc).
Inspired by Krita.
*/
typedef struct BrushMapping {
/* note that we use a curve cache (see BKE_curvemapping_cache)
and copy on write semantics. BrushChannels are copied
extensively (mostly to cache input mappings and resolve
channel inheritance), to the point that copying the
channel curves was a problem.
*/
BrushCurve curve;
float factor;
int blendmode; /* blendmode, a subset of the MA_BLEND_XXX enums*/
int flag, type;
float min, max;
float premultiply_factor; /** factor to premultiply input data with */
int mapfunc; /** mapping function, see eBrushMappingFunc. Most are periodic. */
/** threshold for BRUSH_MAPFUNC_CUTOFF and BRUSH_MAPFUNC_SQUARE mapping functions */
float func_cutoff;
/** controls whether this channel should inherit from scene defaults,
* see eBrushMappingInheritMode */
char inherit_mode, _pad[3];
} BrushMapping;
typedef struct BrushChannel {
struct BrushChannel *next, *prev;
char idname[64]; /* The RNA property name */
char uiname[64]; /** user-friendly name */
char *category; /** category; if NULL, def->category will be used */
struct BrushChannelType *def; /* Brush channel definition */
/*
Cached channel values.
*/
float fvalue; /** floating point value */
int ivalue; /** stores integer, boolean, enum and bitmasks */
float vector[4]; /* stores 3 and 4 component vectors */
/* For curve channels. */
BrushCurve curve;
/* Input device mappings */
BrushMapping mappings[7]; /* dimension should always be BRUSH_MAPPING_MAX */
short type; /** eBrushChannelType */
short ui_order;
int flag; /** eBrushChannelFlag */
int ui_flag, evaluated_flag;
int active_mapping, _pad[1];
} BrushChannel;
typedef struct BrushChannelSet {
ListBase channels;
int channels_num, _pad[1];
void *channelmap; /** idname -> channel map. */
} BrushChannelSet;
#define BRUSH_CHANNEL_MAX_IDNAME sizeof(((BrushChannel){0}).idname)
/* BrushMapping->flag */
typedef enum eBrushMappingFlags {
BRUSH_MAPPING_ENABLED = 1 << 0,
BRUSH_MAPPING_INVERT = 1 << 1,
BRUSH_MAPPING_UI_EXPANDED = 1 << 2,
} eBrushMappingFlags;
/* BrushMapping->inherit_mode */
typedef enum eBrushMappingInheritMode {
BRUSH_MAPPING_INHERIT_NEVER,
BRUSH_MAPPING_INHERIT_ALWAYS,
/* Use channel's inheritance mode. */
BRUSH_MAPPING_INHERIT_CHANNEL
} eBrushMappingInheritMode;
/* BrushMapping->mapfunc */
typedef enum eBrushMappingFunc {
BRUSH_MAPFUNC_NONE,
BRUSH_MAPFUNC_SAW,
BRUSH_MAPFUNC_TENT,
BRUSH_MAPFUNC_COS,
BRUSH_MAPFUNC_CUTOFF,
BRUSH_MAPFUNC_SQUARE, /* square wave */
} eBrushMappingFunc;
/* Input device mapping types. */
typedef enum eBrushMappingType {
BRUSH_MAPPING_PRESSURE = 0,
BRUSH_MAPPING_XTILT = 1,
BRUSH_MAPPING_YTILT = 2,
BRUSH_MAPPING_ANGLE = 3,
BRUSH_MAPPING_SPEED = 4,
BRUSH_MAPPING_RANDOM = 5,
BRUSH_MAPPING_STROKE_T = 6,
BRUSH_MAPPING_MAX = 7 // see BrushChannel.mappings
} eBrushMappingType;
BLI_STATIC_ASSERT(offsetof(BrushChannel, type) - offsetof(BrushChannel, mappings) ==
sizeof(BrushMapping) * BRUSH_MAPPING_MAX,
"BrushChannel.mappings must == BRUSH_MAPPING_MAX");
typedef enum eBrushChannelFlag {
BRUSH_CHANNEL_INHERIT = 1 << 0,
BRUSH_CHANNEL_INHERIT_IF_UNSET = 1 << 1,
BRUSH_CHANNEL_NO_MAPPINGS = 1 << 2,
BRUSH_CHANNEL_UI_EXPANDED = 1 << 3,
BRUSH_CHANNEL_APPLY_MAPPING_TO_ALPHA = 1 << 4,
BRUSH_CHANNEL_NEEDS_EVALUATE = 1 << 5,
/* Set in scene channels; forces inheritance on brush properties. */
BRUSH_CHANNEL_FORCE_INHERIT = 1 << 6,
/* Set in local brush channels; ignores BRUSH_CHANNEL_FORCE_INHERIT. */
BRUSH_CHANNEL_IGNORE_FORCE_INHERIT = 1 << 7,
} eBrushChannelFlag;
typedef enum eBrushChannelUIFlag {
BRUSH_CHANNEL_SHOW_IN_WORKSPACE = 1 << 0,
/* Has user overriden this, used for version patching. */
BRUSH_CHANNEL_SHOW_IN_WORKSPACE_USER_SET = 1 << 1,
BRUSH_CHANNEL_SHOW_IN_HEADER = 1 << 2,
BRUSH_CHANNEL_SHOW_IN_HEADER_USER_SET = 1 << 3,
BRUSH_CHANNEL_SHOW_IN_CONTEXT_MENU = 1 << 4,
BRUSH_CHANNEL_SHOW_IN_CONTEXT_MENU_USER_SET = 1 << 5,
} eBrushChannelUIFlag;
// BrushChannelType->type
typedef enum eBrushChannelType {
BRUSH_CHANNEL_TYPE_FLOAT = 1 << 0,
BRUSH_CHANNEL_TYPE_INT = 1 << 1,
BRUSH_CHANNEL_TYPE_ENUM = 1 << 2,
BRUSH_CHANNEL_TYPE_BITMASK = 1 << 3,
BRUSH_CHANNEL_TYPE_BOOL = 1 << 4,
BRUSH_CHANNEL_TYPE_VEC3 = 1 << 5,
BRUSH_CHANNEL_TYPE_VEC4 = 1 << 6,
BRUSH_CHANNEL_TYPE_CURVE = 1 << 7
} eBrushChannelType;
/* clang-format off */
typedef enum eBrushChannelSubType {
BRUSH_CHANNEL_NONE,
BRUSH_CHANNEL_COLOR,
BRUSH_CHANNEL_FACTOR,
BRUSH_CHANNEL_PERCENT,
BRUSH_CHANNEL_PIXEL,
BRUSH_CHANNEL_ANGLE
} eBrushChannelSubType;
/* clang-format on */

View File

@@ -467,6 +467,7 @@ typedef enum eBrushSculptTool {
SCULPT_TOOL_BOUNDARY = 30,
SCULPT_TOOL_DISPLACEMENT_ERASER = 31,
SCULPT_TOOL_DISPLACEMENT_SMEAR = 32,
SCULPT_TOOL_MAX,
} eBrushSculptTool;
/** #Brush.uv_sculpt_tool */

View File

@@ -20,6 +20,7 @@ struct CurveMapping;
struct Image;
struct MTex;
struct Material;
struct BrushChannelSet;
typedef struct BrushClone {
/** Image for clone tool. */
@@ -393,6 +394,8 @@ typedef struct Brush {
float automasking_cavity_factor;
struct CurveMapping *automasking_cavity_curve;
struct BrushChannelSet *channels;
} Brush;
/* Struct to hold palette colors for sorting. */

View File

@@ -46,6 +46,7 @@ struct SceneCollection;
struct World;
struct bGPdata;
struct bNodeTree;
struct BrushChannelSet;
/* ************************************************************* */
/* Scene Data */
@@ -1588,6 +1589,8 @@ typedef struct ToolSettings {
/* Unified Paint Settings */
struct UnifiedPaintSettings unified_paint_settings;
struct BrushChannelSet *unified_channels;
IDProperty *unified_properties;
struct CurvePaintSettings curve_paint_settings;
@@ -1604,6 +1607,8 @@ typedef struct ToolSettings {
struct SequencerToolSettings *sequencer_tool_settings;
char brush_editor_mode;
char _pad9[7];
} ToolSettings;
/* *************************************************************** */

View File

@@ -22,6 +22,7 @@ set(DEFSRC
rna_attribute.c
rna_boid.c
rna_brush.c
rna_brush_channels.c
rna_cachefile.c
rna_camera.c
rna_cloth.c

View File

@@ -4496,6 +4496,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_asset.c", NULL, RNA_def_asset},
{"rna_boid.c", NULL, RNA_def_boid},
{"rna_brush.c", NULL, RNA_def_brush},
{"rna_brush_channels.c", NULL, RNA_def_brush_channels},
{"rna_cachefile.c", NULL, RNA_def_cachefile},
{"rna_camera.c", "rna_camera_api.c", RNA_def_camera},
{"rna_cloth.c", NULL, RNA_def_cloth},

View File

@@ -23,6 +23,8 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "BKE_brush_channel.h"
#include "rna_internal.h"
#include "IMB_imbuf.h"
@@ -785,6 +787,8 @@ static void rna_Brush_set_size(PointerRNA *ptr, int value)
/* scale unprojected radius so it stays consistent with brush size */
BKE_brush_scale_unprojected_radius(&brush->unprojected_radius, value, brush->size);
brush->size = value;
BKE_brush_channelset_mark_update(brush->channels, size);
}
static void rna_Brush_use_gradient_set(PointerRNA *ptr, int value)
@@ -3521,6 +3525,16 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Gradient", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "channels", PROP_COLLECTION, 0);
RNA_def_property_collection_sdna(prop, NULL, "channels", NULL);
RNA_def_property_struct_type(prop, "BrushChannel");
RNA_def_property_ui_text(prop, "Channels", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
// RNA_def_property_clear_flag(prop, PROP_PTR_NO_OWNERSHIP);
RNA_def_property_override_flag(
prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY | PROPOVERRIDE_LIBRARY_INSERTION);
RNA_def_brush_channelset(brna, prop, "channels", "Brush");
/* gradient source */
prop = RNA_def_property(srna, "gradient_stroke_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, brush_gradient_items);

View File

@@ -0,0 +1,890 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/** \file
* \ingroup RNA
*/
#include <ctype.h>
#include <stdlib.h>
#include "DNA_ID_enums.h"
#include "DNA_brush_channel_types.h"
#include "DNA_brush_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_listBase.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
#include "DNA_workspace_types.h"
#include "BLI_assert.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "rna_internal.h"
#include "IMB_imbuf.h"
#include "BKE_brush.h"
#include "BKE_brush_channel.h"
#include "BKE_colortools.h"
#include "WM_types.h"
static EnumPropertyItem null_enum[2] = {{0, "null", ICON_NONE, "null"}, {0, NULL, 0, NULL, NULL}};
#ifdef RNA_RUNTIME
# include "RNA_access.h"
# if 0
static void rna_brushchannel_update(Scene *scene, Brush *brush)
{
}
void rna_BrushChannel_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
switch (GS(ptr->owner_id->name)) {
case ID_SCE: {
ToolSettings *ts = scene->toolsettings;
Paint *paints[] = {
&ts->sculpt,
&ts->
};
int paints_num = ARRAY_SIZE(paints);
break;
}
case ID_BR: {
Brush *brush = (Brush *)ptr->owner_id;
rna_brushchannel_update(scene, brush);
break;
}
default:
printf("%s: Invalid PointerRNA, unexpected owner_id \"%s\"\n", __func__, ptr->owner_id->name);
return;
}
}
# endif
void rna_BrushChannel_update_tooltip(PointerRNA *ptr, const char *propname)
{
BrushChannel *ch = (BrushChannel *)ptr->data;
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
if (prop) {
if (prop->description) {
// MEM_SAFE_FREE(prop->description);
}
prop->description = ch->def->tooltip;
}
}
BrushChannelSet *rna_BrushChannelSet_get_set(struct PointerRNA *ptr)
{
BrushChannelSet *chset;
ID *id = ptr->owner_id;
switch (GS(id->name)) {
case ID_BR:
chset = ((Brush *)id)->channels;
break;
case ID_SCE: {
Scene *scene = (Scene *)id;
if (!scene->toolsettings) {
return NULL;
}
chset = scene->toolsettings->unified_channels;
break;
}
default:
return NULL;
}
return chset;
}
int rna_BrushChannelSet_channels_begin(CollectionPropertyIterator *iter, struct PointerRNA *ptr)
{
BrushChannelSet *chset = rna_BrushChannelSet_get_set(ptr);
if (!chset) {
return 0;
}
rna_iterator_listbase_begin(iter, &chset->channels, NULL);
return 1;
}
static BrushChannel *get_paired_radius_channel(PointerRNA *rna)
{
BrushChannel *ch = rna->data;
bool is_radius = STREQ(ch->idname, "size");
bool is_unproj = STREQ(ch->idname, "unprojected_radius");
/*
the way the old brush system split view and scene
radii but presented them as the same to the user,
and also to parts of the API is proving difficult
to disentangle. . . - joeedh
*/
if ((is_radius || is_unproj) && rna->owner_id) {
BrushChannelSet *chset = NULL;
if (GS(rna->owner_id->name) == ID_SCE) {
Scene *scene = ((Scene *)rna->owner_id);
if (scene->toolsettings && scene->toolsettings->sculpt) {
chset = scene->toolsettings->unified_channels;
}
}
else if (GS(rna->owner_id->name) == ID_BR) {
chset = ((Brush *)rna->owner_id)->channels;
}
if (!chset) {
return NULL;
}
return is_radius ? BKE_brush_channelset_lookup(chset, unprojected_radius) :
BKE_brush_channelset_lookup(chset, size);
}
return NULL;
}
static void rna_brushchannel_paired_flag_set(PointerRNA *rna, int flag, bool value)
{
BrushChannel *ch = (BrushChannel *)rna->data;
BrushChannel *ch2 = get_paired_radius_channel(rna);
if (value) {
ch->flag |= flag;
if (ch2) {
ch2->flag |= flag;
}
}
else {
ch->flag &= ~flag;
if (ch2) {
ch2->flag &= ~flag;
}
}
}
bool rna_brushchannel_paired_flag_get(PointerRNA *rna, int flag)
{
BrushChannel *ch = (BrushChannel *)rna->data;
return ch->flag & flag;
}
void rna_BrushChannel_inherit_set(PointerRNA *rna, bool value)
{
rna_brushchannel_paired_flag_set(rna, BRUSH_CHANNEL_INHERIT, value);
}
bool rna_BrushChannel_inherit_get(PointerRNA *rna)
{
return rna_brushchannel_paired_flag_get(rna, BRUSH_CHANNEL_INHERIT);
}
void rna_BrushChannel_unified_set(PointerRNA *rna, bool value)
{
rna_brushchannel_paired_flag_set(rna, BRUSH_CHANNEL_FORCE_INHERIT, value);
}
bool rna_BrushChannel_unified_get(PointerRNA *rna)
{
return rna_brushchannel_paired_flag_get(rna, BRUSH_CHANNEL_FORCE_INHERIT);
}
void rna_BrushChannel_disable_unified_set(PointerRNA *rna, bool value)
{
rna_brushchannel_paired_flag_set(rna, BRUSH_CHANNEL_IGNORE_FORCE_INHERIT, value);
}
bool rna_BrushChannel_disable_unified_get(PointerRNA *rna)
{
return rna_brushchannel_paired_flag_get(rna, BRUSH_CHANNEL_IGNORE_FORCE_INHERIT);
}
PointerRNA rna_BrushMapping_curve_get(PointerRNA *ptr)
{
BrushMapping *mapping = (BrushMapping *)ptr->data;
return rna_pointer_inherit_refine(ptr, &RNA_BrushCurve, &mapping->curve);
}
PointerRNA rna_BrushCurve_curve_get(PointerRNA *ptr)
{
BrushCurve *curve = (BrushCurve *)ptr->data;
if (!curve->curve) {
curve->curve = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
rctf bounds = {0.0f, 1.0f, 0.0f, 1.0f};
BKE_curvemap_reset(curve->curve->cm, &bounds, CURVE_PRESET_LINE, CURVEMAP_SLOPE_POSITIVE);
}
return rna_pointer_inherit_refine(ptr, &RNA_CurveMapping, curve->curve);
}
bool rna_BrushMapping_inherit_get(PointerRNA *ptr)
{
BrushMapping *mp = (BrushMapping *)ptr->data;
return mp->inherit_mode;
}
void rna_BrushMapping_inherit_set(PointerRNA *ptr, bool val)
{
BrushMapping *mp = (BrushMapping *)ptr->data;
if (val) {
mp->inherit_mode = BRUSH_MAPPING_INHERIT_ALWAYS;
}
else {
mp->inherit_mode = BRUSH_MAPPING_INHERIT_NEVER;
}
}
int rna_BrushChannel_mappings_begin(CollectionPropertyIterator *iter, struct PointerRNA *ptr)
{
BrushChannel *ch = ptr->data;
rna_iterator_array_begin(
iter, ch->mappings, sizeof(BrushMapping), BRUSH_MAPPING_MAX, false, NULL);
return 1;
}
int rna_BrushChannel_mappings_lookupstring(PointerRNA *rna, const char *key, PointerRNA *r_ptr)
{
BrushChannel *ch = (BrushChannel *)rna->data;
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
if (STREQ(key, BKE_brush_mapping_type_to_typename(i))) {
if (r_ptr) {
*r_ptr = rna_pointer_inherit_refine(rna, &RNA_BrushMapping, ch->mappings + i);
}
return 1;
}
}
return 0;
}
int rna_BrushChannel_mappings_length(PointerRNA *ptr)
{
return BRUSH_MAPPING_MAX;
}
int lookup_icon_id(const char *icon)
{
const EnumPropertyItem *item = rna_enum_icon_items;
int i = 0;
while (item->identifier) {
if (STREQ(item->identifier, icon)) {
return i;
}
item++;
i++;
}
return ICON_NONE;
}
static int rna_enum_check_separator(CollectionPropertyIterator *UNUSED(iter), void *data)
{
EnumPropertyItem *item = (EnumPropertyItem *)data;
return (item->identifier[0] == 0);
}
char *rna_BrushChannel_rnapath(const PointerRNA *ptr)
{
BrushChannel *ch = (BrushChannel *)ptr->data;
if (!ptr->owner_id) {
return NULL;
}
if (GS(ptr->owner_id->name) == ID_BR) {
return BLI_sprintfN("channels[\"%s\"]", ch->idname);
}
else if (GS(ptr->owner_id->name) == ID_SCE) {
return BLI_sprintfN("tool_settings.unified_channels[\"%s\"]", ch->idname);
}
else {
return NULL;
}
}
char *rna_BrushMapping_rnapath(const PointerRNA *ptr)
{
BrushMapping *mp = (BrushMapping *)ptr->data;
if (!ptr->owner_id) {
return NULL;
}
BrushChannelSet *chset;
switch (GS(ptr->owner_id->name)) {
case ID_SCE: {
Scene *scene = (Scene *)ptr->owner_id;
chset = scene->toolsettings->unified_channels;
break;
}
case ID_BR: {
Brush *brush = (Brush *)ptr->owner_id;
chset = brush->channels;
break;
}
default:
BLI_assert_unreachable();
return NULL;
}
BrushChannel *active_ch = NULL;
LISTBASE_FOREACH (BrushChannel *, ch, &chset->channels) {
if (active_ch) {
break;
}
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
if (mp == ch->mappings + i) {
active_ch = ch;
break;
}
}
}
if (!active_ch) {
BLI_assert_unreachable();
return NULL;
}
switch (GS(ptr->owner_id->name)) {
case ID_SCE:
return BLI_sprintfN("tool_settings.unified_channels[\"%s\"].mappings[\"%s\"]",
active_ch->idname,
BKE_brush_mapping_type_to_typename(mp->type));
case ID_BR:
return BLI_sprintfN("channels[\"%s\"].mappings[\"%s\"]",
active_ch->idname,
BKE_brush_mapping_type_to_typename(mp->type));
default:
BLI_assert_unreachable();
return NULL;
}
}
void rna_BrushChannelSet_ensure(ID *id, const char *idname)
{
PointerRNA ptr;
ptr.owner_id = id;
ptr.data = NULL;
ptr.type = NULL;
BrushChannelSet *chset = rna_BrushChannelSet_get_set(&ptr);
if (chset) {
_BKE_brush_channelset_ensure(chset, idname);
}
}
int rna_BrushChannelSet_length(PointerRNA *ptr)
{
BrushChannelSet *chset = rna_BrushChannelSet_get_set(ptr);
// BrushChannelSet *chset = (BrushChannelSet *)ptr->data;
return chset->channels_num;
}
void rna_BrushChannel_category_get(PointerRNA *ptr, char *value)
{
strcpy(value, BKE_brush_channel_category_get((BrushChannel *)ptr->data));
}
int rna_BrushChannel_category_length(PointerRNA *ptr)
{
return strlen(BKE_brush_channel_category_get((BrushChannel *)ptr->data));
}
void rna_BrushChannel_rna_path_get(PointerRNA *ptr, char *value)
{
strcpy(value, BKE_brush_channel_rna_path(ptr->owner_id, (BrushChannel *)ptr->data));
}
int rna_BrushChannel_rna_path_length(PointerRNA *ptr)
{
return strlen(BKE_brush_channel_rna_path(ptr->owner_id, (BrushChannel *)ptr->data));
}
int rna_BrushChannel_factor_value_editable(PointerRNA *ptr, const char **r_info)
{
return 1;
}
bool rna_BrushChannel_get_is_color(PointerRNA *ptr)
{
BrushChannel *ch = (BrushChannel *)ptr->data;
return ch && ch->def ? ch->def->subtype == BRUSH_CHANNEL_COLOR : false;
}
void rna_BrushChannel_category_set(PointerRNA *ptr, const char *value)
{
BKE_brush_channel_category_set((BrushChannel *)ptr->data, value);
}
static void channel_uiflag_set(PointerRNA *ptr, bool value, int flag, int user_set_flag)
{
BrushChannel *ch = (BrushChannel *)ptr->data;
if (value) {
ch->ui_flag |= flag;
}
else {
ch->ui_flag &= ~flag;
}
ch->ui_flag |= user_set_flag;
}
void rna_BrushChannel_show_in_header_set(PointerRNA *ptr, bool value)
{
channel_uiflag_set(
ptr, value, BRUSH_CHANNEL_SHOW_IN_HEADER, BRUSH_CHANNEL_SHOW_IN_HEADER_USER_SET);
}
void rna_BrushChannel_show_in_workspace_set(PointerRNA *ptr, bool value)
{
channel_uiflag_set(
ptr, value, BRUSH_CHANNEL_SHOW_IN_WORKSPACE, BRUSH_CHANNEL_SHOW_IN_WORKSPACE_USER_SET);
}
void rna_BrushChannel_show_in_context_menu_set(PointerRNA *ptr, bool value)
{
channel_uiflag_set(
ptr, value, BRUSH_CHANNEL_SHOW_IN_CONTEXT_MENU, BRUSH_CHANNEL_SHOW_IN_CONTEXT_MENU_USER_SET);
}
#else
static EnumPropertyItem mapping_type_items[] = {
{BRUSH_MAPPING_PRESSURE, "PRESSURE", ICON_NONE, "Pressure"},
{BRUSH_MAPPING_XTILT, "XTILT", ICON_NONE, "X Tilt"},
{BRUSH_MAPPING_YTILT, "YTILT", ICON_NONE, "Y Tilt"},
{BRUSH_MAPPING_ANGLE, "ANGLE", ICON_NONE, "Angle"},
{BRUSH_MAPPING_SPEED, "SPEED", ICON_NONE, "Speed"},
{BRUSH_MAPPING_RANDOM, "RANDOM", ICON_NONE, "Random"},
{BRUSH_MAPPING_STROKE_T, "DISTANCE", ICON_NONE, "Distance"},
{0, NULL, 0, NULL, NULL},
};
void RNA_def_brush_mapping(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "BrushMapping", NULL);
RNA_def_struct_sdna(srna, "BrushMapping");
RNA_def_struct_ui_text(srna, "Brush Mapping", "Brush Mapping");
RNA_def_struct_path_func(srna, "rna_BrushMapping_rnapath");
prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "factor");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Factor", "Mapping factor");
prop = RNA_def_property(srna, "premultiply", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "premultiply_factor");
RNA_def_property_range(prop, -100000, 100000);
RNA_def_property_ui_range(prop, -100, 100, 0.01, 3);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Pre-Multiply", "Multiply input data by this amount");
prop = RNA_def_property(srna, "func_cutoff", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "func_cutoff");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Cutoff", "Cutoff for square and cutoff modes");
prop = RNA_def_property(srna, "min", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "min");
RNA_def_property_range(prop, -100000, 100000);
RNA_def_property_ui_range(prop, -2.0, 2.0, 0.001, 3);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Min", "");
prop = RNA_def_property(srna, "max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max");
RNA_def_property_range(prop, -100000, 100000);
RNA_def_property_ui_range(prop, -2.0, 2.0, 0.001, 3);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Max", "");
static EnumPropertyItem inherit_mode_items[] = {
{BRUSH_MAPPING_INHERIT_NEVER, "NEVER", ICON_NONE, "Never", "Never use unified settings."},
{BRUSH_MAPPING_INHERIT_ALWAYS,
"ALWAYS",
ICON_NONE,
"Always",
"Always use settings from unified channel."},
{BRUSH_MAPPING_INHERIT_CHANNEL,
"USE_CHANNEL",
ICON_NONE,
"If Enabled",
"Use unified settings if enabled in channel that owns this mapping."},
{0, NULL, 0, NULL, NULL}};
prop = RNA_def_property(srna, "inherit_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "inherit_mode");
RNA_def_property_enum_items(prop, inherit_mode_items);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "inherit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "inherit_mode", BRUSH_MAPPING_INHERIT_ALWAYS);
RNA_def_property_ui_text(prop, "Inherit", "Inherit from scene channel");
RNA_def_property_boolean_funcs(
prop, "rna_BrushMapping_inherit_get", "rna_BrushMapping_inherit_set");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "BrushCurve");
RNA_def_property_ui_text(prop, "Curve Sensitivity", "Curve used for the sensitivity");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_pointer_funcs(prop, "rna_BrushMapping_curve_get", NULL, NULL, NULL);
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, mapping_type_items);
RNA_def_property_clear_flag(prop, PROP_EDITABLE | PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Type", "Channel Type");
prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_MAPPING_ENABLED);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Enabled", "Input Mapping Is Enabled");
prop = RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_MAPPING_INVERT);
RNA_def_property_ui_icon(prop, ICON_ARROW_LEFTRIGHT, 0);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Enabled", "Input Mapping Is Enabled");
static EnumPropertyItem blend_items[] = {
{MA_RAMP_BLEND, "MIX", ICON_NONE, "Mix", ""},
{MA_RAMP_MULT, "MULTIPLY", ICON_NONE, "Multiply", ""},
{MA_RAMP_DIV, "DIVIDE", ICON_NONE, "Divide", ""},
{MA_RAMP_ADD, "ADD", ICON_NONE, "Add", ""},
{MA_RAMP_SUB, "SUBTRACT", ICON_NONE, "Subtract", ""},
{MA_RAMP_DIFF, "DIFFERENCE", ICON_NONE, "Difference", ""},
{0, NULL, 0, NULL, NULL}};
prop = RNA_def_property(srna, "blendmode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, blend_items);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Blend Mode", "Input mapping blend mode");
static EnumPropertyItem mapfunc_items[] = {
{BRUSH_MAPFUNC_NONE, "NONE", ICON_NONE, "None", "Pass data through unmodified"},
{BRUSH_MAPFUNC_SQUARE, "SQUARE", ICON_NONE, "Square", "Square wave"},
{BRUSH_MAPFUNC_SAW, "SAW", ICON_NONE, "Saw", "Sawtooth wave"},
{BRUSH_MAPFUNC_TENT, "TENT", ICON_NONE, "Tent", "Tent wave"},
{BRUSH_MAPFUNC_COS, "COS", ICON_NONE, "Cos", "Cosine wave"},
{BRUSH_MAPFUNC_CUTOFF, "CUTOFF", ICON_NONE, "Cutoff", "Inverts data and cuts off at 1.0"},
{0, NULL, 0, NULL, NULL}};
prop = RNA_def_property(srna, "mapfunc", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, mapfunc_items);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Function", "Input data function");
prop = RNA_def_property(srna, "ui_expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_MAPPING_UI_EXPANDED);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Expanded", "View advanced properties");
}
extern BrushChannelType *brush_builtin_channels;
extern const int builtin_channel_len;
EnumPropertyItem channel_types[] = {{BRUSH_CHANNEL_TYPE_FLOAT, "FLOAT", ICON_NONE, "Float"},
{BRUSH_CHANNEL_TYPE_INT, "INT", ICON_NONE, "Int"},
{BRUSH_CHANNEL_TYPE_ENUM, "ENUM", ICON_NONE, "Enum"},
{BRUSH_CHANNEL_TYPE_BITMASK, "BITMASK", ICON_NONE, "Bitmask"},
{BRUSH_CHANNEL_TYPE_BOOL, "BOOL", ICON_NONE, "Boolean"},
{BRUSH_CHANNEL_TYPE_VEC3, "VEC3", ICON_NONE, "Color3"},
{BRUSH_CHANNEL_TYPE_VEC4, "VEC4", ICON_NONE, "Color4"},
{BRUSH_CHANNEL_TYPE_CURVE, "CURVE", ICON_NONE, "Curve"},
{0, NULL, 0, NULL, NULL}};
// getting weird link errors here
// extern const EnumPropertyItem brush_curve_preset_items[];
static const EnumPropertyItem brush_curve_preset_items[] = {
{BRUSH_CURVE_CUSTOM, "CUSTOM", ICON_RNDCURVE, "Custom", ""},
{BRUSH_CURVE_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""},
{BRUSH_CURVE_SMOOTHER, "SMOOTHER", ICON_SMOOTHCURVE, "Smoother", ""},
{BRUSH_CURVE_SPHERE, "SPHERE", ICON_SPHERECURVE, "Sphere", ""},
{BRUSH_CURVE_ROOT, "ROOT", ICON_ROOTCURVE, "Root", ""},
{BRUSH_CURVE_SHARP, "SHARP", ICON_SHARPCURVE, "Sharp", ""},
{BRUSH_CURVE_LIN, "LIN", ICON_LINCURVE, "Linear", ""},
{BRUSH_CURVE_POW4, "POW4", ICON_SHARPCURVE, "Sharper", ""},
{BRUSH_CURVE_INVSQUARE, "INVSQUARE", ICON_INVERSESQUARECURVE, "Inverse Square", ""},
{BRUSH_CURVE_CONSTANT, "CONSTANT", ICON_NOCURVE, "Constant", ""},
{0, NULL, 0, NULL, NULL},
};
void RNA_def_brush_curve(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "BrushCurve", NULL);
RNA_def_struct_sdna(srna, "BrushCurve");
RNA_def_struct_ui_text(srna, "Brush Curve", "Brush Curve");
prop = RNA_def_property(srna, "curve_preset", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, "BrushCurve", "preset");
RNA_def_property_enum_items(prop, brush_curve_preset_items);
RNA_def_property_ui_text(prop, "Curve Pre set", "");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "CurveMapping");
RNA_def_property_ui_text(prop, "Curve Sensitivity", "Curve used for the sensitivity");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_pointer_funcs(prop, "rna_BrushCurve_curve_get", NULL, NULL, NULL);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_property(srna, "preset_slope_negative", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(prop, "Negative Slope", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
}
void RNA_def_brush_channel(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "BrushChannel", NULL);
RNA_def_struct_sdna(srna, "BrushChannel");
RNA_def_struct_ui_text(srna, "Brush Channel", "Brush Channel");
RNA_def_struct_path_func(srna, "rna_BrushChannel_rnapath");
// RNA_def_struct_refine_func(srna, "rna_BrushChannel_refine");
prop = RNA_def_property(srna, "idname", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, "BrushChannel", "idname");
RNA_def_property_clear_flag(prop, PROP_EDITABLE | PROP_ANIMATABLE);
RNA_def_struct_name_property(srna, prop);
prop = RNA_def_property(srna, "rna_path", PROP_STRING, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE | PROP_ANIMATABLE);
RNA_def_property_string_funcs(
prop, "rna_BrushChannel_rna_path_get", "rna_BrushChannel_rna_path_length", NULL);
prop = RNA_def_property(srna, "category", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop,
"rna_BrushChannel_category_get",
"rna_BrushChannel_category_length",
"rna_BrushChannel_category_set");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, "BrushChannel", "uiname");
RNA_def_property_clear_flag(prop, PROP_EDITABLE | PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Name", "Channel name");
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, "BrushChannel", "type");
RNA_def_property_enum_items(prop, channel_types);
RNA_def_property_clear_flag(prop, PROP_EDITABLE | PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Type", "Value Type");
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, "inherit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(prop, "Inherit", "Inherit from scene defaults");
RNA_def_property_boolean_funcs(
prop, "rna_BrushChannel_inherit_get", "rna_BrushChannel_inherit_set");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_property(srna, "disable_unified", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(prop,
"Disable Unified",
"Don't allow unified settings for this channel. Local brush setting.");
RNA_def_property_boolean_funcs(
prop, "rna_BrushChannel_disable_unified_get", "rna_BrushChannel_disable_unified_set");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_property(srna, "unified", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(prop, "Unified", "Force brushes to use default properties");
RNA_def_property_boolean_funcs(
prop, "rna_BrushChannel_unified_get", "rna_BrushChannel_unified_set");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_property(srna, "show_in_header", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, "BrushChannel", "ui_flag", BRUSH_CHANNEL_SHOW_IN_HEADER);
RNA_def_property_ui_text(prop, "In Header", "Show in header");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_boolean_funcs(prop, NULL, "rna_BrushChannel_show_in_header_set");
prop = RNA_def_property(srna, "show_in_workspace", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, "BrushChannel", "ui_flag", BRUSH_CHANNEL_SHOW_IN_WORKSPACE);
RNA_def_property_ui_text(prop, "In Workspace", "Show in workspace");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_boolean_funcs(prop, NULL, "rna_BrushChannel_show_in_workspace_set");
prop = RNA_def_property(srna, "show_in_context_menu", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, "BrushChannel", "ui_flag", BRUSH_CHANNEL_SHOW_IN_CONTEXT_MENU);
RNA_def_property_ui_text(prop, "In Workspace", "Show in workspace");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_boolean_funcs(prop, NULL, "rna_BrushChannel_show_in_context_menu_set");
prop = RNA_def_property(srna, "is_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(prop, "Is Color", "Is this channel a color");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_boolean_funcs(prop, "rna_BrushChannel_get_is_color", NULL);
prop = RNA_def_property(srna, "ui_expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, "BrushChannel", "flag", BRUSH_CHANNEL_UI_EXPANDED);
RNA_def_property_ui_text(prop, "Expanded", "View advanced properties");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_property(srna, "inherit_if_unset", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, "BrushChannel", "flag", BRUSH_CHANNEL_INHERIT_IF_UNSET);
RNA_def_property_ui_text(prop, "Combine", "Combine with default settings");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_property(srna, "mappings", PROP_COLLECTION, PROP_NONE);
// RNA_def_property_collection_sdna(prop, "BrushChannel", "mappings", NULL);
RNA_def_property_collection_funcs(prop,
"rna_BrushChannel_mappings_begin",
"rna_iterator_array_next",
"rna_iterator_array_end",
"rna_iterator_array_get",
"rna_BrushChannel_mappings_length",
NULL,
"rna_BrushChannel_mappings_lookupstring",
NULL);
RNA_def_property_struct_type(prop, "BrushMapping");
prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "BrushCurve");
RNA_def_property_ui_text(prop, "Curve", "Curve");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_property(srna, "active_mapping", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, mapping_type_items);
RNA_def_property_enum_sdna(prop, NULL, "active_mapping");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Active Mapping", "");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
}
void RNA_def_brush_channelset(BlenderRNA *brna,
PropertyRNA *cprop,
const char *propname,
const char *type_prefix)
{
StructRNA *srna;
PropertyRNA *prop;
FunctionRNA *func;
PropertyRNA *parm;
char buf[256], *name;
sprintf(buf, "%sBrushChannels", type_prefix);
name = strdup(buf);
RNA_def_property_srna(cprop, name);
srna = RNA_def_struct(brna, name, NULL);
RNA_def_struct_sdna(srna, "BrushChannelSet");
RNA_def_struct_ui_text(srna, "Brush Channels", "Collection of brush channels");
// srna = RNA_def_struct(brna, "BrushChannelSet", NULL);
// RNA_def_struct_sdna(srna, "BrushChannelSet");
// RNA_def_struct_ui_text(srna, "Channel Set", "Brush Channel Collection");
func = RNA_def_function(srna, "ensure", "rna_BrushChannelSet_ensure");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF);
parm = RNA_def_string(func, "channel", NULL, 64, "Channel", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
// RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
// prop = RNA_def_property(srna, "channels", PROP_COLLECTION, PROP_NONE);
prop = cprop;
RNA_def_property_collection_sdna(prop, NULL, propname, NULL);
RNA_def_property_collection_funcs(prop,
"rna_BrushChannelSet_channels_begin",
"rna_iterator_listbase_next",
"rna_iterator_listbase_end",
"rna_iterator_listbase_get",
"rna_BrushChannelSet_length",
NULL,
NULL,
NULL);
RNA_def_property_struct_type(prop, "BrushChannel");
RNA_def_property_clear_flag(prop, PROP_PTR_NO_OWNERSHIP);
RNA_def_property_flag(prop, PROP_THICK_WRAP | PROP_DYNAMIC);
RNA_def_property_override_flag(
prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY | PROPOVERRIDE_LIBRARY_INSERTION);
}
void RNA_def_brush_channels(BlenderRNA *brna)
{
RNA_def_brush_curve(brna);
RNA_def_brush_mapping(brna);
RNA_def_brush_channel(brna);
}
#endif

View File

@@ -31,6 +31,7 @@ struct Object;
struct ReportList;
struct SDNA;
struct ViewLayer;
struct BrushChannel;
/* Data structures used during define */
@@ -146,6 +147,11 @@ void RNA_def_attribute(struct BlenderRNA *brna);
void RNA_def_asset(struct BlenderRNA *brna);
void RNA_def_boid(struct BlenderRNA *brna);
void RNA_def_brush(struct BlenderRNA *brna);
void RNA_def_brush_channels(struct BlenderRNA *brna);
void RNA_def_brush_channelset(BlenderRNA *brna,
PropertyRNA *cprop,
const char *propname,
const char *type_prefix);
void RNA_def_cachefile(struct BlenderRNA *brna);
void RNA_def_camera(struct BlenderRNA *brna);
void RNA_def_cloth(struct BlenderRNA *brna);
@@ -412,6 +418,14 @@ char *rna_TextureSlot_path(const struct PointerRNA *ptr);
char *rna_Node_ImageUser_path(const struct PointerRNA *ptr);
char *rna_CameraBackgroundImage_image_or_movieclip_user_path(const struct PointerRNA *ptr);
int rna_BrushChannelSet_channels_assignint(struct PointerRNA *ptr,
int key,
const struct PointerRNA *assign_ptr);
int rna_BrushChannelSet_channels_begin(struct CollectionPropertyIterator *iter,
struct PointerRNA *ptr);
int rna_BrushChannelSet_length(struct PointerRNA *rna);
void rna_BrushChannelSet_ensure(struct ID *id, const char *idname);
/* Set U.is_dirty and redraw. */
/**

View File

@@ -346,14 +346,15 @@ static bool rna_path_parse_array_index(const char **path,
*
* \return \a true on success, \a false if the path is somehow invalid.
*/
static bool rna_path_parse(const PointerRNA *ptr,
const char *path,
PointerRNA *r_ptr,
PropertyRNA **r_prop,
int *r_index,
PointerRNA *r_item_ptr,
ListBase *r_elements,
const bool eval_pointer)
#include "BKE_brush_channel.h"
ATTR_NO_OPT static bool rna_path_parse(const PointerRNA *ptr,
const char *path,
PointerRNA *r_ptr,
PropertyRNA **r_prop,
int *r_index,
PointerRNA *r_item_ptr,
ListBase *r_elements,
const bool eval_pointer)
{
BLI_assert(r_item_ptr == nullptr || !eval_pointer);
PropertyRNA *prop;

View File

@@ -29,6 +29,7 @@
#include "BLT_translation.h"
#include "BKE_armature.h"
#include "BKE_brush_channel.h"
#include "BKE_editmesh.h"
#include "BKE_idtype.h"
#include "BKE_paint.h"
@@ -2202,6 +2203,15 @@ static void rna_UnifiedPaintSettings_update(bContext *C, PointerRNA *UNUSED(ptr)
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
}
static int rna_UnifiedPaintSettings_size_get(PointerRNA *ptr)
{
Scene *scene = (Scene*)ptr->owner_id;
PointerRNA prop_ptr;
RNA_pointer_create(&scene->id, &RNA_UnifiedBrushProperties, scene->toolsettings, &prop_ptr);
return RNA_int_get(&prop_ptr, "[\"size\"]");
}
static void rna_UnifiedPaintSettings_size_set(PointerRNA *ptr, int value)
{
UnifiedPaintSettings *ups = ptr->data;
@@ -2209,6 +2219,16 @@ static void rna_UnifiedPaintSettings_size_set(PointerRNA *ptr, int value)
/* scale unprojected radius so it stays consistent with brush size */
BKE_brush_scale_unprojected_radius(&ups->unprojected_radius, value, ups->size);
ups->size = value;
Scene *scene = (Scene *)ptr->owner_id;
PointerRNA prop_ptr;
RNA_pointer_create(
&scene->id, &RNA_UnifiedBrushProperties, scene->toolsettings, &prop_ptr);
RNA_int_set(&prop_ptr, "[\"size\"]", ups->size);
RNA_float_set(&prop_ptr, "[\"unprojected_radius\"]", ups->unprojected_radius);
BKE_brush_channelset_mark_update(scene->toolsettings->unified_channels, size);
}
static void rna_UnifiedPaintSettings_unprojected_radius_set(PointerRNA *ptr, float value)
@@ -2776,6 +2796,41 @@ static void rna_FFmpegSettings_codec_update(Main *UNUSED(bmain),
}
# endif
static IDProperty **rna_UnifiedBrushProperties_idprops(PointerRNA *ptr)
{
ToolSettings *ts = ptr->data;
return &ts->unified_properties;
}
static PointerRNA rna_ToolSettings_unified_properties_get(PointerRNA *ptr)
{
PointerRNA ret = *ptr;
ret.type = &RNA_UnifiedBrushProperties;
return ret;
}
bool rna_UnifiedPaintSettings_use_unified_size_get(PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->owner_id;
BrushChannel *ch = BKE_brush_channelset_lookup(scene->toolsettings->unified_channels, size);
return ch->flag & BRUSH_CHANNEL_FORCE_INHERIT;
}
void rna_UnifiedPaintSettings_use_unified_size_set(PointerRNA *ptr, bool val)
{
Scene *scene = (Scene *)ptr->owner_id;
BrushChannel *ch = BKE_brush_channelset_lookup(scene->toolsettings->unified_channels, size);
if (val) {
ch->flag |= BRUSH_CHANNEL_FORCE_INHERIT;
}
else {
ch->flag &= ~BRUSH_CHANNEL_FORCE_INHERIT;
}
}
#else
/* Grease Pencil Interpolation tool settings */
@@ -2912,6 +2967,17 @@ static void rna_def_view3d_cursor(BlenderRNA *brna)
prop, "rna_View3DCursor_matrix_get", "rna_View3DCursor_matrix_set", NULL);
}
static void rna_def_unified_brush_properties(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "UnifiedBrushProperties", NULL);
/* The struct has custom properties, but no pointer properties to other IDs! */
RNA_def_struct_idprops_func(srna, "rna_UnifiedBrushProperties_idprops");
RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); /* Mandatory! */
}
static void rna_def_tool_settings(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3053,6 +3119,28 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_ToolSettings_path");
RNA_def_struct_ui_text(srna, "Tool Settings", "");
rna_def_unified_brush_properties(brna);
prop = RNA_def_property(srna, "brush_editor_mode", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "brush_editor_mode", 1);
RNA_def_property_ui_text(prop, "Brush Editor Mode", "");
prop = RNA_def_property(srna, "unified_properties", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "UnifiedBrushProperties");
RNA_def_property_ui_text(prop, "Unified Brush Property Storage", "");
RNA_def_property_pointer_funcs(
prop, "rna_ToolSettings_unified_properties_get", NULL, NULL, NULL);
prop = RNA_def_property(srna, "unified_channels", PROP_COLLECTION, 0);
RNA_def_property_collection_sdna(prop, NULL, "unified_channels", NULL);
RNA_def_property_struct_type(prop, "BrushChannel");
RNA_def_property_ui_text(prop, "Channels", "");
// RNA_def_property_clear_flag(prop, PROP_PTR_NO_OWNERSHIP);
RNA_def_property_override_flag(
prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY | PROPOVERRIDE_LIBRARY_INSERTION);
RNA_def_property_ui_text(prop, "Unified Brush Channels", "");
RNA_def_brush_channelset(brna, prop, "unified_channels", "Scene");
prop = RNA_def_property(srna, "sculpt", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Sculpt");
RNA_def_property_ui_text(prop, "Sculpt", "");
@@ -3872,6 +3960,10 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
/* high-level flags to enable or disable unified paint settings */
prop = RNA_def_property(srna, "use_unified_size", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", UNIFIED_PAINT_SIZE);
RNA_def_property_boolean_funcs(prop,
"rna_UnifiedPaintSettings_use_unified_size_get",
"rna_UnifiedPaintSettings_use_unified_size_set");
RNA_def_property_ui_text(prop,
"Use Unified Radius",
"Instead of per-brush radius, the radius is shared across brushes");
@@ -3896,7 +3988,7 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
/* unified paint settings that override the equivalent settings
* from the active brush */
prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
RNA_def_property_int_funcs(prop, NULL, "rna_UnifiedPaintSettings_size_set", NULL);
RNA_def_property_int_funcs(prop, "rna_UnifiedPaintSettings_size_get", "rna_UnifiedPaintSettings_size_set", NULL);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS * 10);
RNA_def_property_ui_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS, 1, -1);