Paint: Store brush and palette colors in scene linear colorspace
For historical reasons these were stored in sRGB space, which caused all kinds of complexity. * For image painting, it now properly uses the byte buffer colorspace instead of assuming sRGB or display colorspace. This can be more expensive, so there is a fast path for sRGB buffers (and for fixed brush colors). * Lots of code was changed to remove conversion when painting float images or vertex colors, and added when painting byte images. * For non-color data, there is now no colorspace conversion between the brush color and image pixels, and #143642 was basically reverted because of that. Compatibility notes: * Backwards compatibility is not perfect, as we can not determine if the brush has non-color data in isolation. We always convert sRGB to linear, and existing brushes configured with non-color data need to be manually fixed. * There is forward compatibility, the old sRGB value is still stored next to the scene linear value. Pull Request: https://projects.blender.org/blender/blender/pulls/144400
This commit is contained in:
@@ -27,7 +27,7 @@
|
||||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 64
|
||||
#define BLENDER_FILE_SUBVERSION 65
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
||||
|
||||
@@ -185,6 +185,9 @@ std::optional<BrushColorJitterSettings> BKE_brush_color_jitter_get_settings(cons
|
||||
const float *BKE_brush_secondary_color_get(const Paint *paint, const Brush *brush);
|
||||
void BKE_brush_color_set(Paint *paint, Brush *brush, const float color[3]);
|
||||
|
||||
void BKE_brush_color_sync_legacy(Brush *brush);
|
||||
void BKE_brush_color_sync_legacy(UnifiedPaintSettings *ups);
|
||||
|
||||
int BKE_brush_size_get(const Paint *paint, const Brush *brush);
|
||||
void BKE_brush_size_set(Paint *paint, Brush *brush, int size);
|
||||
|
||||
|
||||
@@ -140,11 +140,14 @@ bool BKE_palette_is_empty(const Palette *palette);
|
||||
void BKE_palette_color_remove(Palette *palette, PaletteColor *color);
|
||||
void BKE_palette_clear(Palette *palette);
|
||||
|
||||
void BKE_palette_color_set(PaletteColor *color, const float rgb[3]);
|
||||
void BKE_palette_color_sync_legacy(PaletteColor *color);
|
||||
|
||||
void BKE_palette_sort_hsv(tPaletteColorHSV *color_array, int totcol);
|
||||
void BKE_palette_sort_svh(tPaletteColorHSV *color_array, int totcol);
|
||||
void BKE_palette_sort_vhs(tPaletteColorHSV *color_array, int totcol);
|
||||
void BKE_palette_sort_luminance(tPaletteColorHSV *color_array, int totcol);
|
||||
bool BKE_palette_from_hash(Main *bmain, GHash *color_table, const char *name, bool linear);
|
||||
bool BKE_palette_from_hash(Main *bmain, GHash *color_table, const char *name);
|
||||
|
||||
/* Paint curves. */
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_base.hh"
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_rand.h"
|
||||
|
||||
#include "BLT_translation.hh"
|
||||
@@ -543,8 +544,8 @@ static void brush_defaults(Brush *brush)
|
||||
FROM_DEFAULT(fill_threshold);
|
||||
FROM_DEFAULT(flag);
|
||||
FROM_DEFAULT(sampling_flag);
|
||||
FROM_DEFAULT_PTR(rgb);
|
||||
FROM_DEFAULT_PTR(secondary_rgb);
|
||||
FROM_DEFAULT_PTR(color);
|
||||
FROM_DEFAULT_PTR(secondary_color);
|
||||
FROM_DEFAULT(spacing);
|
||||
FROM_DEFAULT(smooth_stroke_radius);
|
||||
FROM_DEFAULT(smooth_stroke_factor);
|
||||
@@ -1119,9 +1120,9 @@ float BKE_brush_sample_masktex(
|
||||
const float *BKE_brush_color_get(const Paint *paint, const Brush *brush)
|
||||
{
|
||||
if (BKE_paint_use_unified_color(paint)) {
|
||||
return paint->unified_paint_settings.rgb;
|
||||
return paint->unified_paint_settings.color;
|
||||
}
|
||||
return brush->rgb;
|
||||
return brush->color;
|
||||
}
|
||||
|
||||
/** Get color jitter settings if enabled. */
|
||||
@@ -1133,7 +1134,7 @@ std::optional<BrushColorJitterSettings> BKE_brush_color_jitter_get_settings(cons
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const UnifiedPaintSettings settings = paint->unified_paint_settings;
|
||||
const UnifiedPaintSettings &settings = paint->unified_paint_settings;
|
||||
return BrushColorJitterSettings{
|
||||
settings.color_jitter_flag,
|
||||
settings.hsv_jitter[0],
|
||||
@@ -1163,23 +1164,39 @@ std::optional<BrushColorJitterSettings> BKE_brush_color_jitter_get_settings(cons
|
||||
const float *BKE_brush_secondary_color_get(const Paint *paint, const Brush *brush)
|
||||
{
|
||||
if (BKE_paint_use_unified_color(paint)) {
|
||||
return paint->unified_paint_settings.secondary_rgb;
|
||||
return paint->unified_paint_settings.secondary_color;
|
||||
}
|
||||
return brush->secondary_rgb;
|
||||
return brush->secondary_color;
|
||||
}
|
||||
|
||||
void BKE_brush_color_set(Paint *paint, Brush *brush, const float color[3])
|
||||
{
|
||||
if (BKE_paint_use_unified_color(paint)) {
|
||||
UnifiedPaintSettings *ups = &paint->unified_paint_settings;
|
||||
copy_v3_v3(ups->rgb, color);
|
||||
copy_v3_v3(ups->color, color);
|
||||
BKE_brush_color_sync_legacy(ups);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(brush->rgb, color);
|
||||
copy_v3_v3(brush->color, color);
|
||||
BKE_brush_tag_unsaved_changes(brush);
|
||||
BKE_brush_color_sync_legacy(brush);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_brush_color_sync_legacy(Brush *brush)
|
||||
{
|
||||
/* For forward compatibility. */
|
||||
linearrgb_to_srgb_v3_v3(brush->rgb, brush->color);
|
||||
linearrgb_to_srgb_v3_v3(brush->secondary_rgb, brush->secondary_color);
|
||||
}
|
||||
|
||||
void BKE_brush_color_sync_legacy(UnifiedPaintSettings *ups)
|
||||
{
|
||||
/* For forward compatibility. */
|
||||
linearrgb_to_srgb_v3_v3(ups->rgb, ups->color);
|
||||
linearrgb_to_srgb_v3_v3(ups->secondary_rgb, ups->secondary_color);
|
||||
}
|
||||
|
||||
void BKE_brush_size_set(Paint *paint, Brush *brush, int size)
|
||||
{
|
||||
UnifiedPaintSettings *ups = &paint->unified_paint_settings;
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
|
||||
#include "BLO_read_write.hh"
|
||||
|
||||
#include "IMB_colormanagement.hh"
|
||||
|
||||
static CLG_LogRef LOG = {"geom.gpencil"};
|
||||
|
||||
static void greasepencil_copy_data(Main * /*bmain*/,
|
||||
@@ -1197,7 +1199,8 @@ void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene)
|
||||
/* Create Colors. */
|
||||
for (int i = 0; i < ARRAY_SIZE(hexcol); i++) {
|
||||
PaletteColor *palcol = BKE_palette_color_add(palette);
|
||||
hex_to_rgb(hexcol[i], palcol->rgb, palcol->rgb + 1, palcol->rgb + 2);
|
||||
hex_to_rgb(hexcol[i], palcol->color, palcol->color + 1, palcol->color + 2);
|
||||
IMB_colormanagement_srgb_to_scene_linear_v3(palcol->color, palcol->color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
/* ALlow using deprecated color for sync legacy. */
|
||||
#define DNA_DEPRECATED_ALLOW
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
@@ -73,6 +76,8 @@
|
||||
|
||||
#include "BLO_read_write.hh"
|
||||
|
||||
#include "IMB_colormanagement.hh"
|
||||
|
||||
#include "bmesh.hh"
|
||||
|
||||
using blender::float3;
|
||||
@@ -1401,6 +1406,17 @@ void BKE_palette_clear(Palette *palette)
|
||||
palette->active_color = 0;
|
||||
}
|
||||
|
||||
void BKE_palette_color_set(PaletteColor *color, const float rgb[3])
|
||||
{
|
||||
copy_v3_v3(color->color, rgb);
|
||||
BKE_palette_color_sync_legacy(color);
|
||||
}
|
||||
|
||||
void BKE_palette_color_sync_legacy(PaletteColor *color)
|
||||
{
|
||||
linearrgb_to_srgb_v3_v3(color->rgb, color->color);
|
||||
}
|
||||
|
||||
Palette *BKE_palette_add(Main *bmain, const char *name)
|
||||
{
|
||||
Palette *palette = BKE_id_new<Palette>(bmain, name);
|
||||
@@ -1554,7 +1570,7 @@ void BKE_palette_sort_luminance(tPaletteColorHSV *color_array, const int totcol)
|
||||
qsort(color_array, totcol, sizeof(tPaletteColorHSV), palettecolor_compare_luminance);
|
||||
}
|
||||
|
||||
bool BKE_palette_from_hash(Main *bmain, GHash *color_table, const char *name, const bool linear)
|
||||
bool BKE_palette_from_hash(Main *bmain, GHash *color_table, const char *name)
|
||||
{
|
||||
tPaletteColorHSV *color_array = nullptr;
|
||||
tPaletteColorHSV *col_elm = nullptr;
|
||||
@@ -1596,10 +1612,8 @@ bool BKE_palette_from_hash(Main *bmain, GHash *color_table, const char *name, co
|
||||
col_elm = &color_array[i];
|
||||
PaletteColor *palcol = BKE_palette_color_add(palette);
|
||||
if (palcol) {
|
||||
copy_v3_v3(palcol->rgb, col_elm->rgb);
|
||||
if (linear) {
|
||||
linearrgb_to_srgb_v3_v3(palcol->rgb, palcol->rgb);
|
||||
}
|
||||
/* Hex was stored as sRGB. */
|
||||
IMB_colormanagement_srgb_to_scene_linear_v3(palcol->color, col_elm->rgb);
|
||||
}
|
||||
}
|
||||
done = true;
|
||||
@@ -1710,8 +1724,8 @@ static void paint_init_data(Paint &paint)
|
||||
if (!paint.unified_paint_settings.curve_rand_value) {
|
||||
paint.unified_paint_settings.curve_rand_value = BKE_paint_default_curve();
|
||||
}
|
||||
copy_v3_v3(paint.unified_paint_settings.rgb, default_ups.rgb);
|
||||
copy_v3_v3(paint.unified_paint_settings.secondary_rgb, default_ups.secondary_rgb);
|
||||
copy_v3_v3(paint.unified_paint_settings.color, default_ups.color);
|
||||
copy_v3_v3(paint.unified_paint_settings.secondary_color, default_ups.secondary_color);
|
||||
}
|
||||
|
||||
bool BKE_paint_ensure(ToolSettings *ts, Paint **r_paint)
|
||||
@@ -1737,10 +1751,10 @@ bool BKE_paint_ensure(ToolSettings *ts, Paint **r_paint)
|
||||
(Paint *)ts->curves_sculpt,
|
||||
(Paint *)&ts->imapaint));
|
||||
#ifndef NDEBUG
|
||||
Paint paint_test = **r_paint;
|
||||
Paint paint_test = blender::dna::shallow_copy(**r_paint);
|
||||
paint_runtime_init(ts, *r_paint);
|
||||
/* Swap so debug doesn't hide errors when release fails. */
|
||||
std::swap(**r_paint, paint_test);
|
||||
blender::dna::shallow_swap(**r_paint, paint_test);
|
||||
BLI_assert(paint_test.runtime->ob_mode == (*r_paint)->runtime->ob_mode);
|
||||
#endif
|
||||
}
|
||||
@@ -1755,7 +1769,7 @@ bool BKE_paint_ensure(ToolSettings *ts, Paint **r_paint)
|
||||
else if ((Sculpt **)r_paint == &ts->sculpt) {
|
||||
Sculpt *data = MEM_callocN<Sculpt>(__func__);
|
||||
|
||||
*data = *DNA_struct_default_get(Sculpt);
|
||||
*data = blender::dna::shallow_copy(*DNA_struct_default_get(Sculpt));
|
||||
|
||||
paint = &data->paint;
|
||||
paint_init_data(*paint);
|
||||
|
||||
@@ -1585,7 +1585,7 @@ static void scene_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old)
|
||||
* (like object ones). */
|
||||
scene_foreach_toolsettings(
|
||||
nullptr, scene_new->toolsettings, true, reader, scene_old->toolsettings);
|
||||
std::swap(*scene_old->toolsettings, *scene_new->toolsettings);
|
||||
blender::dna::shallow_swap(*scene_old->toolsettings, *scene_new->toolsettings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1090,7 +1090,7 @@ void blo_do_versions_410(FileData *fd, Library * /*lib*/, Main *bmain)
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
Sculpt *sculpt = scene->toolsettings->sculpt;
|
||||
if (sculpt != nullptr) {
|
||||
Sculpt default_sculpt = *DNA_struct_default_get(Sculpt);
|
||||
Sculpt default_sculpt = blender::dna::shallow_copy(*DNA_struct_default_get(Sculpt));
|
||||
sculpt->automasking_boundary_edges_propagation_steps =
|
||||
default_sculpt.automasking_boundary_edges_propagation_steps;
|
||||
}
|
||||
|
||||
@@ -4681,7 +4681,8 @@ void do_versions_after_linking_450(FileData * /*fd*/, Main *bmain)
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 405, 76)) {
|
||||
ToolSettings toolsettings_default = *DNA_struct_default_get(ToolSettings);
|
||||
ToolSettings toolsettings_default = blender::dna::shallow_copy(
|
||||
*DNA_struct_default_get(ToolSettings));
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
scene->toolsettings->snap_playhead_mode = toolsettings_default.snap_playhead_mode;
|
||||
scene->toolsettings->snap_step_frames = toolsettings_default.snap_step_frames;
|
||||
|
||||
@@ -20,13 +20,16 @@
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_rigidbody_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_sequence_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
#include "DNA_workspace_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_math_numbers.hh"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_math_vector.hh"
|
||||
@@ -741,42 +744,47 @@ static void version_seq_text_from_legacy(Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
static void apply_unified_paint_settings_to_all_modes(Scene &scene)
|
||||
static void for_each_mode_paint_settings(
|
||||
Scene &scene, blender::FunctionRef<void(Scene &scene, Paint *paint)> func)
|
||||
{
|
||||
func(scene, reinterpret_cast<Paint *>(scene.toolsettings->vpaint));
|
||||
func(scene, reinterpret_cast<Paint *>(scene.toolsettings->wpaint));
|
||||
func(scene, reinterpret_cast<Paint *>(scene.toolsettings->sculpt));
|
||||
func(scene, reinterpret_cast<Paint *>(scene.toolsettings->gp_paint));
|
||||
func(scene, reinterpret_cast<Paint *>(scene.toolsettings->gp_vertexpaint));
|
||||
func(scene, reinterpret_cast<Paint *>(scene.toolsettings->gp_sculptpaint));
|
||||
func(scene, reinterpret_cast<Paint *>(scene.toolsettings->gp_weightpaint));
|
||||
func(scene, reinterpret_cast<Paint *>(scene.toolsettings->curves_sculpt));
|
||||
func(scene, reinterpret_cast<Paint *>(&scene.toolsettings->imapaint));
|
||||
}
|
||||
|
||||
static void copy_unified_paint_settings(Scene &scene, Paint *paint)
|
||||
{
|
||||
if (paint == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const UnifiedPaintSettings &scene_ups = scene.toolsettings->unified_paint_settings;
|
||||
auto apply_to_paint = [&](Paint *paint) {
|
||||
if (paint == nullptr) {
|
||||
return;
|
||||
}
|
||||
UnifiedPaintSettings &ups = paint->unified_paint_settings;
|
||||
UnifiedPaintSettings &ups = paint->unified_paint_settings;
|
||||
|
||||
ups.size = scene_ups.size;
|
||||
ups.unprojected_radius = scene_ups.unprojected_radius;
|
||||
ups.alpha = scene_ups.alpha;
|
||||
ups.weight = scene_ups.weight;
|
||||
copy_v3_v3(ups.rgb, scene_ups.rgb);
|
||||
copy_v3_v3(ups.secondary_rgb, scene_ups.secondary_rgb);
|
||||
ups.color_jitter_flag = scene_ups.color_jitter_flag;
|
||||
copy_v3_v3(ups.hsv_jitter, scene_ups.hsv_jitter);
|
||||
ups.size = scene_ups.size;
|
||||
ups.unprojected_radius = scene_ups.unprojected_radius;
|
||||
ups.alpha = scene_ups.alpha;
|
||||
ups.weight = scene_ups.weight;
|
||||
copy_v3_v3(ups.color, scene_ups.color);
|
||||
copy_v3_v3(ups.rgb, scene_ups.rgb);
|
||||
copy_v3_v3(ups.secondary_color, scene_ups.secondary_color);
|
||||
copy_v3_v3(ups.secondary_rgb, scene_ups.secondary_rgb);
|
||||
ups.color_jitter_flag = scene_ups.color_jitter_flag;
|
||||
copy_v3_v3(ups.hsv_jitter, scene_ups.hsv_jitter);
|
||||
|
||||
BLI_assert(ups.curve_rand_hue == nullptr);
|
||||
BLI_assert(ups.curve_rand_saturation == nullptr);
|
||||
BLI_assert(ups.curve_rand_value == nullptr);
|
||||
ups.curve_rand_hue = BKE_curvemapping_copy(scene_ups.curve_rand_hue);
|
||||
ups.curve_rand_saturation = BKE_curvemapping_copy(scene_ups.curve_rand_saturation);
|
||||
ups.curve_rand_value = BKE_curvemapping_copy(scene_ups.curve_rand_value);
|
||||
ups.flag = scene_ups.flag;
|
||||
};
|
||||
|
||||
apply_to_paint(reinterpret_cast<Paint *>(scene.toolsettings->vpaint));
|
||||
apply_to_paint(reinterpret_cast<Paint *>(scene.toolsettings->wpaint));
|
||||
apply_to_paint(reinterpret_cast<Paint *>(scene.toolsettings->sculpt));
|
||||
apply_to_paint(reinterpret_cast<Paint *>(scene.toolsettings->gp_paint));
|
||||
apply_to_paint(reinterpret_cast<Paint *>(scene.toolsettings->gp_vertexpaint));
|
||||
apply_to_paint(reinterpret_cast<Paint *>(scene.toolsettings->gp_sculptpaint));
|
||||
apply_to_paint(reinterpret_cast<Paint *>(scene.toolsettings->gp_weightpaint));
|
||||
apply_to_paint(reinterpret_cast<Paint *>(scene.toolsettings->curves_sculpt));
|
||||
apply_to_paint(reinterpret_cast<Paint *>(&scene.toolsettings->imapaint));
|
||||
BLI_assert(ups.curve_rand_hue == nullptr);
|
||||
BLI_assert(ups.curve_rand_saturation == nullptr);
|
||||
BLI_assert(ups.curve_rand_value == nullptr);
|
||||
ups.curve_rand_hue = BKE_curvemapping_copy(scene_ups.curve_rand_hue);
|
||||
ups.curve_rand_saturation = BKE_curvemapping_copy(scene_ups.curve_rand_saturation);
|
||||
ups.curve_rand_value = BKE_curvemapping_copy(scene_ups.curve_rand_value);
|
||||
ups.flag = scene_ups.flag;
|
||||
}
|
||||
|
||||
/* The Use Alpha option is does not exist in the new generic Mix node, it essentially just
|
||||
@@ -1905,7 +1913,7 @@ void blo_do_versions_500(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 26)) {
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
apply_unified_paint_settings_to_all_modes(*scene);
|
||||
for_each_mode_paint_settings(*scene, copy_unified_paint_settings);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2372,7 +2380,7 @@ void blo_do_versions_500(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 62)) {
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 63)) {
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
if (scene->r.bake_flag & R_BAKE_MULTIRES) {
|
||||
scene->r.bake.type = scene->r.bake_mode;
|
||||
@@ -2399,6 +2407,31 @@ void blo_do_versions_500(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 65)) {
|
||||
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
|
||||
srgb_to_linearrgb_v3_v3(brush->color, brush->rgb);
|
||||
srgb_to_linearrgb_v3_v3(brush->secondary_color, brush->secondary_rgb);
|
||||
}
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
UnifiedPaintSettings &ups = scene->toolsettings->unified_paint_settings;
|
||||
srgb_to_linearrgb_v3_v3(ups.color, ups.rgb);
|
||||
srgb_to_linearrgb_v3_v3(ups.secondary_color, ups.secondary_rgb);
|
||||
|
||||
for_each_mode_paint_settings(*scene, [](Scene & /*scene*/, Paint *paint) {
|
||||
if (paint != nullptr) {
|
||||
UnifiedPaintSettings &ups = paint->unified_paint_settings;
|
||||
srgb_to_linearrgb_v3_v3(ups.color, ups.rgb);
|
||||
srgb_to_linearrgb_v3_v3(ups.secondary_color, ups.secondary_rgb);
|
||||
}
|
||||
});
|
||||
}
|
||||
LISTBASE_FOREACH (Palette *, palette, &bmain->palettes) {
|
||||
LISTBASE_FOREACH (PaletteColor *, color, &palette->colors) {
|
||||
srgb_to_linearrgb_v3_v3(color->color, color->rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Always bump subversion in BKE_blender_version.h when adding versioning
|
||||
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.
|
||||
|
||||
@@ -367,8 +367,8 @@ static void blo_update_defaults_paint(Paint *paint)
|
||||
paint->unified_paint_settings.alpha = default_ups.alpha;
|
||||
paint->unified_paint_settings.weight = default_ups.weight;
|
||||
paint->unified_paint_settings.flag = default_ups.flag;
|
||||
copy_v3_v3(paint->unified_paint_settings.rgb, default_ups.rgb);
|
||||
copy_v3_v3(paint->unified_paint_settings.secondary_rgb, default_ups.secondary_rgb);
|
||||
copy_v3_v3(paint->unified_paint_settings.color, default_ups.color);
|
||||
copy_v3_v3(paint->unified_paint_settings.secondary_color, default_ups.secondary_color);
|
||||
|
||||
if (paint->unified_paint_settings.curve_rand_hue == nullptr) {
|
||||
paint->unified_paint_settings.curve_rand_hue = BKE_paint_default_curve();
|
||||
@@ -492,8 +492,8 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene)
|
||||
|
||||
const UnifiedPaintSettings &default_ups = *DNA_struct_default_get(UnifiedPaintSettings);
|
||||
ts->unified_paint_settings.flag = default_ups.flag;
|
||||
copy_v3_v3(ts->unified_paint_settings.rgb, default_ups.rgb);
|
||||
copy_v3_v3(ts->unified_paint_settings.secondary_rgb, default_ups.secondary_rgb);
|
||||
copy_v3_v3(ts->unified_paint_settings.color, default_ups.color);
|
||||
copy_v3_v3(ts->unified_paint_settings.secondary_color, default_ups.secondary_color);
|
||||
|
||||
if (ts->unified_paint_settings.curve_rand_hue == nullptr) {
|
||||
ts->unified_paint_settings.curve_rand_hue = BKE_paint_default_curve();
|
||||
|
||||
@@ -809,7 +809,7 @@ static wmOperatorStatus grease_pencil_primitive_invoke(bContext *C,
|
||||
GPPAINT_FLAG_USE_VERTEXCOLOR);
|
||||
if (use_vertex_color) {
|
||||
ColorGeometry4f color_base;
|
||||
srgb_to_linearrgb_v3_v3(color_base, ptd.brush->rgb);
|
||||
copy_v3_v3(color_base, ptd.brush->color);
|
||||
color_base.a = ptd.settings->vertex_factor;
|
||||
ptd.vertex_color = ELEM(ptd.settings->vertex_mode, GPPAINT_MODE_STROKE, GPPAINT_MODE_BOTH) ?
|
||||
std::make_optional(color_base) :
|
||||
|
||||
@@ -360,8 +360,7 @@ static wmOperatorStatus grease_pencil_vertex_paint_set_exec(bContext *C, wmOpera
|
||||
const float factor = RNA_float_get(op->ptr, "factor");
|
||||
const bool use_selection_mask = ED_grease_pencil_any_vertex_mask_selection(scene.toolsettings);
|
||||
|
||||
float3 color_linear;
|
||||
srgb_to_linearrgb_v3_v3(color_linear, BKE_brush_color_get(&paint, &brush));
|
||||
float3 color_linear = BKE_brush_color_get(&paint, &brush);
|
||||
const ColorGeometry4f target_color(color_linear[0], color_linear[1], color_linear[2], 1.0f);
|
||||
|
||||
std::atomic<bool> any_changed;
|
||||
|
||||
@@ -88,63 +88,6 @@ static void eyedropper_draw_cb(const wmWindow * /*window*/, void *arg)
|
||||
eyedropper_draw_cursor_text_region(eye->cb_win_event_xy, eye->sample_text);
|
||||
}
|
||||
|
||||
/* A heuristic to check whether the current eyedropper destination property is used for non-color
|
||||
* painting. If so, the eyedropper will ignore the PROP_COLOR_GAMMA nature of the property and
|
||||
* not convert linear colors to display space.
|
||||
*
|
||||
* The current logic is targeting texture painting, both 2D and 3D. It assumes that invoking the
|
||||
* operator from 3D viewport means 3D painting, and invoking from image editor means 2D painting.
|
||||
*
|
||||
* For the 3D painting the function checks whether active object is in texture paint mode, and if
|
||||
* so checks the active image (via material slot, or the explicitly specified image) to have
|
||||
* non-color (data) colorspace.
|
||||
*
|
||||
* For the 2D painting it checks the active image editor's image colorspace.
|
||||
*
|
||||
* Since brush color could be re-used from multiple spaces the check is not fully reliable: it is
|
||||
* possible to invoke sampling from one editor and do stroke in other editor. There is no easy way
|
||||
* of dealing with this, and it is unlikely to be a common configuration. */
|
||||
static bool is_data_destination(const bContext *C, const Eyedropper *eye)
|
||||
{
|
||||
if (eye->ptr.type != &RNA_Brush) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
if (v3d) {
|
||||
/*const*/ Object *object = CTX_data_active_object(C);
|
||||
if (!object) {
|
||||
return false;
|
||||
}
|
||||
if ((object->mode & OB_MODE_TEXTURE_PAINT) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
const ImagePaintSettings &settings = scene->toolsettings->imapaint;
|
||||
Image *image = nullptr;
|
||||
if (settings.mode == IMAGEPAINT_MODE_MATERIAL) {
|
||||
Material *material = BKE_object_material_get(object, object->actcol);
|
||||
if (material && material->texpaintslot) {
|
||||
image = material->texpaintslot[material->paint_active_slot].ima;
|
||||
}
|
||||
}
|
||||
else if (settings.mode == IMAGEPAINT_MODE_IMAGE) {
|
||||
image = settings.canvas;
|
||||
}
|
||||
|
||||
return image && IMB_colormanagement_space_name_is_data(image->colorspace_settings.name);
|
||||
}
|
||||
|
||||
const SpaceImage *space_image = CTX_wm_space_image(C);
|
||||
if (space_image) {
|
||||
return space_image->image &&
|
||||
IMB_colormanagement_space_name_is_data(space_image->image->colorspace_settings.name);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool eyedropper_init(bContext *C, wmOperator *op)
|
||||
{
|
||||
Eyedropper *eye = MEM_new<Eyedropper>(__func__);
|
||||
@@ -194,7 +137,7 @@ static bool eyedropper_init(bContext *C, wmOperator *op)
|
||||
eye->draw_handle_sample_text = WM_draw_cb_activate(eye->cb_win, eyedropper_draw_cb, eye);
|
||||
}
|
||||
|
||||
if (prop_subtype != PROP_COLOR && !is_data_destination(C, eye)) {
|
||||
if (prop_subtype != PROP_COLOR) {
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const char *display_device;
|
||||
|
||||
|
||||
@@ -145,9 +145,7 @@ static void eyedropper_grease_pencil_exit(bContext *C, wmOperator *op)
|
||||
op->customdata = nullptr;
|
||||
}
|
||||
|
||||
static void eyedropper_add_material(bContext *C,
|
||||
const float3 col_conv,
|
||||
const MaterialMode mat_mode)
|
||||
static void eyedropper_add_material(bContext *C, const float3 color, const MaterialMode mat_mode)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
@@ -166,10 +164,10 @@ static void eyedropper_add_material(bContext *C,
|
||||
MaterialGPencilStyle *gp_style = ma->gp_style;
|
||||
if (gp_style != nullptr) {
|
||||
/* Check stroke color. */
|
||||
bool found_stroke = compare_v3v3(gp_style->stroke_rgba, col_conv, 0.01f) &&
|
||||
bool found_stroke = compare_v3v3(gp_style->stroke_rgba, color, 0.01f) &&
|
||||
(gp_style->flag & GP_MATERIAL_STROKE_SHOW);
|
||||
/* Check fill color. */
|
||||
bool found_fill = compare_v3v3(gp_style->fill_rgba, col_conv, 0.01f) &&
|
||||
bool found_fill = compare_v3v3(gp_style->fill_rgba, color, 0.01f) &&
|
||||
(gp_style->flag & GP_MATERIAL_FILL_SHOW);
|
||||
|
||||
if ((mat_mode == MaterialMode::Stroke) && (found_stroke) &&
|
||||
@@ -215,7 +213,7 @@ static void eyedropper_add_material(bContext *C,
|
||||
/* Stroke color. */
|
||||
gp_style_new->flag |= GP_MATERIAL_STROKE_SHOW;
|
||||
gp_style_new->flag &= ~GP_MATERIAL_FILL_SHOW;
|
||||
copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
|
||||
copy_v3_v3(gp_style_new->stroke_rgba, color);
|
||||
zero_v4(gp_style_new->fill_rgba);
|
||||
}
|
||||
/* Fill Only. */
|
||||
@@ -224,20 +222,20 @@ static void eyedropper_add_material(bContext *C,
|
||||
gp_style_new->flag &= ~GP_MATERIAL_STROKE_SHOW;
|
||||
gp_style_new->flag |= GP_MATERIAL_FILL_SHOW;
|
||||
zero_v4(gp_style_new->stroke_rgba);
|
||||
copy_v3_v3(gp_style_new->fill_rgba, col_conv);
|
||||
copy_v3_v3(gp_style_new->fill_rgba, color);
|
||||
}
|
||||
/* Stroke and Fill. */
|
||||
else if (mat_mode == MaterialMode::Both) {
|
||||
gp_style_new->flag |= GP_MATERIAL_STROKE_SHOW | GP_MATERIAL_FILL_SHOW;
|
||||
copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
|
||||
copy_v3_v3(gp_style_new->fill_rgba, col_conv);
|
||||
copy_v3_v3(gp_style_new->stroke_rgba, color);
|
||||
copy_v3_v3(gp_style_new->fill_rgba, color);
|
||||
}
|
||||
/* Push undo for new created material. */
|
||||
ED_undo_push(C, "Add Grease Pencil Material");
|
||||
}
|
||||
|
||||
/* Create a new palette color and palette if needed. */
|
||||
static void eyedropper_add_palette_color(bContext *C, const float3 col_conv)
|
||||
static void eyedropper_add_palette_color(bContext *C, const float3 color)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
@@ -263,7 +261,7 @@ static void eyedropper_add_palette_color(bContext *C, const float3 col_conv)
|
||||
Palette *palette = paint->palette;
|
||||
int i;
|
||||
LISTBASE_FOREACH_INDEX (PaletteColor *, palcolor, &palette->colors, i) {
|
||||
if (compare_v3v3(palcolor->rgb, col_conv, 0.01f)) {
|
||||
if (compare_v3v3(palcolor->color, color, 0.01f)) {
|
||||
palette->active_color = i;
|
||||
return;
|
||||
}
|
||||
@@ -273,12 +271,12 @@ static void eyedropper_add_palette_color(bContext *C, const float3 col_conv)
|
||||
PaletteColor *palcol = BKE_palette_color_add(palette);
|
||||
if (palcol) {
|
||||
palette->active_color = BLI_listbase_count(&palette->colors) - 1;
|
||||
copy_v3_v3(palcol->rgb, col_conv);
|
||||
BKE_palette_color_set(palcol, color);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the active brush's color. */
|
||||
static void eyedropper_set_brush_color(bContext *C, const float3 &col_conv)
|
||||
static void eyedropper_set_brush_color(bContext *C, const float3 &color)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
@@ -288,7 +286,8 @@ static void eyedropper_set_brush_color(bContext *C, const float3 &col_conv)
|
||||
return;
|
||||
}
|
||||
|
||||
copy_v3_v3(brush->rgb, col_conv);
|
||||
copy_v3_v3(brush->color, color);
|
||||
BKE_brush_color_sync_legacy(brush);
|
||||
BKE_brush_tag_unsaved_changes(brush);
|
||||
}
|
||||
|
||||
@@ -311,24 +310,15 @@ static void eyedropper_grease_pencil_color_set(bContext *C,
|
||||
mat_mode = MaterialMode::Both;
|
||||
}
|
||||
|
||||
float3 col_conv = eye->color;
|
||||
|
||||
/* Convert from linear rgb space to sRGB space because palette and brush colors are in
|
||||
* sRGB space, and this conversion is needed to undo the conversion to linear performed by
|
||||
* eyedropper_color_sample_fl. */
|
||||
if (eye->display && ELEM(eye->mode, EyeMode::Palette, EyeMode::Brush)) {
|
||||
IMB_colormanagement_scene_linear_to_srgb_v3(col_conv, col_conv);
|
||||
}
|
||||
|
||||
switch (eye->mode) {
|
||||
case EyeMode::Material:
|
||||
eyedropper_add_material(C, col_conv, mat_mode);
|
||||
eyedropper_add_material(C, eye->color, mat_mode);
|
||||
break;
|
||||
case EyeMode::Palette:
|
||||
eyedropper_add_palette_color(C, col_conv);
|
||||
eyedropper_add_palette_color(C, eye->color);
|
||||
break;
|
||||
case EyeMode::Brush:
|
||||
eyedropper_set_brush_color(C, col_conv);
|
||||
eyedropper_set_brush_color(C, eye->color);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6660,13 +6660,13 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
|
||||
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
|
||||
RNA_property_float_get_array_at_most(
|
||||
&but->rnapoin, but->rnaprop, color, ARRAY_SIZE(color));
|
||||
IMB_colormanagement_srgb_to_scene_linear_v3(color, color);
|
||||
BKE_brush_color_set(paint, brush, color);
|
||||
updated = true;
|
||||
}
|
||||
else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
|
||||
RNA_property_float_get_array_at_most(
|
||||
&but->rnapoin, but->rnaprop, color, ARRAY_SIZE(color));
|
||||
IMB_colormanagement_scene_linear_to_srgb_v3(color, color);
|
||||
BKE_brush_color_set(paint, brush, color);
|
||||
updated = true;
|
||||
}
|
||||
|
||||
@@ -2403,8 +2403,8 @@ static wmOperatorStatus drop_color_invoke(bContext *C, wmOperator *op, const wmE
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!gamma) {
|
||||
linearrgb_to_srgb_v3_v3(color, color);
|
||||
if (gamma) {
|
||||
srgb_to_linearrgb_v3_v3(color, color);
|
||||
}
|
||||
|
||||
ED_imapaint_bucket_fill(C, color, op, event->mval);
|
||||
|
||||
@@ -660,7 +660,7 @@ static bke::CurvesGeometry boundary_to_curves(const Scene &scene,
|
||||
scene.toolsettings->gp_paint, &brush);
|
||||
if (use_vertex_color) {
|
||||
ColorGeometry4f vertex_color;
|
||||
srgb_to_linearrgb_v3_v3(vertex_color, brush.rgb);
|
||||
copy_v3_v3(vertex_color, brush.color);
|
||||
vertex_color.a = brush.gpencil_settings->vertex_factor;
|
||||
|
||||
if (ELEM(brush.gpencil_settings->vertex_mode, GPPAINT_MODE_FILL, GPPAINT_MODE_BOTH)) {
|
||||
|
||||
@@ -166,7 +166,7 @@ static Brush *create_fill_guide_brush()
|
||||
|
||||
settings->brush_draw_mode = GP_BRUSH_MODE_VERTEXCOLOR;
|
||||
/* TODO: Use theme setting. */
|
||||
copy_v3_fl3(fill_guides_brush->rgb, 0.0f, 1.0f, 1.0f);
|
||||
copy_v3_fl3(fill_guides_brush->color, 0.0f, 1.0f, 1.0f);
|
||||
settings->vertex_factor = 1.0f;
|
||||
|
||||
settings->active_smooth = 0.35f;
|
||||
@@ -292,7 +292,7 @@ struct PaintOperationExecutor {
|
||||
use_vertex_color_ = brush_using_vertex_color(scene_->toolsettings->gp_paint, brush_);
|
||||
if (use_vertex_color_) {
|
||||
ColorGeometry4f color_base;
|
||||
srgb_to_linearrgb_v3_v3(color_base, brush_->rgb);
|
||||
copy_v3_v3(color_base, brush_->color);
|
||||
color_base.a = settings_->vertex_factor;
|
||||
if (ELEM(settings_->vertex_mode, GPPAINT_MODE_STROKE, GPPAINT_MODE_BOTH)) {
|
||||
vertex_color_ = color_base;
|
||||
|
||||
@@ -90,7 +90,7 @@ void TintOperation::on_stroke_begin(const bContext &C, const InputSample & /*sta
|
||||
|
||||
float4 color_linear;
|
||||
color_linear[3] = 1.0f;
|
||||
srgb_to_linearrgb_v3_v3(color_linear, BKE_brush_color_get(paint, brush));
|
||||
copy_v3_v3(color_linear, BKE_brush_color_get(paint, brush));
|
||||
|
||||
color_ = ColorGeometry4f(color_linear);
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ void VertexPaintOperation::on_stroke_extended(const bContext &C,
|
||||
const bool do_fill = do_vertex_color_fill(brush);
|
||||
|
||||
float color_linear[3];
|
||||
srgb_to_linearrgb_v3_v3(color_linear, BKE_brush_color_get(&paint, &brush));
|
||||
copy_v3_v3(color_linear, BKE_brush_color_get(&paint, &brush));
|
||||
const ColorGeometry4f mix_color(color_linear[0], color_linear[1], color_linear[2], 1.0f);
|
||||
|
||||
this->foreach_editable_drawing(C, GrainSize(1), [&](const GreasePencilStrokeParams ¶ms) {
|
||||
|
||||
@@ -41,7 +41,7 @@ void VertexReplaceOperation::on_stroke_extended(const bContext &C,
|
||||
const bool do_fill = do_vertex_color_fill(brush);
|
||||
|
||||
float3 color_linear;
|
||||
srgb_to_linearrgb_v3_v3(color_linear, BKE_brush_color_get(&paint, &brush));
|
||||
copy_v3_v3(color_linear, BKE_brush_color_get(&paint, &brush));
|
||||
const ColorGeometry4f replace_color(color_linear.x, color_linear.y, color_linear.z, 1.0f);
|
||||
|
||||
this->foreach_editable_drawing(C, GrainSize(1), [&](const GreasePencilStrokeParams ¶ms) {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_axis_angle.hh"
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_math_matrix.hh"
|
||||
#include "BLI_math_rotation.h"
|
||||
#include "BLI_rect.h"
|
||||
@@ -1657,7 +1658,12 @@ static void grease_pencil_brush_cursor_draw(PaintCursorContext &pcontext)
|
||||
ELEM(brush->gpencil_settings->vertex_mode,
|
||||
GPPAINT_MODE_STROKE,
|
||||
GPPAINT_MODE_BOTH);
|
||||
color = use_vertex_color_stroke ? float3(brush->rgb) : float4(gp_style->stroke_rgba).xyz();
|
||||
if (use_vertex_color_stroke) {
|
||||
IMB_colormanagement_scene_linear_to_srgb_v3(color, brush->color);
|
||||
}
|
||||
else {
|
||||
color = float4(gp_style->stroke_rgba).xyz();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1669,6 +1675,7 @@ static void grease_pencil_brush_cursor_draw(PaintCursorContext &pcontext)
|
||||
else if (pcontext.mode == PaintMode::VertexGPencil) {
|
||||
pcontext.pixel_radius = BKE_brush_size_get(pcontext.paint, brush);
|
||||
color = BKE_brush_color_get(paint, brush);
|
||||
IMB_colormanagement_scene_linear_to_srgb_v3(color, color);
|
||||
}
|
||||
|
||||
GPU_line_width(1.0f);
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_math_vector.hh"
|
||||
#include "BLI_noise.hh"
|
||||
#include "BLI_rand.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
@@ -45,7 +45,6 @@
|
||||
#include "BKE_object.hh"
|
||||
#include "BKE_paint.hh"
|
||||
#include "BKE_paint_types.hh"
|
||||
#include "BKE_report.hh"
|
||||
#include "BKE_scene.hh"
|
||||
|
||||
#include "NOD_texture.h"
|
||||
@@ -369,7 +368,6 @@ void paint_brush_color_get(const Paint *paint,
|
||||
bool invert,
|
||||
float distance,
|
||||
float pressure,
|
||||
bool is_data,
|
||||
float r_color[3])
|
||||
{
|
||||
if (invert) {
|
||||
@@ -394,25 +392,22 @@ void paint_brush_color_get(const Paint *paint,
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Gradient / Color-band colors are not considered #PROP_COLOR_GAMMA.
|
||||
* Brush colors are currently in sRGB though. */
|
||||
IMB_colormanagement_scene_linear_to_srgb_v3(r_color, color_gr);
|
||||
copy_v3_v3(r_color, color_gr);
|
||||
}
|
||||
else if (color_jitter_settings) {
|
||||
copy_v3_v3(r_color,
|
||||
BKE_paint_randomize_color(*color_jitter_settings,
|
||||
*initial_hsv_jitter,
|
||||
distance,
|
||||
pressure,
|
||||
BKE_brush_color_get(paint, br)));
|
||||
/* Perform color jitter with sRGB transfer function. This is inconsistent with other
|
||||
* paint modes which do it in linear space. But arguably it's better to do it in the
|
||||
* more perceptually uniform color space. */
|
||||
blender::float3 color = BKE_brush_color_get(paint, br);
|
||||
linearrgb_to_srgb_v3_v3(color, color);
|
||||
color = BKE_paint_randomize_color(
|
||||
*color_jitter_settings, *initial_hsv_jitter, distance, pressure, color);
|
||||
srgb_to_linearrgb_v3_v3(r_color, color);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(r_color, BKE_brush_color_get(paint, br));
|
||||
}
|
||||
}
|
||||
if (!is_data) {
|
||||
IMB_colormanagement_srgb_to_scene_linear_v3(r_color, r_color);
|
||||
}
|
||||
}
|
||||
|
||||
void paint_brush_init_tex(Brush *brush)
|
||||
@@ -870,10 +865,12 @@ static wmOperatorStatus brush_colors_flip_exec(bContext *C, wmOperator * /*op*/)
|
||||
|
||||
if (BKE_paint_use_unified_color(paint)) {
|
||||
UnifiedPaintSettings &ups = paint->unified_paint_settings;
|
||||
swap_v3_v3(ups.rgb, ups.secondary_rgb);
|
||||
swap_v3_v3(ups.color, ups.secondary_color);
|
||||
BKE_brush_color_sync_legacy(&ups);
|
||||
}
|
||||
else if (br) {
|
||||
swap_v3_v3(br->rgb, br->secondary_rgb);
|
||||
swap_v3_v3(br->color, br->secondary_color);
|
||||
BKE_brush_color_sync_legacy(br);
|
||||
BKE_brush_tag_unsaved_changes(br);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -407,14 +407,8 @@ static ImBuf *brush_painter_imbuf_new(
|
||||
|
||||
/* get brush color */
|
||||
if (brush->image_brush_type == IMAGE_PAINT_BRUSH_TYPE_DRAW) {
|
||||
paint_brush_color_get(paint,
|
||||
brush,
|
||||
painter->initial_hsv_jitter,
|
||||
cache->invert,
|
||||
distance,
|
||||
pressure,
|
||||
cache->is_data,
|
||||
brush_rgb);
|
||||
paint_brush_color_get(
|
||||
paint, brush, painter->initial_hsv_jitter, cache->invert, distance, pressure, brush_rgb);
|
||||
|
||||
if (cache->is_srgb) {
|
||||
IMB_colormanagement_scene_linear_to_srgb_v3(brush_rgb, brush_rgb);
|
||||
@@ -503,14 +497,8 @@ static void brush_painter_imbuf_update(BrushPainter *painter,
|
||||
|
||||
/* get brush color */
|
||||
if (brush->image_brush_type == IMAGE_PAINT_BRUSH_TYPE_DRAW) {
|
||||
paint_brush_color_get(paint,
|
||||
brush,
|
||||
painter->initial_hsv_jitter,
|
||||
cache->invert,
|
||||
0.0f,
|
||||
1.0f,
|
||||
cache->is_data,
|
||||
brush_rgb);
|
||||
paint_brush_color_get(
|
||||
paint, brush, painter->initial_hsv_jitter, cache->invert, 0.0f, 1.0f, brush_rgb);
|
||||
|
||||
if (cache->is_srgb) {
|
||||
IMB_colormanagement_scene_linear_to_srgb_v3(brush_rgb, brush_rgb);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_base_safe.h"
|
||||
#include "BLI_math_bits.h"
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_math_color_blend.h"
|
||||
#include "BLI_math_geom.h"
|
||||
#include "BLI_math_vector.hh"
|
||||
@@ -221,6 +222,11 @@ struct ProjPaintImage {
|
||||
/** Store flag to enforce validation of undo rectangle. */
|
||||
bool **valid;
|
||||
bool touch;
|
||||
/** Paint color in the colorspace of this image, cached for performance. */
|
||||
float paint_color_byte[3];
|
||||
bool is_data;
|
||||
bool is_srgb;
|
||||
const ColorSpace *byte_colorspace;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -268,8 +274,7 @@ struct ProjPaintState {
|
||||
/* PROJ_SRC_**** */
|
||||
int source;
|
||||
|
||||
/* the paint color. It can change depending of inverted mode or not */
|
||||
float paint_color[3];
|
||||
/* Scene linear paint color. It can change depending on inverted mode or not. */
|
||||
float paint_color_linear[3];
|
||||
float dither;
|
||||
|
||||
@@ -1974,7 +1979,9 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
|
||||
uchar rgba_ub[4];
|
||||
float rgba[4];
|
||||
project_face_pixel(other_tri_uv, ibuf_other, w, rgba_ub, nullptr);
|
||||
srgb_to_linearrgb_uchar4(rgba, rgba_ub);
|
||||
rgba_uchar_to_float(rgba, rgba_ub);
|
||||
IMB_colormanagement_colorspace_to_scene_linear_v3(rgba,
|
||||
ibuf_other->byte_buffer.colorspace);
|
||||
straight_to_premul_v4_v4(((ProjPixelClone *)projPixel)->clonepx.f, rgba);
|
||||
}
|
||||
}
|
||||
@@ -1983,8 +1990,8 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
|
||||
float rgba[4];
|
||||
project_face_pixel(other_tri_uv, ibuf_other, w, nullptr, rgba);
|
||||
premul_to_straight_v4(rgba);
|
||||
linearrgb_to_srgb_uchar3(((ProjPixelClone *)projPixel)->clonepx.ch, rgba);
|
||||
((ProjPixelClone *)projPixel)->clonepx.ch[3] = rgba[3] * 255;
|
||||
IMB_colormanagement_scene_linear_to_colorspace_v3(rgba, ibuf->byte_buffer.colorspace);
|
||||
rgba_float_to_uchar(((ProjPixelClone *)projPixel)->clonepx.ch, rgba);
|
||||
}
|
||||
else { /* char to char */
|
||||
project_face_pixel(
|
||||
@@ -5074,16 +5081,23 @@ static void do_projectpaint_draw(ProjPaintState *ps,
|
||||
int u,
|
||||
int v)
|
||||
{
|
||||
const ProjPaintImage *img = &ps->projImages[projPixel->image_index];
|
||||
float rgb[3];
|
||||
uchar rgba_ub[4];
|
||||
|
||||
if (ps->is_texbrush) {
|
||||
mul_v3_v3v3(rgb, texrgb, ps->paint_color_linear);
|
||||
/* TODO(sergey): Support texture paint color space. */
|
||||
linearrgb_to_srgb_v3_v3(rgb, rgb);
|
||||
if (img->is_srgb) {
|
||||
/* Fast-ish path for sRGB. */
|
||||
IMB_colormanagement_scene_linear_to_srgb_v3(rgb, rgb);
|
||||
}
|
||||
else if (img->byte_colorspace) {
|
||||
/* Slow path with arbitrary colorspace. */
|
||||
IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, img->byte_colorspace);
|
||||
}
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(rgb, ps->paint_color);
|
||||
copy_v3_v3(rgb, img->paint_color_byte);
|
||||
}
|
||||
|
||||
if (dither > 0.0f) {
|
||||
@@ -5322,7 +5336,13 @@ static void do_projectpaint_thread(TaskPool *__restrict /*pool*/, void *ph_v)
|
||||
IMB_BlendMode(ps->blend));
|
||||
}
|
||||
else {
|
||||
linearrgb_to_srgb_v3_v3(color_f, color_f);
|
||||
const ProjPaintImage *img = &ps->projImages[projPixel->image_index];
|
||||
if (img->is_srgb) {
|
||||
IMB_colormanagement_scene_linear_to_srgb_v3(color_f, color_f);
|
||||
}
|
||||
else if (img->byte_colorspace) {
|
||||
IMB_colormanagement_scene_linear_to_colorspace_v3(color_f, img->byte_colorspace);
|
||||
}
|
||||
|
||||
if (ps->dither > 0.0f) {
|
||||
float_to_byte_dither_v3(
|
||||
@@ -5350,10 +5370,11 @@ static void do_projectpaint_thread(TaskPool *__restrict /*pool*/, void *ph_v)
|
||||
IMB_BlendMode(ps->blend));
|
||||
}
|
||||
else {
|
||||
const ProjPaintImage *img = &ps->projImages[projPixel->image_index];
|
||||
float mask = float(projPixel->mask) * (1.0f / 65535.0f);
|
||||
projPixel->newColor.ch[3] = mask * 255 * brush_alpha;
|
||||
|
||||
rgb_float_to_uchar(projPixel->newColor.ch, ps->paint_color);
|
||||
rgb_float_to_uchar(projPixel->newColor.ch, img->paint_color_byte);
|
||||
IMB_blend_color_byte(projPixel->pixel.ch_pt,
|
||||
projPixel->origColor.ch_pt,
|
||||
projPixel->newColor.ch,
|
||||
@@ -5749,17 +5770,6 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
|
||||
return touch_any;
|
||||
}
|
||||
|
||||
static bool has_data_projection_paint_image(const ProjPaintState &ps)
|
||||
{
|
||||
for (int i = 0; i < ps.image_tot; i++) {
|
||||
const ImBuf *ibuf = ps.projImages[i].ibuf;
|
||||
if (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void paint_proj_stroke_ps(const bContext * /*C*/,
|
||||
void *ps_handle_p,
|
||||
const float prev_pos[2],
|
||||
@@ -5790,8 +5800,34 @@ static void paint_proj_stroke_ps(const bContext * /*C*/,
|
||||
ps->mode == BRUSH_STROKE_INVERT,
|
||||
distance,
|
||||
pressure,
|
||||
has_data_projection_paint_image(*ps),
|
||||
ps->paint_color);
|
||||
ps->paint_color_linear);
|
||||
|
||||
/* Cache colorspace info per image for performance. */
|
||||
for (int i = 0; i < ps->image_tot; i++) {
|
||||
ProjPaintImage *img = &ps->projImages[i];
|
||||
const ImBuf *ibuf = img->ibuf;
|
||||
|
||||
copy_v3_v3(img->paint_color_byte, ps->paint_color_linear);
|
||||
img->byte_colorspace = nullptr;
|
||||
img->is_data = false;
|
||||
img->is_srgb = false;
|
||||
|
||||
if (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) {
|
||||
img->is_data = true;
|
||||
}
|
||||
else if (ibuf->byte_buffer.data && ibuf->byte_buffer.colorspace) {
|
||||
img->byte_colorspace = ibuf->byte_buffer.colorspace;
|
||||
img->is_srgb = IMB_colormanagement_space_is_srgb(img->byte_colorspace);
|
||||
if (img->is_srgb) {
|
||||
IMB_colormanagement_scene_linear_to_srgb_v3(img->paint_color_byte,
|
||||
img->paint_color_byte);
|
||||
}
|
||||
else {
|
||||
IMB_colormanagement_scene_linear_to_colorspace_v3(img->paint_color_byte,
|
||||
img->byte_colorspace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ps->brush_type == IMAGE_PAINT_BRUSH_TYPE_MASK) {
|
||||
ps->stencil_value = brush->weight;
|
||||
|
||||
@@ -350,8 +350,7 @@ void paint_brush_color_get(const Paint *paint,
|
||||
bool invert,
|
||||
float distance,
|
||||
float pressure,
|
||||
bool is_data,
|
||||
float r_color[3] /* In scene linear colorspace. */);
|
||||
float r_color[3]);
|
||||
bool paint_use_opacity_masking(const Paint *paint, const Brush *brush);
|
||||
void paint_brush_init_tex(Brush *brush);
|
||||
void paint_brush_exit_tex(Brush *brush);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_color.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
@@ -42,6 +43,8 @@
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_define.hh"
|
||||
|
||||
#include "IMB_colormanagement.hh"
|
||||
|
||||
#include "curves_sculpt_intern.hh"
|
||||
#include "paint_hide.hh"
|
||||
#include "paint_intern.hh"
|
||||
@@ -183,11 +186,11 @@ static wmOperatorStatus palette_color_add_exec(bContext *C, wmOperator * /*op*/)
|
||||
PaintMode::GPencil,
|
||||
PaintMode::VertexGPencil))
|
||||
{
|
||||
copy_v3_v3(color->rgb, BKE_brush_color_get(paint, brush));
|
||||
copy_v3_v3(color->color, BKE_brush_color_get(paint, brush));
|
||||
color->value = 0.0;
|
||||
}
|
||||
else if (mode == PaintMode::Weight) {
|
||||
zero_v3(color->rgb);
|
||||
zero_v3(color->color);
|
||||
color->value = brush->weight;
|
||||
}
|
||||
}
|
||||
@@ -272,8 +275,10 @@ static wmOperatorStatus palette_extract_img_exec(bContext *C, wmOperator *op)
|
||||
const int range = int(pow(10.0f, threshold));
|
||||
for (int row = 0; row < ibuf->y; row++) {
|
||||
for (int col = 0; col < ibuf->x; col++) {
|
||||
float color[4];
|
||||
IMB_sampleImageAtLocation(ibuf, float(col), float(row), false, color);
|
||||
float color[3];
|
||||
IMB_sampleImageAtLocation(ibuf, float(col), float(row), color);
|
||||
/* Convert to sRGB for hex. */
|
||||
IMB_colormanagement_scene_linear_to_srgb_v3(color, color);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
color[i] = truncf(color[i] * range) / range;
|
||||
}
|
||||
@@ -285,7 +290,7 @@ static wmOperatorStatus palette_extract_img_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
}
|
||||
|
||||
done = BKE_palette_from_hash(bmain, color_table, image->id.name + 2, false);
|
||||
done = BKE_palette_from_hash(bmain, color_table, image->id.name + 2);
|
||||
}
|
||||
|
||||
/* Free memory. */
|
||||
@@ -343,9 +348,9 @@ static wmOperatorStatus palette_sort_exec(bContext *C, wmOperator *op)
|
||||
int t = 0;
|
||||
LISTBASE_FOREACH (PaletteColor *, color, &palette->colors) {
|
||||
float h, s, v;
|
||||
rgb_to_hsv(color->rgb[0], color->rgb[1], color->rgb[2], &h, &s, &v);
|
||||
rgb_to_hsv(color->color[0], color->color[1], color->color[2], &h, &s, &v);
|
||||
col_elm = &color_array[t];
|
||||
copy_v3_v3(col_elm->rgb, color->rgb);
|
||||
copy_v3_v3(col_elm->rgb, color->color);
|
||||
col_elm->value = color->value;
|
||||
col_elm->h = h;
|
||||
col_elm->s = s;
|
||||
@@ -376,7 +381,7 @@ static wmOperatorStatus palette_sort_exec(bContext *C, wmOperator *op)
|
||||
col_elm = &color_array[i];
|
||||
PaletteColor *palcol = BKE_palette_color_add(palette);
|
||||
if (palcol) {
|
||||
copy_v3_v3(palcol->rgb, col_elm->rgb);
|
||||
copy_v3_v3(palcol->color, col_elm->rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -489,7 +494,7 @@ static wmOperatorStatus palette_join_exec(bContext *C, wmOperator *op)
|
||||
LISTBASE_FOREACH (PaletteColor *, color, &palette_join->colors) {
|
||||
PaletteColor *palcol = BKE_palette_color_add(palette);
|
||||
if (palcol) {
|
||||
copy_v3_v3(palcol->rgb, color->rgb);
|
||||
copy_v3_v3(palcol->color, color->color);
|
||||
palcol->value = color->value;
|
||||
done = true;
|
||||
}
|
||||
|
||||
@@ -183,25 +183,6 @@ static void paint_sample_color(
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
const View3D *v3d = CTX_wm_view3d(C);
|
||||
|
||||
bool is_data = false;
|
||||
|
||||
if (v3d) {
|
||||
const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
|
||||
if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
Object *object = BKE_view_layer_active_object_get(view_layer);
|
||||
const Material *material = BKE_object_material_get(object, object->actcol);
|
||||
if (material && material->texpaintslot) {
|
||||
const Image *image = material->texpaintslot[material->paint_active_slot].ima;
|
||||
is_data = image && IMB_colormanagement_space_name_is_data(image->colorspace_settings.name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const Image *image = imapaint->canvas;
|
||||
is_data = image && IMB_colormanagement_space_name_is_data(image->colorspace_settings.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (v3d && texpaint_proj) {
|
||||
/* first try getting a color directly from the mesh faces if possible */
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
@@ -279,17 +260,9 @@ static void paint_sample_color(
|
||||
rgba_f = math::clamp(rgba_f, 0.0f, 1.0f);
|
||||
straight_to_premul_v4(rgba_f);
|
||||
if (use_palette) {
|
||||
if (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) {
|
||||
copy_v3_v3(color->rgb, rgba_f);
|
||||
}
|
||||
else {
|
||||
linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
|
||||
}
|
||||
BKE_palette_color_set(color, rgba_f);
|
||||
}
|
||||
else {
|
||||
if ((ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0) {
|
||||
linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
|
||||
}
|
||||
BKE_brush_color_set(paint, br, rgba_f);
|
||||
}
|
||||
}
|
||||
@@ -297,12 +270,18 @@ static void paint_sample_color(
|
||||
uchar4 rgba = interp == SHD_INTERP_CLOSEST ?
|
||||
imbuf::interpolate_nearest_wrap_byte(ibuf, u, v) :
|
||||
imbuf::interpolate_bilinear_wrap_byte(ibuf, u, v);
|
||||
float rgba_f[4];
|
||||
rgba_uchar_to_float(rgba_f, rgba);
|
||||
|
||||
if ((ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0) {
|
||||
IMB_colormanagement_colorspace_to_scene_linear_v3(rgba_f,
|
||||
ibuf->byte_buffer.colorspace);
|
||||
}
|
||||
|
||||
if (use_palette) {
|
||||
rgb_uchar_to_float(color->rgb, rgba);
|
||||
BKE_palette_color_set(color, rgba_f);
|
||||
}
|
||||
else {
|
||||
float rgba_f[3];
|
||||
rgb_uchar_to_float(rgba_f, rgba);
|
||||
BKE_brush_color_set(paint, br, rgba_f);
|
||||
}
|
||||
}
|
||||
@@ -320,13 +299,10 @@ static void paint_sample_color(
|
||||
/* Sample from the active image buffer. The sampled color is in
|
||||
* Linear Scene Reference Space. */
|
||||
float rgba_f[3];
|
||||
bool is_data;
|
||||
if (ED_space_image_color_sample(sima, region, blender::int2(x, y), rgba_f, &is_data)) {
|
||||
if (!is_data) {
|
||||
linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
|
||||
}
|
||||
|
||||
if (use_palette) {
|
||||
copy_v3_v3(color->rgb, rgba_f);
|
||||
BKE_palette_color_set(color, rgba_f);
|
||||
}
|
||||
else {
|
||||
BKE_brush_color_set(paint, br, rgba_f);
|
||||
@@ -343,25 +319,13 @@ static void paint_sample_color(
|
||||
blender::int2(x + region->winrct.xmin, y + region->winrct.ymin),
|
||||
rgb_fl);
|
||||
|
||||
/* The sampled color is in display space, which is what it is supposed to be when painting on
|
||||
* an image with known colorspace. When painting on non-color/data textures convert display to
|
||||
* scene linear so that painting with the new color will produce the same color after the
|
||||
* texture comes via rendering/color management. */
|
||||
if (is_data) {
|
||||
/* Note that the logic for the image sampling above uses hardcoded linear<->srgb conversion,
|
||||
* as well does the do_projectpaint_draw(). For the consistency use hardcoded conversion here
|
||||
* as well.
|
||||
*
|
||||
* Ideally it should become something like:
|
||||
* const ColorManagedDisplay *display = IMB_colormanagement_display_get_named(
|
||||
* scene->display_settings.display_device);
|
||||
* IMB_colormanagement_display_to_scene_linear_v3(rgb_fl, display);
|
||||
*/
|
||||
srgb_to_linearrgb_v3_v3(rgb_fl, rgb_fl);
|
||||
}
|
||||
/* The sampled color is in display colorspace, convert to scene linear. */
|
||||
const ColorManagedDisplay *display = IMB_colormanagement_display_get_named(
|
||||
scene->display_settings.display_device);
|
||||
IMB_colormanagement_display_to_scene_linear_v3(rgb_fl, display);
|
||||
|
||||
if (use_palette) {
|
||||
copy_v3_v3(color->rgb, rgb_fl);
|
||||
BKE_palette_color_set(color, rgb_fl);
|
||||
}
|
||||
else {
|
||||
BKE_brush_color_set(paint, br, rgb_fl);
|
||||
|
||||
@@ -650,7 +650,7 @@ static ColorPaint4f vpaint_get_current_col(VPaint &vp, bool secondary)
|
||||
float color[4];
|
||||
const float *brush_color = secondary ? BKE_brush_secondary_color_get(&vp.paint, brush) :
|
||||
BKE_brush_color_get(&vp.paint, brush);
|
||||
IMB_colormanagement_srgb_to_scene_linear_v3(color, brush_color);
|
||||
copy_v3_v3(color, brush_color);
|
||||
|
||||
color[3] = 1.0f; /* alpha isn't used, could even be removed to speedup paint a little */
|
||||
|
||||
|
||||
@@ -2579,7 +2579,6 @@ static void cache_initial_config_set(bContext *C, wmOperator *op, Cache &expand_
|
||||
BKE_curvemapping_init(expand_cache.brush->curve);
|
||||
copy_v4_fl(expand_cache.fill_color, 1.0f);
|
||||
copy_v3_v3(expand_cache.fill_color, BKE_brush_color_get(paint, expand_cache.brush));
|
||||
IMB_colormanagement_srgb_to_scene_linear_v3(expand_cache.fill_color, expand_cache.fill_color);
|
||||
|
||||
expand_cache.scene = CTX_data_scene(C);
|
||||
expand_cache.texture_distortion_strength = 0.0f;
|
||||
|
||||
@@ -380,7 +380,6 @@ static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object &ob)
|
||||
float fill_color[3];
|
||||
|
||||
RNA_float_get_array(op->ptr, "fill_color", fill_color);
|
||||
IMB_colormanagement_srgb_to_scene_linear_v3(fill_color, fill_color);
|
||||
|
||||
Mesh &mesh = *static_cast<Mesh *>(ob.data);
|
||||
if (filter_strength < 0.0 && ss.filter_cache->pre_smoothed_color.is_empty()) {
|
||||
@@ -606,7 +605,7 @@ void SCULPT_OT_color_filter(wmOperatorType *ot)
|
||||
0.0f,
|
||||
1.0f);
|
||||
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MESH);
|
||||
RNA_def_property_subtype(prop, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_subtype(prop, PROP_COLOR);
|
||||
}
|
||||
|
||||
} // namespace blender::ed::sculpt_paint::color
|
||||
|
||||
@@ -650,9 +650,7 @@ static wmOperatorStatus sample_color_invoke(bContext *C, wmOperator *op, const w
|
||||
std::get<int>(ss.active_vert()));
|
||||
}
|
||||
|
||||
float color_srgb[3];
|
||||
IMB_colormanagement_scene_linear_to_srgb_v3(color_srgb, active_vertex_color);
|
||||
BKE_brush_color_set(&sd.paint, &brush, color_srgb);
|
||||
BKE_brush_color_set(&sd.paint, &brush, active_vertex_color);
|
||||
|
||||
WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, &brush);
|
||||
|
||||
@@ -1195,7 +1193,7 @@ static wmOperatorStatus mask_from_cavity_exec(bContext *C, wmOperator *op)
|
||||
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
|
||||
|
||||
/* Set up automasking settings. */
|
||||
Sculpt scene_copy = sd;
|
||||
Sculpt scene_copy = dna::shallow_copy(sd);
|
||||
|
||||
MaskSettingsSource src = (MaskSettingsSource)RNA_enum_get(op->ptr, "settings_source");
|
||||
switch (src) {
|
||||
@@ -1389,7 +1387,7 @@ static wmOperatorStatus mask_from_boundary_exec(bContext *C, wmOperator *op)
|
||||
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
|
||||
|
||||
/* Set up automasking settings. */
|
||||
Sculpt scene_copy = sd;
|
||||
Sculpt scene_copy = dna::shallow_copy(sd);
|
||||
|
||||
MaskSettingsSource src = (MaskSettingsSource)RNA_enum_get(op->ptr, "settings_source");
|
||||
switch (src) {
|
||||
|
||||
@@ -430,8 +430,6 @@ static void do_paint_brush_task(const Depsgraph &depsgraph,
|
||||
float3 brush_color_rgb = ss.cache->invert ? BKE_brush_secondary_color_get(&paint, &brush) :
|
||||
BKE_brush_color_get(&paint, &brush);
|
||||
|
||||
IMB_colormanagement_srgb_to_scene_linear_v3(brush_color_rgb, brush_color_rgb);
|
||||
|
||||
const std::optional<BrushColorJitterSettings> color_jitter_settings =
|
||||
BKE_brush_color_jitter_get_settings(&paint, &brush);
|
||||
if (color_jitter_settings) {
|
||||
|
||||
@@ -210,11 +210,7 @@ template<typename ImageBuffer> class PaintingKernel {
|
||||
return;
|
||||
}
|
||||
|
||||
/* NOTE: Brush colors are stored in sRGB. We use math color to follow other areas that
|
||||
* use brush colors. From there on we use IMB_colormanagement to convert the brush color to the
|
||||
* colorspace of the texture. This isn't ideal, but would need more refactoring to make sure
|
||||
* that brush colors are stored in scene linear by default. */
|
||||
srgb_to_linearrgb_v3_v3(brush_color_, in_brush_color);
|
||||
copy_v3_v3(brush_color_, in_brush_color);
|
||||
brush_color_[3] = 1.0f;
|
||||
|
||||
const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(
|
||||
|
||||
@@ -139,5 +139,4 @@ inline void interpolate_cubic_mitchell_byte(const ImBuf *in, uchar output[4], fl
|
||||
/**
|
||||
* Sample pixel of image using NEAREST method.
|
||||
*/
|
||||
void IMB_sampleImageAtLocation(
|
||||
ImBuf *ibuf, float x, float y, bool make_linear_rgb, float color[4]);
|
||||
void IMB_sampleImageAtLocation(ImBuf *ibuf, float x, float y, float scene_linear_rgb[3]);
|
||||
|
||||
@@ -28,6 +28,7 @@ extern blender::float3x3 imbuf_scene_linear_to_aces;
|
||||
extern blender::float3x3 imbuf_aces_to_scene_linear;
|
||||
extern blender::float3x3 imbuf_scene_linear_to_rec709;
|
||||
extern blender::float3x3 imbuf_rec709_to_scene_linear;
|
||||
extern bool imbuf_scene_linear_is_rec709;
|
||||
|
||||
#define MAX_COLORSPACE_NAME 64
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ float3x3 imbuf_scene_linear_to_rec709 = float3x3::zero();
|
||||
float3x3 imbuf_rec709_to_scene_linear = float3x3::zero();
|
||||
float3x3 imbuf_scene_linear_to_aces = float3x3::zero();
|
||||
float3x3 imbuf_aces_to_scene_linear = float3x3::zero();
|
||||
bool imbuf_scene_linear_is_rec709 = false;
|
||||
|
||||
/* lock used by pre-cached processors getters, so processor wouldn't
|
||||
* be created several times
|
||||
@@ -571,6 +572,9 @@ static bool colormanage_load_config(ocio::Config &config)
|
||||
imbuf_aces_to_scene_linear = imbuf_xyz_to_scene_linear * ocio::ACES_TO_XYZ;
|
||||
imbuf_scene_linear_to_aces = math::invert(imbuf_aces_to_scene_linear);
|
||||
|
||||
imbuf_scene_linear_is_rec709 = math::is_equal(
|
||||
imbuf_scene_linear_to_rec709, float3x3::identity(), 0.0001f);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,24 +47,41 @@ void IMB_colormanagement_scene_linear_to_xyz(float xyz[3], const float scene_lin
|
||||
|
||||
void IMB_colormanagement_rec709_to_scene_linear(float scene_linear[3], const float rec709[3])
|
||||
{
|
||||
mul_v3_m3v3(scene_linear, imbuf_rec709_to_scene_linear.ptr(), rec709);
|
||||
if (imbuf_scene_linear_is_rec709) {
|
||||
copy_v3_v3(scene_linear, rec709);
|
||||
}
|
||||
else {
|
||||
mul_v3_m3v3(scene_linear, imbuf_rec709_to_scene_linear.ptr(), rec709);
|
||||
}
|
||||
}
|
||||
|
||||
void IMB_colormanagement_scene_linear_to_rec709(float rec709[3], const float scene_linear[3])
|
||||
{
|
||||
mul_v3_m3v3(rec709, imbuf_scene_linear_to_rec709.ptr(), scene_linear);
|
||||
if (imbuf_scene_linear_is_rec709) {
|
||||
copy_v3_v3(rec709, scene_linear);
|
||||
}
|
||||
else {
|
||||
mul_v3_m3v3(rec709, imbuf_scene_linear_to_rec709.ptr(), scene_linear);
|
||||
}
|
||||
}
|
||||
|
||||
void IMB_colormanagement_scene_linear_to_srgb_v3(float srgb[3], const float scene_linear[3])
|
||||
{
|
||||
mul_v3_m3v3(srgb, imbuf_scene_linear_to_rec709.ptr(), scene_linear);
|
||||
if (imbuf_scene_linear_is_rec709) {
|
||||
copy_v3_v3(srgb, scene_linear);
|
||||
}
|
||||
else {
|
||||
mul_v3_m3v3(srgb, imbuf_scene_linear_to_rec709.ptr(), scene_linear);
|
||||
}
|
||||
linearrgb_to_srgb_v3_v3(srgb, srgb);
|
||||
}
|
||||
|
||||
void IMB_colormanagement_srgb_to_scene_linear_v3(float scene_linear[3], const float srgb[3])
|
||||
{
|
||||
srgb_to_linearrgb_v3_v3(scene_linear, srgb);
|
||||
mul_m3_v3(imbuf_rec709_to_scene_linear.ptr(), scene_linear);
|
||||
if (!imbuf_scene_linear_is_rec709) {
|
||||
mul_m3_v3(imbuf_rec709_to_scene_linear.ptr(), scene_linear);
|
||||
}
|
||||
}
|
||||
|
||||
void IMB_colormanagement_aces_to_scene_linear(float scene_linear[3], const float aces[3])
|
||||
|
||||
@@ -6,21 +6,24 @@
|
||||
* \ingroup imbuf
|
||||
*/
|
||||
|
||||
#include "BLI_math_color.h"
|
||||
|
||||
#include "IMB_colormanagement.hh"
|
||||
#include "IMB_interp.hh"
|
||||
|
||||
void IMB_sampleImageAtLocation(ImBuf *ibuf, float x, float y, bool make_linear_rgb, float color[4])
|
||||
void IMB_sampleImageAtLocation(ImBuf *ibuf, float x, float y, float scene_linear_rgb[3])
|
||||
{
|
||||
using namespace blender;
|
||||
if (ibuf->float_buffer.data) {
|
||||
imbuf::interpolate_nearest_border_fl(ibuf, color, x, y);
|
||||
float rgba[4];
|
||||
imbuf::interpolate_nearest_border_fl(ibuf, rgba, x, y);
|
||||
premul_to_straight_v4_v4(rgba, rgba);
|
||||
copy_v3_v3(scene_linear_rgb, rgba);
|
||||
}
|
||||
else {
|
||||
uchar4 byte_color = imbuf::interpolate_nearest_border_byte(ibuf, x, y);
|
||||
rgba_uchar_to_float(color, byte_color);
|
||||
if (make_linear_rgb) {
|
||||
IMB_colormanagement_colorspace_to_scene_linear_v4(
|
||||
color, false, ibuf->byte_buffer.colorspace);
|
||||
}
|
||||
rgb_uchar_to_float(scene_linear_rgb, byte_color);
|
||||
IMB_colormanagement_colorspace_to_scene_linear_v3(scene_linear_rgb,
|
||||
ibuf->byte_buffer.colorspace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,9 +48,12 @@
|
||||
.fill_threshold = 0.2f, \
|
||||
\
|
||||
/* BRUSH PAINT BRUSH SETTINGS */ \
|
||||
/* Default rgb color of the brush when painting - white. */ \
|
||||
/* Default rgb color of the brush when painting - white. Initialize both
|
||||
* linear and deprecated sRGB values. */ \
|
||||
.color = {1.0f, 1.0f, 1.0f}, \
|
||||
.rgb = {1.0f, 1.0f, 1.0f}, \
|
||||
\
|
||||
.secondary_color = {0, 0, 0}, \
|
||||
.secondary_rgb = {0, 0, 0}, \
|
||||
\
|
||||
/* BRUSH STROKE SETTINGS */ \
|
||||
|
||||
@@ -219,7 +219,7 @@ typedef struct Brush {
|
||||
float rate;
|
||||
|
||||
/** Color. */
|
||||
float rgb[3];
|
||||
float color[3];
|
||||
int color_jitter_flag;
|
||||
float hsv_jitter[3];
|
||||
|
||||
@@ -248,7 +248,11 @@ typedef struct Brush {
|
||||
float tip_scale_x;
|
||||
|
||||
/** Background color. */
|
||||
float secondary_rgb[3];
|
||||
float secondary_color[3];
|
||||
|
||||
/* Deprecated sRGB color for forward compatibility. */
|
||||
float rgb[3] DNA_DEPRECATED;
|
||||
float secondary_rgb[3] DNA_DEPRECATED;
|
||||
|
||||
/** Rate */
|
||||
float dash_ratio;
|
||||
@@ -419,6 +423,8 @@ typedef struct Brush {
|
||||
} Brush;
|
||||
|
||||
/* Struct to hold palette colors for sorting. */
|
||||
#
|
||||
#
|
||||
typedef struct tPaletteColorHSV {
|
||||
float rgb[3];
|
||||
float value;
|
||||
@@ -429,9 +435,13 @@ typedef struct tPaletteColorHSV {
|
||||
|
||||
typedef struct PaletteColor {
|
||||
struct PaletteColor *next, *prev;
|
||||
/* two values, one to store rgb, other to store values for sculpt/weight */
|
||||
float rgb[3];
|
||||
/* Two values, one to store color, other to store values for sculpt/weight. */
|
||||
float color[3];
|
||||
float value;
|
||||
|
||||
/* For forward compatibility. */
|
||||
float rgb[3] DNA_DEPRECATED;
|
||||
float _pad;
|
||||
} PaletteColor;
|
||||
|
||||
typedef struct Palette {
|
||||
|
||||
@@ -305,6 +305,8 @@
|
||||
.unprojected_radius = 0.29, \
|
||||
.alpha = 0.5f, \
|
||||
.weight = 0.5f, \
|
||||
.color = {0.0f, 0.0f, 0.0f}, \
|
||||
.secondary_color = {1.0f, 1.0f, 1.0f}, \
|
||||
.rgb = {0.0f, 0.0f, 0.0f}, \
|
||||
.secondary_rgb = {1.0f, 1.0f, 1.0f}, \
|
||||
.flag = UNIFIED_PAINT_SIZE | UNIFIED_PAINT_COLOR, \
|
||||
|
||||
@@ -1075,6 +1075,8 @@ typedef struct TimeMarker {
|
||||
* values are used
|
||||
*/
|
||||
typedef struct UnifiedPaintSettings {
|
||||
DNA_DEFINE_CXX_METHODS(UnifiedPaintSettings)
|
||||
|
||||
/** Unified radius of brush in pixels. */
|
||||
int size;
|
||||
|
||||
@@ -1088,9 +1090,13 @@ typedef struct UnifiedPaintSettings {
|
||||
float weight;
|
||||
|
||||
/** Unified brush color. */
|
||||
float rgb[3];
|
||||
float color[3];
|
||||
/** Unified brush secondary color. */
|
||||
float secondary_rgb[3];
|
||||
float secondary_color[3];
|
||||
|
||||
/* Deprecated sRGB color for forward compatibility. */
|
||||
float rgb[3] DNA_DEPRECATED;
|
||||
float secondary_rgb[3] DNA_DEPRECATED;
|
||||
|
||||
/** Unified color jitter settings */
|
||||
int color_jitter_flag;
|
||||
@@ -1152,6 +1158,8 @@ typedef struct ToolSystemBrushBindings {
|
||||
|
||||
/** Paint Tool Base. */
|
||||
typedef struct Paint {
|
||||
DNA_DEFINE_CXX_METHODS(Paint)
|
||||
|
||||
/**
|
||||
* The active brush. Possibly null. Possibly stored in a separate #Main data-base and not user-
|
||||
* counted.
|
||||
@@ -1302,6 +1310,8 @@ typedef struct ParticleEditSettings {
|
||||
|
||||
/** Sculpt. */
|
||||
typedef struct Sculpt {
|
||||
DNA_DEFINE_CXX_METHODS(Sculpt)
|
||||
|
||||
Paint paint;
|
||||
|
||||
/** For rotating around a pivot point. */
|
||||
@@ -1646,6 +1656,8 @@ enum {
|
||||
};
|
||||
|
||||
typedef struct ToolSettings {
|
||||
DNA_DEFINE_CXX_METHODS(ToolSettings)
|
||||
|
||||
/** Vertex paint. */
|
||||
VPaint *vpaint;
|
||||
/** Weight paint. */
|
||||
|
||||
@@ -664,6 +664,13 @@ static void rna_Brush_update(Main * /*bmain*/, Scene * /*scene*/, PointerRNA *pt
|
||||
// WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, nullptr);
|
||||
}
|
||||
|
||||
static void rna_Brush_color_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
Brush *br = static_cast<Brush *>(ptr->data);
|
||||
rna_Brush_update(bmain, scene, ptr);
|
||||
BKE_brush_color_sync_legacy(br);
|
||||
}
|
||||
|
||||
static void rna_Brush_material_update(bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
Brush *br = static_cast<Brush *>(ptr->data);
|
||||
@@ -2824,17 +2831,17 @@ static void rna_def_brush(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Rate", "Interval between paints for Airbrush");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 3);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "rgb");
|
||||
RNA_def_property_float_sdna(prop, nullptr, "color");
|
||||
RNA_def_property_ui_text(prop, "Color", "");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_color_update");
|
||||
|
||||
prop = RNA_def_property(srna, "secondary_color", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
prop = RNA_def_property(srna, "secondary_color", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 3);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "secondary_rgb");
|
||||
RNA_def_property_float_sdna(prop, nullptr, "secondary_color");
|
||||
RNA_def_property_ui_text(prop, "Secondary Color", "");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_color_update");
|
||||
|
||||
prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
# include "DNA_brush_types.h"
|
||||
|
||||
# include "BLI_math_color.h"
|
||||
|
||||
# include "BKE_library.hh"
|
||||
# include "BKE_paint.hh"
|
||||
# include "BKE_report.hh"
|
||||
@@ -60,6 +62,13 @@ static void rna_Palette_color_clear(Palette *palette)
|
||||
BKE_palette_clear(palette);
|
||||
}
|
||||
|
||||
static void rna_PaletteColor_color_update(Main * /*bmain*/, Scene * /*scene*/, PointerRNA *ptr)
|
||||
{
|
||||
/* For forward compatibility. */
|
||||
PaletteColor *color = static_cast<PaletteColor *>(ptr->data);
|
||||
BKE_palette_color_sync_legacy(color);
|
||||
}
|
||||
|
||||
static PointerRNA rna_Palette_active_color_get(PointerRNA *ptr)
|
||||
{
|
||||
Palette *palette = static_cast<Palette *>(ptr->data);
|
||||
@@ -137,13 +146,13 @@ static void rna_def_palettecolor(BlenderRNA *brna)
|
||||
srna = RNA_def_struct(brna, "PaletteColor", nullptr);
|
||||
RNA_def_struct_ui_text(srna, "Palette Color", "");
|
||||
|
||||
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_range(prop, 0.0, 1.0);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "rgb");
|
||||
RNA_def_property_float_sdna(prop, nullptr, "color");
|
||||
RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Color", "");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_PaletteColor_color_update");
|
||||
|
||||
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_range(prop, 0.0, 1.0);
|
||||
|
||||
@@ -527,6 +527,13 @@ static void rna_UnifiedPaintSettings_update(bContext *C, PointerRNA * /*ptr*/)
|
||||
WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, scene);
|
||||
}
|
||||
|
||||
static void rna_UnifiedPaintSettings_color_update(bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
UnifiedPaintSettings *ups = static_cast<UnifiedPaintSettings *>(ptr->data);
|
||||
rna_UnifiedPaintSettings_update(C, ptr);
|
||||
BKE_brush_color_sync_legacy(ups);
|
||||
}
|
||||
|
||||
static void rna_UnifiedPaintSettings_size_set(PointerRNA *ptr, int value)
|
||||
{
|
||||
UnifiedPaintSettings *ups = static_cast<UnifiedPaintSettings *>(ptr->data);
|
||||
@@ -849,19 +856,19 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Weight", "Weight to assign in vertex groups");
|
||||
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
|
||||
|
||||
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_range(prop, 0.0, 1.0);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "rgb");
|
||||
RNA_def_property_float_sdna(prop, nullptr, "color");
|
||||
RNA_def_property_ui_text(prop, "Color", "");
|
||||
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
|
||||
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_color_update");
|
||||
|
||||
prop = RNA_def_property(srna, "secondary_color", PROP_FLOAT, PROP_COLOR_GAMMA);
|
||||
prop = RNA_def_property(srna, "secondary_color", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_range(prop, 0.0, 1.0);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "secondary_rgb");
|
||||
RNA_def_property_float_sdna(prop, nullptr, "secondary_color");
|
||||
RNA_def_property_ui_text(prop, "Secondary Color", "");
|
||||
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
|
||||
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_color_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_color_jitter", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
|
||||
Reference in New Issue
Block a user