Commit: d79427986bcd272925660c91a3498a7d2c237848
Author: Pablo Dobarro
Date:   Fri May 31 22:46:29 2019 +0200
Branches: sculpt-mode-features
https://developer.blender.org/rBd79427986bcd272925660c91a3498a7d2c237848

Sculpt vertex colors: Color filter tool

This tool allows the manipulation of all the colors stored in the
vertices at once. Behavior and implementation are similar to the mesh
filter tool. Sculpt vertex colors are not connected to the renderer, so
the viewport does not update when EEVEE/Cycles is enabled.
I also added some separators to the toolbar to separate brushes from
filters.

===================================================================

M       release/scripts/presets/keyconfig/keymap_data/blender_default.py
M       release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
M       source/blender/editors/sculpt_paint/sculpt.c
M       source/blender/editors/sculpt_paint/sculpt_intern.h

===================================================================

diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py 
b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 2cc1c3a9178..63b9875c116 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -5531,6 +5531,16 @@ def km_3d_view_tool_sculpt_mesh_filter(params):
         ]},
     )
 
+def km_3d_view_tool_sculpt_color_filter(params):
+    return (
+        "3D View Tool: Sculpt, Color Filter",
+        {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+        {"items": [
+            ("sculpt.color_filter", {"type": params.tool_tweak, "value": 
'ANY'},
+             None)
+        ]},
+    )
+
 
 def km_3d_view_tool_sculpt_mask_filter(params):
     return (
@@ -5963,6 +5973,7 @@ def generate_keymaps(params=None):
         km_3d_view_tool_sculpt_box_hide(params),
         km_3d_view_tool_sculpt_box_mask(params),
         km_3d_view_tool_sculpt_mesh_filter(params),
+        km_3d_view_tool_sculpt_color_filter(params),
         km_3d_view_tool_sculpt_mask_filter(params),
         km_3d_view_tool_paint_weight_sample_weight(params),
         km_3d_view_tool_paint_weight_sample_vertex_group(params),
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py 
b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 426e6ac0cd6..a1a0f7cd636 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -1007,6 +1007,24 @@ class _defs_sculpt:
             draw_settings=draw_settings,
         )
 
+    @ToolDef.from_fn
+    def color_filter():
+        def draw_settings(context, layout, tool):
+            props = tool.operator_properties("sculpt.color_filter")
+            sub = layout.row()
+            sub.use_property_split = False
+            sub.prop(props, "type", expand=False)
+            sub.prop(props, "strength")
+
+        return dict(
+            idname="builtin.color_filter",
+            label="Color Filter",
+            icon="ops.sculpt.color_filter",
+            widget=None,
+            keymap= (),
+            draw_settings=draw_settings,
+        )
+
     @ToolDef.from_fn
     def translate():
         def draw_settings(context, layout, tool):
@@ -1950,8 +1968,11 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, 
Panel):
             None,
             _defs_sculpt.hide_border,
             _defs_sculpt.mask_border,
+            None,
             _defs_sculpt.mesh_filter,
+            _defs_sculpt.color_filter,
             _defs_sculpt.mask_filter,
+            None,
             _defs_sculpt.translate,
             _defs_transform.rotate,
             *_tools_annotate,
diff --git a/source/blender/editors/sculpt_paint/sculpt.c 
b/source/blender/editors/sculpt_paint/sculpt.c
index 872c4c29cb6..975889c7498 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1722,6 +1722,43 @@ static float neighbor_max_mask(SculptSession *ss, const 
int vert, float *prev_ma
   return max;
 }
 
+static void neighbor_average_color(SculptSession *ss, float avg[3], unsigned 
vert)
+{
+  const MeshElemMap *vert_map = &ss->pmap[vert];
+  const MVert *mvert = ss->mvert;
+  const float f = 0.00392156862;
+
+  /* Don't modify corner vertices */
+  if (vert_map->count > 1) {
+    int i, total = 0;
+
+    zero_v3(avg);
+
+    for (i = 0; i < vert_map->count; i++) {
+      const MPoly *p = &ss->mpoly[vert_map->indices[i]];
+      unsigned f_adj_v[2];
+
+      if (poly_get_adj_loops_from_vert(p, ss->mloop, vert, f_adj_v) != -1) {
+        int j;
+        for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) {
+          if (vert_map->count != 2 || ss->pmap[f_adj_v[j]].count <= 2) {
+            float orig_color[3];
+            orig_color[0] = ss->filter_cache->orvcol[f_adj_v[j]].r * f;
+            orig_color[1] = ss->filter_cache->orvcol[f_adj_v[j]].g * f;
+            orig_color[2] = ss->filter_cache->orvcol[f_adj_v[j]].b * f;
+            add_v3_v3(avg, orig_color);
+            total++;
+          }
+        }
+      }
+    }
+
+    if (total > 0) {
+      mul_v3_fl(avg, 1.0f / total);
+      return;
+    }
+  }
+}
 /* Same logic as neighbor_average(), but for bmesh rather than mesh */
 static void bmesh_neighbor_average(float avg[3], BMVert *v)
 {
@@ -7587,11 +7624,16 @@ static void filter_cache_init_task_cb(void *__restrict 
userdata,
   BKE_pbvh_vertex_iter_end;
 
   if (data->node_mask[i] == 1) {
-    sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS);
+    if (data->init_colors) {
+      sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_COLOR);
+    }
+    else {
+      sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_COORDS);
+    }
   }
 }
 
-static void sculpt_filter_cache_init(Object *ob, Sculpt *sd, bool init_random)
+static void sculpt_filter_cache_init(Object *ob, Sculpt *sd, bool init_random, 
bool init_colors)
 {
   SculptSession *ss = ob->sculpt;
   PBVH *pbvh = ob->sculpt->pbvh;
@@ -7605,6 +7647,10 @@ static void sculpt_filter_cache_init(Object *ob, Sculpt 
*sd, bool init_random)
                                                 "random_disp");
   }
 
+  if (init_colors && ss->vcol) {
+    ss->filter_cache->orvcol = MEM_dupallocN(ss->vcol);
+  }
+
   SculptSearchSphereData searchdata = {
       .ss = ss,
       .sd = sd,
@@ -7630,6 +7676,7 @@ static void sculpt_filter_cache_init(Object *ob, Sculpt 
*sd, bool init_random)
       .ob = ob,
       .nodes = nodes,
       .filter_type = filter_type,
+      .init_colors = init_colors,
       .random_disp = ss->filter_cache->random_disp,
       .node_mask = node_mask,
   };
@@ -7677,6 +7724,9 @@ static void sculpt_filter_cache_free(SculptSession *ss)
   if (ss->filter_cache->random_disp) {
     MEM_freeN(ss->filter_cache->random_disp);
   }
+  if (ss->filter_cache->orvcol) {
+    MEM_freeN(ss->filter_cache->orvcol);
+  }
   MEM_freeN(ss->filter_cache);
 }
 
@@ -7865,7 +7915,7 @@ int sculpt_mesh_filter_invoke(bContext *C, wmOperator 
*op, const wmEvent *event)
 
   sculpt_undo_push_begin("mesh filter fill");
 
-  sculpt_filter_cache_init(ob, sd, mode == MESH_FILTER_RANDOM);
+  sculpt_filter_cache_init(ob, sd, mode == MESH_FILTER_RANDOM, false);
 
   WM_event_add_modal_handler(C, op);
   return OPERATOR_RUNNING_MODAL;
@@ -7891,6 +7941,279 @@ void SCULPT_OT_mesh_filter(struct wmOperatorType *ot)
       ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter 
Strength", -10.0f, 10.0f);
 }
 
+typedef enum eSculptColorFilterTypes {
+  COLOR_FILTER_HUE = 0,
+  COLOR_FILTER_SATURATION = 1,
+  COLOR_FILTER_VALUE = 2,
+  COLOR_FILTER_RED = 3,
+  COLOR_FILTER_GREEN = 4,
+  COLOR_FILTER_BLUE = 5,
+  COLOR_FILTER_SMOOTH = 6,
+  COLOR_FILTER_RANDOM_HUE = 7,
+  COLOR_FILTER_RANDOM_SATURATION = 8,
+  COLOR_FILTER_RANDOM_VALUE = 9,
+  COLOR_FILTER_BRIGHTNESS = 10,
+  COLOR_FILTER_CONTRAST = 11,
+} eSculptColorFilterTypes;
+
+EnumPropertyItem prop_color_filter_types[] = {
+    {COLOR_FILTER_HUE, "HUE", 0, "Hue", "Change hue"},
+    {COLOR_FILTER_SATURATION, "SATURATION", 0, "Saturation", "Change 
saturation"},
+    {COLOR_FILTER_VALUE, "VALUE", 0, "Value", "Change value"},
+
+    {COLOR_FILTER_BRIGHTNESS, "BRIGTHNESS", 0, "Brightness", "Change 
brightness"},
+    {COLOR_FILTER_CONTRAST, "CONTRAST", 0, "Contrast", "Change contrast"},
+
+    {COLOR_FILTER_SMOOTH, "SMOOTH", 0, "Smooth", "Smooth colors"},
+
+    {COLOR_FILTER_RED, "RED", 0, "Red", "Change red"},
+    {COLOR_FILTER_GREEN, "GREEN", 0, "Green", "Change green"},
+    {COLOR_FILTER_BLUE, "BLUE", 0, "Blue", "Change blue"},
+
+    {COLOR_FILTER_RANDOM_HUE, "RANDOM_HUE", 0, "Random hue", "Change hue"},
+    {COLOR_FILTER_RANDOM_SATURATION,
+     "RANDOM_SATURATION",
+     0,
+     "Random saturation",
+     "Change saturation"},
+    {COLOR_FILTER_RANDOM_VALUE, "RANDOM_VALUE", 0, "Random Value", "Change 
value"},
+
+    {0, NULL, 0, NULL, NULL},
+};
+
+static void color_filter_task_cb(void *__restrict userdata,
+                                 const int i,
+                                 const ParallelRangeTLS *__restrict 
UNUSED(tls))
+{
+  SculptThreadedTaskData *data = userdata;
+  SculptSession *ss = data->ob->sculpt;
+  PBVHNode *node = data->nodes[i];
+
+  const int mode = data->filter_type;
+
+  PBVHVertexIter vd;
+  BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+  {
+    float orig_color[3], final_color[3], hsv_color[3], rgb_color[3], d[3];
+    int hue;
+    float brightness, contrast, gain, delta, offset;
+    float fade = vd.mask ? *vd.mask : 1.0f;
+    fade = 1 - fade;
+    fade *= data->filter_strength;
+    // 1/255
+    const float f = 0.00392156862;
+
+    orig_color[0] = ss->filter_cache->orvcol[vd.vert_indices[vd.i]].r * f;
+    orig_color[1] = ss->filter_cache->orvcol[vd.vert_indices[vd.i]].g * f;
+    orig_color[2] = ss->filter_cache->orvcol[vd.vert_indices[vd.i]].b * f;
+
+    switch (mode) {
+      case COLOR_FILTER_HUE:
+        rgb_to_hsv_v(orig_color, hsv_color);
+        hue = hsv_color[0] + fade;
+        hsv_color[0] = fabs((hsv_color[0] + fade) - hue);
+        hsv_to_rgb_v(hsv_color, final_color);
+        break;
+      case COLOR_FILTER_SATURATION:
+        rgb_to_hsv_v(orig_color, hsv_color);
+        hsv_color[1] = hsv_color[1] + fade;
+        CLAMP(hsv_color[1], 0.0f, 1.0f);
+        hsv_to_rgb_v(hsv_color, final_color);
+        break;
+      case COLOR_FILTER_VALUE:
+        rgb_to_hsv_v(orig_color, hsv_color);
+        hsv_color[2] = hsv_color[2] + fade;
+        CLAMP(hsv_color[2], 0.0f, 1.0f);
+        hsv_to_rgb_v(hsv_color, final_color);
+        break;
+      case COLOR_FILTER_RED:
+        orig_color[0] = orig_color[0] + fade;
+        CLAMP(orig_color[0], 0.0f, 1.0f);
+        copy_v3_v3(final_color, orig_color);
+        break;
+      case COLOR_FILTER_GREEN:
+        orig_color[1] = orig_color[1] + fade;
+        CLAMP(orig_color[1], 0.0f, 1.0f);
+        copy_v3_v3(final_color, orig_color);
+        break;
+      case COLOR_FILTER_BLUE:
+        orig_color[2] = orig_color[2] + fade;
+        CLAMP(orig_color[2], 0.0f, 1.0f);
+        copy_v3_v3(final_color, orig_color);
+        break;
+      case COLOR_FILTER

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to