[Bf-blender-cvs] [d79427986bc] sculpt-mode-features: Sculpt vertex colors: Color filter tool

Pablo Dobarro noreply at git.blender.org
Fri May 31 22:46:31 CEST 2019


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. @@



More information about the Bf-blender-cvs mailing list