GSOC 2013 paint

Yep, at last it's here!

There are a few minor issues remaining but development can go on in
master after discussion at blender institute.

For full list of features see:

http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.72/Painting

Thanks to Sergey and Campbell for the extensive review and to the
countless artists that have given their input and reported issues during
development.
This commit is contained in:
2014-07-21 12:02:05 +02:00
parent 8489b94e07
commit f745564e4e
113 changed files with 7930 additions and 1223 deletions
+2
View File
@@ -730,6 +730,8 @@ if B.targets != ['cudakernels']:
data_to_c_simple("release/datafiles/brushicons/soften.png")
data_to_c_simple("release/datafiles/brushicons/subtract.png")
data_to_c_simple("release/datafiles/brushicons/texdraw.png")
data_to_c_simple("release/datafiles/brushicons/texfill.png")
data_to_c_simple("release/datafiles/brushicons/texmask.png")
data_to_c_simple("release/datafiles/brushicons/thumb.png")
data_to_c_simple("release/datafiles/brushicons/twist.png")
data_to_c_simple("release/datafiles/brushicons/vertexdraw.png")
@@ -50,6 +50,10 @@ class UnifiedPaintPanel():
row.prop(ups, "use_unified_strength", text="Strength")
if context.weight_paint_object:
parent.prop(ups, "use_unified_weight", text="Weight")
elif context.vertex_paint_object or context.image_paint_object:
parent.prop(ups, "use_unified_color", text="Color")
else:
parent.prop(ups, "use_unified_color", text="Color")
@staticmethod
def prop_unified_size(parent, context, brush, prop_name, icon='NONE', text="", slider=False):
@@ -69,6 +73,105 @@ class UnifiedPaintPanel():
ptr = ups if ups.use_unified_weight else brush
parent.prop(ptr, prop_name, icon=icon, text=text, slider=slider)
@staticmethod
def prop_unified_color(parent, context, brush, prop_name, text=""):
ups = context.tool_settings.unified_paint_settings
ptr = ups if ups.use_unified_color else brush
parent.prop(ptr, prop_name, text=text)
@staticmethod
def prop_unified_color_picker(parent, context, brush, prop_name, value_slider=True):
ups = context.tool_settings.unified_paint_settings
ptr = ups if ups.use_unified_color else brush
parent.template_color_picker(ptr, prop_name, value_slider=value_slider)
def brush_texpaint_common(panel, context, layout, brush, settings):
capabilities = brush.image_paint_capabilities
col = layout.column()
if brush.image_tool in {'DRAW', 'FILL'}:
if brush.blend not in {'ERASE_ALPHA', 'ADD_ALPHA'}:
if not brush.use_gradient:
panel.prop_unified_color_picker(col, context, brush, "color", value_slider=True)
if settings.palette:
col.template_palette(settings, "palette", color=True)
if brush.use_gradient:
col.label("Gradient Colors")
col.template_color_ramp(brush, "gradient", expand=True)
if brush.image_tool != 'FILL':
col.label("Background Color")
row = col.row(align=True)
panel.prop_unified_color(row, context, brush, "secondary_color", text="")
if brush.image_tool == 'DRAW':
col.prop(brush, "gradient_stroke_mode", text="Mode")
if brush.gradient_stroke_mode in {'SPACING_REPEAT', 'SPACING_CLAMP'}:
col.prop(brush, "grad_spacing")
elif brush.image_tool == 'FILL':
col.prop(brush, "gradient_fill_mode")
else:
row = col.row(align=True)
panel.prop_unified_color(row, context, brush, "color", text="")
if brush.image_tool == 'FILL':
col.prop(brush, "fill_threshold")
else:
panel.prop_unified_color(row, context, brush, "secondary_color", text="")
row.separator()
row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="")
elif brush.image_tool == 'SOFTEN':
col = layout.column(align=True)
col.row().prop(brush, "direction", expand=True)
col.separator()
col.prop(brush, "sharp_threshold")
col.prop(brush, "blur_kernel_radius")
col.separator()
col.prop(brush, "blur_mode")
elif brush.image_tool == 'MASK':
col.prop(brush, "weight", text="Mask Value", slider=True)
elif brush.image_tool == 'CLONE':
col.separator()
col.prop(brush, "clone_image", text="Image")
col.prop(brush, "clone_alpha", text="Alpha")
col.separator()
if capabilities.has_radius:
row = col.row(align=True)
panel.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
panel.prop_unified_size(row, context, brush, "use_pressure_size")
row = col.row(align=True)
if capabilities.has_space_attenuation:
row.prop(brush, "use_space_attenuation", toggle=True, icon_only=True)
panel.prop_unified_strength(row, context, brush, "strength", text="Strength")
panel.prop_unified_strength(row, context, brush, "use_pressure_strength")
if brush.image_tool in {'DRAW', 'FILL'}:
col.separator()
col.prop(brush, "blend", text="Blend")
col = layout.column()
# use_accumulate
if capabilities.has_accumulate:
col = layout.column(align=True)
col.prop(brush, "use_accumulate")
col.prop(brush, "use_alpha")
col.prop(brush, "use_gradient")
col.separator()
col.template_ID(settings, "palette", new="palette.new")
# Used in both the View3D toolbar and texture properties
def brush_texture_settings(layout, brush, sculpt):
@@ -136,6 +239,7 @@ def brush_mask_texture_settings(layout, brush):
layout.operator("brush.stencil_reset_transform").mask = True
col = layout.column()
col.prop(brush, "use_pressure_masking", text="")
col.label(text="Angle:")
col.active = brush.brush_capabilities.has_texture_angle
col.prop(mask_tex_slot, "angle", text="")
+83 -47
View File
@@ -22,6 +22,7 @@ from bpy.types import Header, Menu, Panel
from bl_ui.properties_paint_common import (
UnifiedPaintPanel,
brush_texture_settings,
brush_texpaint_common,
brush_mask_texture_settings,
)
from bl_ui.properties_grease_pencil_common import GreasePencilPanel
@@ -31,13 +32,11 @@ from bpy.app.translations import pgettext_iface as iface_
class ImagePaintPanel(UnifiedPaintPanel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
bl_category = "Tools"
class BrushButtonsPanel:
class BrushButtonsPanel(UnifiedPaintPanel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
bl_category = "Tools"
@classmethod
def poll(cls, context):
@@ -66,6 +65,7 @@ class IMAGE_MT_view(Menu):
sima = context.space_data
uv = sima.uv_editor
toolsettings = context.tool_settings
paint = toolsettings.image_paint
show_uvedit = sima.show_uvedit
show_render = sima.show_render
@@ -80,6 +80,8 @@ class IMAGE_MT_view(Menu):
layout.prop(toolsettings, "show_uv_local_view")
layout.prop(uv, "show_other_objects")
if paint.brush and (context.image_paint_object or sima.mode == 'PAINT'):
layout.prop(uv, "show_texpaint")
layout.separator()
@@ -140,6 +142,24 @@ class IMAGE_MT_select(Menu):
layout.operator("uv.select_split")
class IMAGE_MT_brush(Menu):
bl_label = "Brush"
def draw(self, context):
layout = self.layout
toolsettings = context.tool_settings
settings = toolsettings.image_paint
brush = settings.brush
ups = context.tool_settings.unified_paint_settings
layout.prop(ups, "use_unified_size", text="Unified Size")
layout.prop(ups, "use_unified_strength", text="Unified Strength")
layout.separator()
# brush tool
layout.prop_menu_enum(brush, "image_tool")
class IMAGE_MT_image(Menu):
bl_label = "Image"
@@ -382,7 +402,6 @@ class IMAGE_HT_header(Header):
mode = sima.mode
show_render = sima.show_render
# show_paint = sima.show_paint
show_uvedit = sima.show_uvedit
show_maskedit = sima.show_maskedit
@@ -401,8 +420,7 @@ class IMAGE_HT_header(Header):
row = layout.row()
row.template_ID(sima, "mask", new="mask.new")
if show_uvedit or show_maskedit:
layout.prop(sima, "pivot_point", icon_only=True)
layout.prop(sima, "pivot_point", icon_only=True)
# uv editing
if show_uvedit:
@@ -462,6 +480,7 @@ class MASK_MT_editor_menus(Menu):
show_uvedit = sima.show_uvedit
show_maskedit = sima.show_maskedit
show_paint = sima.show_paint
layout.menu("IMAGE_MT_view")
@@ -469,6 +488,8 @@ class MASK_MT_editor_menus(Menu):
layout.menu("IMAGE_MT_select")
if show_maskedit:
layout.menu("MASK_MT_select")
if show_paint:
layout.menu("IMAGE_MT_brush")
if ima and ima.is_dirty:
layout.menu("IMAGE_MT_image", text="Image*")
@@ -658,49 +679,27 @@ class IMAGE_PT_tools_transform_uvs(Panel, UVToolsPanel):
col.operator("transform.shear")
class IMAGE_PT_paint(Panel, ImagePaintPanel):
class IMAGE_PT_paint(Panel, BrushButtonsPanel):
bl_label = "Paint"
@classmethod
def poll(cls, context):
sima = context.space_data
return sima.show_paint
bl_category = "Tools"
def draw(self, context):
layout = self.layout
toolsettings = context.tool_settings.image_paint
brush = toolsettings.brush
settings = context.tool_settings.image_paint
brush = settings.brush
col = layout.column()
col.template_ID_preview(toolsettings, "brush", new="brush.add", rows=2, cols=6)
col.template_ID_preview(settings, "brush", new="brush.add", rows=2, cols=6)
if brush:
col = layout.column()
if brush.image_tool == 'DRAW' and brush.blend not in ('ERASE_ALPHA', 'ADD_ALPHA'):
col.template_color_picker(brush, "color", value_slider=True)
col.prop(brush, "color", text="")
row = col.row(align=True)
self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
self.prop_unified_size(row, context, brush, "use_pressure_size")
row = col.row(align=True)
self.prop_unified_strength(row, context, brush, "strength", slider=True, text="Strength")
self.prop_unified_strength(row, context, brush, "use_pressure_strength")
col.prop(brush, "blend", text="Blend")
if brush.image_tool == 'CLONE':
col.separator()
col.prop(brush, "clone_image", text="Image")
col.prop(brush, "clone_alpha", text="Alpha")
brush_texpaint_common(self, context, layout, brush, settings)
class IMAGE_PT_tools_brush_overlay(BrushButtonsPanel, Panel):
bl_label = "Overlay"
bl_options = {'DEFAULT_CLOSED'}
bl_category = "Options"
def draw(self, context):
layout = self.layout
@@ -754,6 +753,7 @@ class IMAGE_PT_tools_brush_overlay(BrushButtonsPanel, Panel):
class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, Panel):
bl_label = "Texture"
bl_options = {'DEFAULT_CLOSED'}
bl_category = "Tools"
def draw(self, context):
layout = self.layout
@@ -770,6 +770,7 @@ class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, Panel):
class IMAGE_PT_tools_mask_texture(BrushButtonsPanel, Panel):
bl_label = "Texture Mask"
bl_options = {'DEFAULT_CLOSED'}
bl_category = "Tools"
def draw(self, context):
layout = self.layout
@@ -786,6 +787,7 @@ class IMAGE_PT_tools_mask_texture(BrushButtonsPanel, Panel):
class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, Panel):
bl_label = "Tool"
bl_options = {'DEFAULT_CLOSED'}
bl_category = "Options"
def draw(self, context):
layout = self.layout
@@ -804,6 +806,7 @@ class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, Panel):
class IMAGE_PT_paint_stroke(BrushButtonsPanel, Panel):
bl_label = "Paint Stroke"
bl_options = {'DEFAULT_CLOSED'}
bl_category = "Tools"
def draw(self, context):
layout = self.layout
@@ -828,10 +831,19 @@ class IMAGE_PT_paint_stroke(BrushButtonsPanel, Panel):
if brush.use_space:
col.separator()
row = col.row(align=True)
row.active = brush.use_space
row.prop(brush, "spacing", text="Spacing")
row.prop(brush, "use_pressure_spacing", toggle=True, text="")
if brush.use_line or brush.use_curve:
col.separator()
row = col.row(align=True)
row.prop(brush, "spacing", text="Spacing")
if brush.use_curve:
col.separator()
col.template_ID(brush, "paint_curve", new="paintcurve.new")
col.operator("paintcurve.draw")
col = layout.column()
col.separator()
@@ -846,25 +858,23 @@ class IMAGE_PT_paint_stroke(BrushButtonsPanel, Panel):
col = layout.column()
col.separator()
col.prop(brush, "use_smooth_stroke")
if brush.brush_capabilities.has_smooth_stroke:
col.prop(brush, "use_smooth_stroke")
sub = col.column()
sub.active = brush.use_smooth_stroke
sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
sub = col.column()
sub.active = brush.use_smooth_stroke
sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
col.separator()
col.separator()
col.prop(toolsettings, "input_samples")
col.separator()
col.prop(brush, "use_wrap")
class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel):
bl_label = "Paint Curve"
bl_options = {'DEFAULT_CLOSED'}
bl_category = "Tools"
def draw(self, context):
layout = self.layout
@@ -874,7 +884,8 @@ class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel):
layout.template_curve_mapping(brush, "curve")
row = layout.row(align=True)
col = layout.column(align=True)
row = col.row(align=True)
row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
@@ -886,6 +897,7 @@ class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel):
class IMAGE_PT_tools_brush_appearance(BrushButtonsPanel, Panel):
bl_label = "Appearance"
bl_options = {'DEFAULT_CLOSED'}
bl_category = "Options"
def draw(self, context):
layout = self.layout
@@ -912,6 +924,30 @@ class IMAGE_PT_tools_brush_appearance(BrushButtonsPanel, Panel):
sub.prop(brush, "icon_filepath", text="")
class IMAGE_PT_tools_paint_options(BrushButtonsPanel, Panel):
bl_label = "Image Paint"
bl_category = "Options"
def draw(self, context):
layout = self.layout
toolsettings = context.tool_settings
brush = toolsettings.image_paint.brush
ups = toolsettings.unified_paint_settings
col = layout.column(align=True)
col.prop(brush, "use_wrap")
col.separator()
col.label(text="Unified Settings:")
row = col.row()
row.prop(ups, "use_unified_size", text="Size")
row.prop(ups, "use_unified_strength", text="Strength")
col.prop(ups, "use_unified_color", text="Color")
class IMAGE_UV_sculpt_curve(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOLS'
@@ -1454,7 +1454,7 @@ class VIEW3D_MT_brush(Menu):
layout.separator()
if sculpt_tool != 'GRAB':
layout.prop_menu_enum(brush, "stroke_method")
layout.prop_menu_enum(brush, "sculpt_stroke_method")
if sculpt_tool in {'DRAW', 'PINCH', 'INFLATE', 'LAYER', 'CLAY'}:
layout.prop_menu_enum(brush, "direction")
@@ -18,11 +18,12 @@
# <pep8 compliant>
import bpy
from bpy.types import Menu, Panel
from bpy.types import Menu, Panel, UIList
from bl_ui.properties_grease_pencil_common import GreasePencilPanel
from bl_ui.properties_paint_common import (
UnifiedPaintPanel,
brush_texture_settings,
brush_texpaint_common,
brush_mask_texture_settings,
)
@@ -363,6 +364,7 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, Panel):
draw_repeat_tools(context, layout)
class VIEW3D_PT_tools_meshweight(View3DPanel, Panel):
bl_category = "Tools"
bl_context = "mesh_edit"
@@ -388,6 +390,7 @@ class VIEW3D_PT_tools_meshweight(View3DPanel, Panel):
layout = self.layout
self.draw_generic(layout)
class VIEW3D_PT_tools_add_mesh_edit(View3DPanel, Panel):
bl_category = "Create"
bl_context = "mesh_edit"
@@ -979,25 +982,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
# Texture Paint Mode #
elif context.image_paint_object and brush:
col = layout.column()
if brush.image_tool == 'DRAW' and brush.blend not in ('ERASE_ALPHA', 'ADD_ALPHA'):
col.template_color_picker(brush, "color", value_slider=True)
col.prop(brush, "color", text="")
row = col.row(align=True)
self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
self.prop_unified_size(row, context, brush, "use_pressure_size")
row = col.row(align=True)
self.prop_unified_strength(row, context, brush, "strength", text="Strength")
self.prop_unified_strength(row, context, brush, "use_pressure_strength")
col.prop(brush, "blend", text="Blend")
col = layout.column()
col.active = (brush.blend not in {'ERASE_ALPHA', 'ADD_ALPHA'})
col.prop(brush, "use_alpha")
brush_texpaint_common(self, context, layout, brush, settings)
# Weight Paint Mode #
elif context.weight_paint_object and brush:
@@ -1024,9 +1009,12 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
# Vertex Paint Mode #
elif context.vertex_paint_object and brush:
col = layout.column()
col.template_color_picker(brush, "color", value_slider=True)
col.prop(brush, "color", text="")
self.prop_unified_color_picker(col, context, brush, "color", value_slider=True)
if settings.palette:
col.template_palette(settings, "palette", color=True)
self.prop_unified_color(col, context, brush, "color", text="")
col.separator()
row = col.row(align=True)
self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
self.prop_unified_size(row, context, brush, "use_pressure_size")
@@ -1036,12 +1024,75 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
self.prop_unified_strength(row, context, brush, "use_pressure_strength")
# XXX - TODO
#row = col.row(align=True)
#row.prop(brush, "jitter", slider=True)
#row.prop(brush, "use_pressure_jitter", toggle=True, text="")
# row = col.row(align=True)
# row.prop(brush, "jitter", slider=True)
# row.prop(brush, "use_pressure_jitter", toggle=True, text="")
col.separator()
col.prop(brush, "vertex_tool", text="Blend")
col.separator()
col.template_ID(settings, "palette", new="palette.new")
class TEXTURE_UL_texpaintslots(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
ma = data
ima = item
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.label(text=ima.name, translate=False, icon_value=icon)
elif self.layout_type in {'GRID'}:
layout.alignment = 'CENTER'
layout.label(text="")
class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
bl_context = "imagepaint"
bl_label = "Slots"
bl_category = "Layers"
@classmethod
def poll(cls, context):
brush = context.tool_settings.image_paint.brush
ob = context.active_object
return (brush is not None and ob is not None)
def draw(self, context):
layout = self.layout
settings = context.tool_settings.image_paint
brush = settings.brush
ob = context.active_object
col = layout.column()
if len(ob.material_slots) > 1:
col.label("Materials")
col.template_list("MATERIAL_UL_matslots", "",
ob, "material_slots",
ob, "active_material_index", rows=2)
mat = ob.active_material
if mat:
col.label("Available Paint Slots")
col.template_list("TEXTURE_UL_texpaintslots", "",
mat, "texture_paint_slots",
mat, "paint_active_slot", rows=2)
if not mat.use_nodes:
col.operator_menu_enum("paint.add_texture_paint_slot", "type")
row = col.row(align=True)
row.prop(settings, "slot_xresolution_default")
row.prop(settings, "slot_yresolution_default")
col.prop(settings, "slot_color_default")
if brush.image_tool == 'CLONE' and settings.use_clone_layer:
col.label("Clone Slot")
col.template_list("TEXTURE_UL_texpaintslots", "",
mat, "texture_paint_slots",
mat, "paint_clone_slot", rows=2)
class VIEW3D_PT_tools_brush_overlay(Panel, View3DPaintPanel):
bl_category = "Options"
@@ -1194,10 +1245,19 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
if brush.use_space:
col.separator()
row = col.row(align=True)
row.active = brush.use_space
row.prop(brush, "spacing", text="Spacing")
row.prop(brush, "use_pressure_spacing", toggle=True, text="")
if brush.use_line or brush.use_curve:
col.separator()
row = col.row(align=True)
row.prop(brush, "spacing", text="Spacing")
if brush.use_curve:
col.separator()
col.template_ID(brush, "paint_curve", new="paintcurve.new")
col.operator("paintcurve.draw")
if context.sculpt_object:
if brush.sculpt_capabilities.has_jitter:
col.separator()
@@ -1234,12 +1294,13 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
col = layout.column()
col.separator()
col.prop(brush, "use_smooth_stroke")
if brush.brush_capabilities.has_smooth_stroke:
col.prop(brush, "use_smooth_stroke")
sub = col.column()
sub.active = brush.use_smooth_stroke
sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
sub = col.column()
sub.active = brush.use_smooth_stroke
sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
layout.prop(settings, "input_samples")
@@ -1263,7 +1324,8 @@ class VIEW3D_PT_tools_brush_curve(Panel, View3DPaintPanel):
layout.template_curve_mapping(brush, "curve", brush=True)
row = layout.row(align=True)
col = layout.column(align=True)
row = col.row(align=True)
row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
@@ -1493,7 +1555,7 @@ class VIEW3D_PT_tools_vertexpaint(Panel, View3DPaintPanel):
col = layout.column()
row = col.row()
#col.prop(vpaint, "mode", text="")
# col.prop(vpaint, "mode", text="")
row.prop(vpaint, "use_normal")
col.prop(vpaint, "use_spray")
@@ -1531,7 +1593,7 @@ class VIEW3D_PT_tools_imagepaint_external(Panel, View3DPaintPanel):
col.operator("image.save_dirty", text="Save All Edited")
class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
class VIEW3D_PT_tools_projectpaint(View3DPaintPanel, Panel):
bl_category = "Options"
bl_context = "imagepaint"
bl_label = "Project Paint"
@@ -1551,6 +1613,7 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
settings = toolsettings.image_paint
col = layout.column()
col.prop(ipaint, "use_occlude")
col.prop(ipaint, "use_backface_culling")
@@ -1565,19 +1628,21 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
split.prop(ipaint, "use_stencil_layer", text="Stencil")
row = split.row()
row.active = (ipaint.use_stencil_layer)
col = split.column()
col.active = (ipaint.use_stencil_layer)
row = col.row()
stencil_text = mesh.uv_texture_stencil.name if mesh.uv_texture_stencil else ""
row.menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False)
row.prop(ipaint, "invert_stencil", text="", icon='IMAGE_ALPHA')
col.template_ID(ipaint, "stencil_image", new="image.new")
col.prop(ipaint, "stencil_color")
col = layout.column()
col.active = (settings.brush.image_tool == 'CLONE')
col.prop(ipaint, "use_clone_layer", text="Clone from UV map")
clone_text = mesh.uv_texture_clone.name if mesh.uv_texture_clone else ""
col.menu("VIEW3D_MT_tools_projectpaint_clone", text=clone_text, translate=False)
col.prop(ipaint, "use_clone_layer", text="Clone from paint slot")
layout.prop(ipaint, "seam_bleed")
self.unified_paint_settings(layout, context)
class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
+8 -4
View File
@@ -150,8 +150,10 @@ typedef DMDrawOption (*DMSetDrawOptions)(void *userData, int index);
typedef DMDrawOption (*DMSetDrawOptionsTex)(struct MTFace *tface, const bool has_vcol, int matnr);
typedef enum DMDrawFlag {
DM_DRAW_USE_COLORS = 1,
DM_DRAW_ALWAYS_SMOOTH = 2
DM_DRAW_USE_COLORS = (1 << 0),
DM_DRAW_ALWAYS_SMOOTH = (1 << 1),
DM_DRAW_USE_ACTIVE_UV = (1 << 2),
DM_DRAW_USE_TEXPAINT_UV = (1 << 3),
} DMDrawFlag;
typedef enum DMForeachFlag {
@@ -389,7 +391,7 @@ struct DerivedMesh {
void (*drawFacesTex)(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData);
void *userData, DMDrawFlag uvflag);
/** Draw all faces with GLSL materials
* o setMaterial is called for every different material nr
@@ -423,7 +425,7 @@ struct DerivedMesh {
void (*drawMappedFacesTex)(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData);
void *userData, DMDrawFlag uvflag);
/** Draw mapped faces with GLSL materials
* - setMaterial is called for every different material nr
@@ -593,6 +595,8 @@ void DM_ensure_tessface(DerivedMesh *dm);
void DM_update_tessface_data(DerivedMesh *dm);
void DM_update_materials(DerivedMesh *dm, struct Object *ob);
struct MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr);
/** interpolates vertex data from the vertices indexed by src_indices in the
* source mesh using the given weights and stores the result in the vertex
* indexed by dest_index in the dest mesh
+1 -1
View File
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 271
#define BLENDER_SUBVERSION 2
#define BLENDER_SUBVERSION 3
/* 262 was the last editmesh release but it has compatibility code for bmesh data */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 5
+5 -1
View File
@@ -81,7 +81,11 @@ unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side, bool
/* radial control */
struct ImBuf *BKE_brush_gen_radial_control_imbuf(struct Brush *br, bool secondary);
/* unified strength and size */
/* unified strength size and color */
float *BKE_brush_color_get(const struct Scene *scene, struct Brush *brush);
float *BKE_brush_secondary_color_get(const struct Scene *scene, struct Brush *brush);
void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3]);
int BKE_brush_size_get(const struct Scene *scene, struct Brush *brush);
void BKE_brush_size_set(struct Scene *scene, struct Brush *brush, int value);
+1 -1
View File
@@ -71,7 +71,7 @@ void id_clear_lib_data(struct Main *bmain, struct ID *id);
struct ListBase *which_libbase(struct Main *mainlib, short type);
#define MAX_LIBARRAY 41
#define MAX_LIBARRAY 43
int set_listbasepointers(struct Main *main, struct ListBase **lb);
void BKE_libblock_free(struct Main *bmain, void *idv);
+2
View File
@@ -87,6 +87,8 @@ typedef struct Main {
ListBase nodetree;
ListBase brush;
ListBase particle;
ListBase palettes;
ListBase paintcurves;
ListBase wm;
ListBase gpencil;
ListBase movieclip;
+4
View File
@@ -86,6 +86,10 @@ short find_material_index(struct Object *ob, struct Material *ma);
bool object_add_material_slot(struct Object *ob);
bool object_remove_material_slot(struct Object *ob);
void BKE_texpaint_slot_refresh_cache(struct Material *ma, bool use_nodes);
void BKE_texpaint_slots_refresh_object(struct Object *ob, bool use_nodes);
void BKE_texpaint_slots_clear(struct Material *ma);
/* rna api */
void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user);
void BKE_material_append_id(struct ID *id, struct Material *ma);
+24
View File
@@ -40,11 +40,15 @@ struct CurveMapping;
struct MDisps;
struct MeshElemMap;
struct GridPaintMask;
struct Main;
struct MFace;
struct MultireModifierData;
struct MVert;
struct Object;
struct Paint;
struct PaintCurve;
struct Palette;
struct PaletteColor;
struct PBVH;
struct Scene;
struct Sculpt;
@@ -52,6 +56,7 @@ struct StrokeCache;
struct Tex;
struct ImagePool;
struct UnifiedPaintSettings;
struct wmOperator;
enum OverlayFlags;
@@ -91,6 +96,19 @@ OverlayControlFlags BKE_paint_get_overlay_flags(void);
void BKE_paint_reset_overlay_invalid(OverlayControlFlags flag);
void BKE_paint_set_overlay_override(enum OverlayFlags flag);
/* palettes */
void BKE_palette_free(struct Palette *palette);
struct Palette *BKE_palette_add(struct Main *bmain, const char *name);
struct PaletteColor *BKE_palette_color_add(struct Palette *palette);
void BKE_palette_color_delete(struct Palette *palette);
bool BKE_palette_is_empty(const struct Palette *palette);
void BKE_palette_color_remove(struct Palette *palette, struct PaletteColor *color);
void BKE_palette_cleanup(struct Palette *palette);
/* paint curves */
struct PaintCurve *BKE_paint_curve_add(struct Main *bmain, const char *name);
void BKE_paint_curve_free(struct PaintCurve *pc);
void BKE_paint_init(struct Paint *p, const char col[3]);
void BKE_paint_free(struct Paint *p);
void BKE_paint_copy(struct Paint *src, struct Paint *tar);
@@ -100,6 +118,9 @@ struct Paint *BKE_paint_get_active_from_context(const struct bContext *C);
PaintMode BKE_paintmode_get_active_from_context(const struct bContext *C);
struct Brush *BKE_paint_brush(struct Paint *paint);
void BKE_paint_brush_set(struct Paint *paint, struct Brush *br);
struct Palette *BKE_paint_palette(struct Paint *paint);
void BKE_paint_palette_set(struct Paint *p, struct Palette *palette);
void BKE_paint_curve_set(struct Brush *br, struct PaintCurve *pc);
/* testing face select mode
* Texture paint could be removed since selected faces are not used
@@ -117,7 +138,10 @@ bool paint_is_bmesh_face_hidden(struct BMFace *f);
/* paint masks */
float paint_grid_paint_mask(const struct GridPaintMask *gpm, unsigned level,
unsigned x, unsigned y);
/* stroke related */
void paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, const float mouse_pos[2]);
/* Session data (mode-specific) */
typedef struct SculptSession {
+29 -3
View File
@@ -37,6 +37,7 @@
#include "DNA_cloth_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -501,11 +502,36 @@ void DM_update_materials(DerivedMesh *dm, Object *ob)
dm->mat = MEM_callocN(totmat * sizeof(*dm->mat), "DerivedMesh.mat");
for (i = 1; i < totmat; i++) {
dm->mat[i] = give_current_material(ob, i);
/* we leave last material as empty - rationale here is being able to index
* the materials by using the mf->mat_nr directly and leaving the last
* material as NULL in case no materials exist on mesh, so indexing will not fail */
for (i = 0; i < totmat - 1; i++) {
dm->mat[i] = give_current_material(ob, i + 1);
}
}
MTFace *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr)
{
MTFace *tf_base;
BLI_assert(mat_nr < dm->totmat);
if (dm->mat[mat_nr] && dm->mat[mat_nr]->texpaintslot &&
dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname[0])
{
tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE,
dm->mat[mat_nr]->texpaintslot[dm->mat[mat_nr]->paint_active_slot].uvname);
/* This can fail if we have changed the name in the UV layer list and have assigned the old name in the material
* texture slot.*/
if (!tf_base)
tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
}
else {
tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
}
return tf_base;
}
void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob, CustomDataMask mask)
{
@@ -3091,7 +3117,7 @@ static void navmesh_drawColored(DerivedMesh *dm)
static void navmesh_DM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData)
void *userData, DMDrawFlag UNUSED(flag))
{
(void) setDrawOptions;
(void) compareDrawOptions;
+50 -6
View File
@@ -83,6 +83,7 @@ static void brush_defaults(Brush *brush)
brush->plane_trim = 0.5f;
brush->clone.alpha = 0.5f;
brush->normal_weight = 0.0f;
brush->fill_threshold = 0.2f;
brush->flag |= BRUSH_ALPHA_PRESSURE;
/* BRUSH PAINT TOOL SETTINGS */
@@ -90,6 +91,8 @@ static void brush_defaults(Brush *brush)
brush->rgb[1] = 1.0f;
brush->rgb[2] = 1.0f;
zero_v3(brush->secondary_rgb);
/* BRUSH STROKE SETTINGS */
brush->flag |= (BRUSH_SPACE | BRUSH_SPACE_ATTEN);
brush->spacing = 10; /* how far each brush dot should be spaced as a percentage of brush diameter */
@@ -161,6 +164,9 @@ Brush *BKE_brush_copy(Brush *brush)
if (brush->mask_mtex.tex)
id_us_plus((ID *)brush->mask_mtex.tex);
if (brush->paint_curve)
id_us_plus((ID *)brush->paint_curve);
if (brush->icon_imbuf)
brushn->icon_imbuf = IMB_dupImBuf(brush->icon_imbuf);
@@ -180,11 +186,9 @@ Brush *BKE_brush_copy(Brush *brush)
/* not brush itself */
void BKE_brush_free(Brush *brush)
{
if (brush->mtex.tex)
brush->mtex.tex->id.us--;
if (brush->mask_mtex.tex)
brush->mask_mtex.tex->id.us--;
id_us_min((ID *)brush->mtex.tex);
id_us_min((ID *)brush->mask_mtex.tex);
id_us_min((ID *)brush->paint_curve);
if (brush->icon_imbuf)
IMB_freeImBuf(brush->icon_imbuf);
@@ -192,6 +196,9 @@ void BKE_brush_free(Brush *brush)
BKE_previewimg_free(&(brush->preview));
curvemapping_free(brush->curve);
if (brush->gradient)
MEM_freeN(brush->gradient);
}
static void extern_local_brush(Brush *brush)
@@ -199,6 +206,7 @@ static void extern_local_brush(Brush *brush)
id_lib_extern((ID *)brush->mtex.tex);
id_lib_extern((ID *)brush->mask_mtex.tex);
id_lib_extern((ID *)brush->clone.image);
id_lib_extern((ID *)brush->paint_curve);
}
void BKE_brush_make_local(Brush *brush)
@@ -742,10 +750,23 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
}
CLAMP(intensity, 0.0f, 1.0f);
switch (br->mask_pressure) {
case BRUSH_MASK_PRESSURE_CUTOFF:
intensity = ((1.0f - intensity) < ups->size_pressure_value) ? 1.0f : 0.0f;
break;
case BRUSH_MASK_PRESSURE_RAMP:
intensity = ups->size_pressure_value + intensity * (1.0f - ups->size_pressure_value);
break;
default:
break;
}
return intensity;
}
/* Unified Size and Strength */
/* Unified Size / Strength / Color */
/* XXX: be careful about setting size and unprojected radius
* because they depend on one another
@@ -760,6 +781,29 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
* In any case, a better solution is needed to prevent
* inconsistency. */
float *BKE_brush_color_get(const struct Scene *scene, struct Brush *brush)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->rgb : brush->rgb;
}
float *BKE_brush_secondary_color_get(const struct Scene *scene, struct Brush *brush)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
return (ups->flag & UNIFIED_PAINT_COLOR) ? ups->secondary_rgb : brush->secondary_rgb;
}
void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float color[3])
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
if (ups->flag & UNIFIED_PAINT_COLOR)
copy_v3_v3(ups->rgb, color);
else
copy_v3_v3(brush->rgb, color);
}
void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
@@ -51,6 +51,7 @@
#include "BKE_editmesh.h"
#include "BKE_curve.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -669,7 +670,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
DMSetDrawOptionsTex drawParams,
DMSetDrawOptions drawParamsMapped,
DMCompareDrawOptions compareDrawOptions,
void *userData)
void *userData, DMDrawFlag uvflag)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
MVert *mv = cddm->mvert;
@@ -680,6 +681,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
MCol *mcol;
int i, orig;
int colType, startFace = 0;
bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0;
/* double lookup */
const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
@@ -718,14 +720,35 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
cdDM_update_normals_from_pbvh(dm);
if (GPU_buffer_legacy(dm)) {
int mat_nr_cache = -1;
MTFace *tf_base = DM_get_tessface_data_layer(dm, CD_MTFACE);
MTFace *tf_stencil_base = NULL;
MTFace *tf_stencil = NULL;
if (uvflag & DM_DRAW_USE_TEXPAINT_UV) {
int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
}
DEBUG_VBO("Using legacy code. cdDM_drawFacesTex_common\n");
for (i = 0; i < dm->numTessFaceData; i++, mf++) {
MVert *mvert;
DMDrawOption draw_option;
unsigned char *cp = NULL;
if (uvflag & DM_DRAW_USE_TEXPAINT_UV) {
if (mf->mat_nr != mat_nr_cache) {
tf_base = DM_paint_uvlayer_active_get(dm, mf->mat_nr);
mat_nr_cache = mf->mat_nr;
}
}
tf = tf_base ? tf_base + i : NULL;
tf_stencil = tf_stencil_base ? tf_stencil_base + i : NULL;
if (drawParams) {
draw_option = drawParams(tf ? &tf[i] : NULL, (mcol != NULL), mf->mat_nr);
draw_option = drawParams(use_tface ? tf : NULL, (mcol != NULL), mf->mat_nr);
}
else {
if (index_mf_to_mpoly) {
@@ -778,21 +801,24 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
}
glBegin(mf->v4 ? GL_QUADS : GL_TRIANGLES);
if (tf) glTexCoord2fv(tf[i].uv[0]);
if (tf) glTexCoord2fv(tf->uv[0]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
mvert = &mv[mf->v1];
if (lnors) glNormal3sv((const GLshort *)lnors[0][0]);
else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
glVertex3fv(mvert->co);
if (tf) glTexCoord2fv(tf[i].uv[1]);
if (tf) glTexCoord2fv(tf->uv[1]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
mvert = &mv[mf->v2];
if (lnors) glNormal3sv((const GLshort *)lnors[0][1]);
else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no);
glVertex3fv(mvert->co);
if (tf) glTexCoord2fv(tf[i].uv[2]);
if (tf) glTexCoord2fv(tf->uv[2]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
mvert = &mv[mf->v3];
if (lnors) glNormal3sv((const GLshort *)lnors[0][2]);
@@ -800,7 +826,8 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
glVertex3fv(mvert->co);
if (mf->v4) {
if (tf) glTexCoord2fv(tf[i].uv[3]);
if (tf) glTexCoord2fv(tf->uv[3]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
mvert = &mv[mf->v4];
if (lnors) glNormal3sv((const GLshort *)lnors[0][3]);
@@ -819,7 +846,10 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
GPU_uv_setup(dm);
if (uvflag & DM_DRAW_USE_TEXPAINT_UV)
GPU_texpaint_uv_setup(dm);
else
GPU_uv_setup(dm);
if (mcol) {
GPU_color_setup(dm, colType);
}
@@ -839,7 +869,7 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
next_actualFace = dm->drawObject->triangle_to_mface[i + 1];
if (drawParams) {
draw_option = drawParams(tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr);
draw_option = drawParams(use_tface && tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr);
}
else {
if (index_mf_to_mpoly) {
@@ -895,9 +925,9 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
static void cdDM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData)
void *userData, DMDrawFlag uvflag)
{
cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, uvflag);
}
static void cdDM_drawMappedFaces(DerivedMesh *dm,
@@ -1123,9 +1153,9 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm,
static void cdDM_drawMappedFacesTex(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData)
void *userData, DMDrawFlag flag)
{
cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
}
static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert,
@@ -2472,6 +2472,17 @@ static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
}
if (ELEM(idtype, ID_MA, ID_TE)) {
const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(sce);
for (obt = bmain->object.first; obt; obt = obt->id.next) {
if (obt->mode & OB_MODE_TEXTURE_PAINT) {
obt->recalc |= OB_RECALC_DATA;
BKE_texpaint_slots_refresh_object(obt, new_shading_nodes);
lib_id_recalc_data_tag(bmain, &obt->id);
}
}
}
if (idtype == ID_MC) {
MovieClip *clip = (MovieClip *) id;
@@ -911,7 +911,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm,
static void emDM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData)
void *userData, DMDrawFlag UNUSED(flag))
{
emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
}
@@ -919,7 +919,7 @@ static void emDM_drawFacesTex(DerivedMesh *dm,
static void emDM_drawMappedFacesTex(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData)
void *userData, DMDrawFlag UNUSED(flag))
{
emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
}
@@ -73,6 +73,8 @@ static IDType idtypes[] = {
{ ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE },
{ ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE },
{ ID_PA, "ParticleSettings", "particles", 0 },
{ ID_PAL, "Palettes", "palettes", IDTYPE_FLAGS_ISLINKABLE },
{ ID_PC, "PaintCurve", "paint_curves", IDTYPE_FLAGS_ISLINKABLE },
{ ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE },
{ ID_SCR, "Screen", "screens", 0 },
{ ID_SEQ, "Sequence", "sequences", 0 }, /* not actually ID data */
@@ -104,6 +104,7 @@
#include "BKE_mask.h"
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_packedFile.h"
#include "BKE_speaker.h"
@@ -515,6 +516,10 @@ ListBase *which_libbase(Main *mainlib, short type)
return &(mainlib->mask);
case ID_LS:
return &(mainlib->linestyle);
case ID_PAL:
return &(mainlib->palettes);
case ID_PC:
return &(mainlib->paintcurves);
}
return NULL;
}
@@ -596,6 +601,8 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[a++] = &(main->text);
lb[a++] = &(main->sound);
lb[a++] = &(main->group);
lb[a++] = &(main->palettes);
lb[a++] = &(main->paintcurves);
lb[a++] = &(main->brush);
lb[a++] = &(main->script);
lb[a++] = &(main->particle);
@@ -731,6 +738,12 @@ static ID *alloc_libblock_notest(short type)
case ID_LS:
id = MEM_callocN(sizeof(FreestyleLineStyle), "Freestyle Line Style");
break;
case ID_PAL:
id = MEM_callocN(sizeof(Palette), "Palette");
break;
case ID_PC:
id = MEM_callocN(sizeof(PaintCurve), "Paint Curve");
break;
}
return id;
}
@@ -1007,6 +1020,12 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
case ID_LS:
BKE_linestyle_free((FreestyleLineStyle *)id);
break;
case ID_PAL:
BKE_palette_free((Palette *)id);
break;
case ID_PC:
BKE_paint_curve_free((PaintCurve *)id);
break;
}
/* avoid notifying on removed data */
+114 -1
View File
@@ -111,6 +111,9 @@ void BKE_material_free_ex(Material *ma, bool do_id_user)
MEM_freeN(ma->nodetree);
}
if (ma->texpaintslot)
MEM_freeN(ma->texpaintslot);
if (ma->gpumaterial.first)
GPU_material_free(ma);
}
@@ -269,7 +272,9 @@ Material *localize_material(Material *ma)
if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col);
if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec);
if (ma->texpaintslot) man->texpaintslot = MEM_dupallocN(man->texpaintslot);
man->preview = NULL;
if (ma->nodetree)
@@ -1301,6 +1306,114 @@ bool object_remove_material_slot(Object *ob)
return true;
}
void BKE_texpaint_slots_clear(struct Material *ma)
{
if (ma->texpaintslot) {
MEM_freeN(ma->texpaintslot);
ma->texpaintslot = NULL;
}
ma->tot_slots = 0;
ma->paint_active_slot = 0;
ma->paint_clone_slot = 0;
}
static bool get_mtex_slot_valid_texpaint(struct MTex *mtex)
{
return (mtex && (mtex->texco == TEXCO_UV) &&
mtex->tex && (mtex->tex->type == TEX_IMAGE) &&
mtex->tex->ima);
}
void BKE_texpaint_slot_refresh_cache(Material *ma, bool use_nodes)
{
MTex **mtex;
short count = 0;
short index = 0, i;
if (!ma)
return;
if (ma->texpaintslot) {
MEM_freeN(ma->texpaintslot);
ma->texpaintslot = NULL;
}
if (use_nodes) {
bNode *node, *active_node;
if (!(ma->use_nodes && ma->nodetree))
return;
for (node = ma->nodetree->nodes.first; node; node = node->next) {
if (node->typeinfo->nclass == NODE_CLASS_TEXTURE)
count++;
}
ma->tot_slots = count;
if (count == 0) {
ma->paint_active_slot = 0;
return;
}
ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
active_node = nodeGetActiveTexture(ma->nodetree);
for (node = ma->nodetree->nodes.first; node; node = node->next) {
if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
if (active_node == node)
ma->paint_active_slot = index;
ma->texpaintslot[index++].ima = (Image *)node->id;
}
}
}
else {
for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) {
if (get_mtex_slot_valid_texpaint(*mtex)) {
count++;
}
}
ma->tot_slots = count;
if (count == 0) {
ma->paint_active_slot = 0;
return;
}
ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) {
if (get_mtex_slot_valid_texpaint(*mtex)) {
ma->texpaintslot[index].ima = (*mtex)->tex->ima;
BLI_strncpy(ma->texpaintslot[index++].uvname, (*mtex)->uvname, 64);
}
}
}
if (ma->paint_active_slot >= count) {
ma->paint_active_slot = count - 1;
}
if (ma->paint_clone_slot >= count) {
ma->paint_clone_slot = count - 1;
}
return;
}
void BKE_texpaint_slots_refresh_object(struct Object *ob, bool use_nodes)
{
int i;
for (i = 1; i < ob->totcol + 1; i++) {
Material *ma = give_current_material(ob, i);
BKE_texpaint_slot_refresh_cache(ma, use_nodes);
}
}
/* r_col = current value, col = new value, (fac == 0) is no change */
void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
+103
View File
@@ -45,8 +45,10 @@
#include "BLI_bitmap.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
#include "BLI_listbase.h"
#include "BKE_brush.h"
#include "BKE_main.h"
#include "BKE_context.h"
#include "BKE_crazyspace.h"
#include "BKE_depsgraph.h"
@@ -269,6 +271,105 @@ void BKE_paint_brush_set(Paint *p, Brush *br)
}
}
void BKE_paint_curve_free(PaintCurve *pc)
{
if (pc->points) {
MEM_freeN(pc->points);
pc->points = NULL;
pc->tot_points = 0;
}
}
PaintCurve *BKE_paint_curve_add(Main *bmain, const char *name)
{
PaintCurve *pc;
pc = BKE_libblock_alloc(bmain, ID_PC, name);
return pc;
}
Palette *BKE_paint_palette(Paint *p)
{
return p ? p->palette : NULL;
}
void BKE_paint_palette_set(Paint *p, Palette *palette)
{
if (p) {
id_us_min((ID *)p->palette);
id_us_plus((ID *)palette);
p->palette = palette;
}
}
void BKE_paint_curve_set(Brush *br, PaintCurve *pc)
{
if (br) {
id_us_min((ID *)br->paint_curve);
id_us_plus((ID *)pc);
br->paint_curve = pc;
}
}
/* remove colour from palette. Must be certain color is inside the palette! */
void BKE_palette_color_remove(Palette *palette, PaletteColor *color)
{
BLI_remlink(&palette->colors, color);
BLI_addhead(&palette->deleted, color);
}
void BKE_palette_cleanup(Palette *palette)
{
BLI_freelistN(&palette->deleted);
}
Palette *BKE_palette_add(Main *bmain, const char *name)
{
Palette *palette;
palette = BKE_libblock_alloc(bmain, ID_PAL, name);
/* enable fake user by default */
palette->id.flag |= LIB_FAKEUSER;
return palette;
}
void BKE_palette_free(Palette *palette)
{
BLI_freelistN(&palette->colors);
}
PaletteColor *BKE_palette_color_add(Palette *palette)
{
PaletteColor *color = MEM_callocN(sizeof(*color), "Pallete Color");
BLI_addtail(&palette->colors, color);
palette->active_color = BLI_countlist(&palette->colors) - 1;
return color;
}
void BKE_palette_color_delete(struct Palette *palette)
{
PaletteColor *color = BLI_findlink(&palette->colors, palette->active_color);
if(color) {
if ((color == palette->colors.last) && (palette->colors.last != palette->colors.first))
palette->active_color--;
BLI_remlink(&palette->colors, color);
BLI_addhead(&palette->deleted, color);
}
}
bool BKE_palette_is_empty(const struct Palette *palette)
{
return BLI_listbase_is_empty(&palette->colors);
}
/* are we in vertex paint or weight pain face select mode? */
bool BKE_paint_select_face_test(Object *ob)
{
@@ -318,6 +419,7 @@ void BKE_paint_init(Paint *p, const char col[3])
void BKE_paint_free(Paint *paint)
{
id_us_min((ID *)paint->brush);
id_us_min((ID *)paint->palette);
}
/* called when copying scene settings, so even if 'src' and 'tar' are the same
@@ -328,6 +430,7 @@ void BKE_paint_copy(Paint *src, Paint *tar)
{
tar->brush = src->brush;
id_us_plus((ID *)tar->brush);
id_us_plus((ID *)tar->palette);
}
/* returns non-zero if any of the face's vertices
+45 -5
View File
@@ -41,6 +41,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
@@ -2291,18 +2292,23 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
DMSetDrawOptionsTex drawParams,
DMSetDrawOptions drawParamsMapped,
DMCompareDrawOptions compareDrawOptions,
void *userData)
void *userData, DMDrawFlag flag)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
CCGSubSurf *ss = ccgdm->ss;
CCGKey key;
MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
MTFace *tf_stencil_base = NULL;
MTFace *tf_stencil = NULL;
MTFace *tf_base;
short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
DMFlagMat *faceFlags = ccgdm->faceFlags;
DMDrawOption draw_option;
int i, totface, gridSize = ccgSubSurf_getGridSize(ss);
int gridFaces = gridSize - 1;
int gridOffset = 0;
int mat_nr_cache = -1;
(void) compareDrawOptions;
@@ -2316,6 +2322,12 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
mcol = dm->getTessFaceDataArray(dm, CD_TEXTURE_MCOL);
totface = ccgSubSurf_getNumFaces(ss);
if (flag & DM_DRAW_USE_TEXPAINT_UV) {
int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
}
for (i = 0; i < totface; i++) {
CCGFace *f = ccgdm->faceMap[i].face;
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
@@ -2334,6 +2346,18 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
mat_nr = 0;
}
/* texture painting, handle the correct uv layer here */
if (flag & DM_DRAW_USE_TEXPAINT_UV) {
if (mat_nr != mat_nr_cache) {
tf_base = DM_paint_uvlayer_active_get(dm, mat_nr);
mat_nr_cache = mat_nr;
}
tf = tf_base + gridOffset;
tf_stencil = tf_stencil_base + gridOffset;
gridOffset += gridFaces * gridFaces * numVerts;
}
if (drawParams)
draw_option = drawParams(tf, (mcol != NULL), mat_nr);
else if (index != ORIGINDEX_NONE)
@@ -2374,26 +2398,31 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
float *d_co = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
if (tf) glTexCoord2fv(tf->uv[1]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
glNormal3sv(ln[0][1]);
glVertex3fv(d_co);
if (tf) glTexCoord2fv(tf->uv[2]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
glNormal3sv(ln[0][2]);
glVertex3fv(c_co);
if (tf) glTexCoord2fv(tf->uv[3]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
glNormal3sv(ln[0][3]);
glVertex3fv(b_co);
if (tf) glTexCoord2fv(tf->uv[0]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
glNormal3sv(ln[0][0]);
glVertex3fv(a_co);
if (tf) tf++;
if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
ln++;
}
@@ -2409,17 +2438,20 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
if (tf) glTexCoord2fv(tf->uv[0]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
glNormal3fv(CCG_elem_no(&key, a));
glVertex3fv(CCG_elem_co(&key, a));
if (tf) glTexCoord2fv(tf->uv[1]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
glNormal3fv(CCG_elem_no(&key, b));
glVertex3fv(CCG_elem_co(&key, b));
if (x != gridFaces - 1) {
if (tf) tf++;
if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
}
}
@@ -2428,16 +2460,19 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
b = CCG_grid_elem(&key, faceGridData, x, y + 1);
if (tf) glTexCoord2fv(tf->uv[3]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
glNormal3fv(CCG_elem_no(&key, a));
glVertex3fv(CCG_elem_co(&key, a));
if (tf) glTexCoord2fv(tf->uv[2]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
glNormal3fv(CCG_elem_no(&key, b));
glVertex3fv(CCG_elem_co(&key, b));
if (tf) tf++;
if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
glEnd();
@@ -2456,22 +2491,27 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
ccgDM_glNormalFast(a_co, b_co, c_co, d_co);
if (tf) glTexCoord2fv(tf->uv[1]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[1]);
if (cp) glColor3ub(cp[7], cp[6], cp[5]);
glVertex3fv(d_co);
if (tf) glTexCoord2fv(tf->uv[2]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[2]);
if (cp) glColor3ub(cp[11], cp[10], cp[9]);
glVertex3fv(c_co);
if (tf) glTexCoord2fv(tf->uv[3]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[3]);
if (cp) glColor3ub(cp[15], cp[14], cp[13]);
glVertex3fv(b_co);
if (tf) glTexCoord2fv(tf->uv[0]);
if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE1, tf_stencil->uv[0]);
if (cp) glColor3ub(cp[3], cp[2], cp[1]);
glVertex3fv(a_co);
if (tf) tf++;
if (tf_stencil) tf_stencil++;
if (cp) cp += 16;
}
}
@@ -2484,17 +2524,17 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
static void ccgDM_drawFacesTex(DerivedMesh *dm,
DMSetDrawOptionsTex setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData)
void *userData, DMDrawFlag flag)
{
ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, flag);
}
static void ccgDM_drawMappedFacesTex(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMCompareDrawOptions compareDrawOptions,
void *userData)
void *userData, DMDrawFlag flag)
{
ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
}
static void ccgDM_drawUVEdges(DerivedMesh *dm)
+3 -2
View File
@@ -474,7 +474,8 @@ void BKE_texture_free(Tex *tex)
void default_tex(Tex *tex)
{
tex->type = TEX_CLOUDS;
tex->type = TEX_IMAGE;
tex->ima = NULL;
tex->stype = 0;
tex->flag = TEX_CHECKER_ODD;
tex->imaflag = TEX_INTERPOL | TEX_MIPMAP | TEX_USEALPHA;
@@ -592,7 +593,7 @@ Tex *add_texture(Main *bmain, const char *name)
void default_mtex(MTex *mtex)
{
mtex->texco = TEXCO_ORCO;
mtex->texco = TEXCO_UV;
mtex->mapto = MAP_COL;
mtex->object = NULL;
mtex->projx = PROJ_X;
@@ -49,6 +49,24 @@ MINLINE void blend_color_lighten_byte(unsigned char dst[4], const unsigned char
MINLINE void blend_color_darken_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]);
MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]);
MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4]);
MINLINE void blend_color_overlay_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_hardlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_burn_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_linearburn_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_dodge_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_screen_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_softlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_pinlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_linearlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_vividlight_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_difference_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_exclusion_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_color_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_hue_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_saturation_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_luminosity_byte(unsigned char dst[4], unsigned const char src1[4], unsigned const char src2[4]);
MINLINE void blend_color_interpolate_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4], float t);
MINLINE void blend_color_mix_float(float dst[4], const float src1[4], const float src2[4]);
@@ -59,6 +77,24 @@ MINLINE void blend_color_lighten_float(float dst[4], const float src1[4], const
MINLINE void blend_color_darken_float(float dst[4], const float src1[4], const float src2[4]);
MINLINE void blend_color_erase_alpha_float(float dst[4], const float src1[4], const float src2[4]);
MINLINE void blend_color_add_alpha_float(float dst[4], const float src1[4], const float src2[4]);
MINLINE void blend_color_overlay_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_burn_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_linearburn_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_dodge_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_screen_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_softlight_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_pinlight_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_linearlight_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_vividlight_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_difference_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_exclusion_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_color_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_hue_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_saturation_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_luminosity_float(float dst[4], const float src1[4], const float src2[2]);
MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], const float src2[4], float t);
#if BLI_MATH_DO_INLINE
+2
View File
@@ -65,6 +65,7 @@ MINLINE void swap_v4_v4(float a[4], float b[4]);
MINLINE void copy_v2_v2_char(char r[2], const char a[2]);
MINLINE void copy_v3_v3_char(char r[3], const char a[3]);
MINLINE void copy_v4_v4_char(char r[4], const char a[4]);
/* short */
MINLINE void copy_v2_v2_short(short r[2], const short a[2]);
MINLINE void copy_v3_v3_short(short r[3], const short a[3]);
@@ -231,6 +232,7 @@ MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_R
MINLINE bool compare_v2v2(const float a[2], const float b[2], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool compare_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool compare_len_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool compare_len_squared_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool compare_v4v4(const float a[4], const float b[4], const float limit) ATTR_WARN_UNUSED_RESULT;
MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT;
File diff suppressed because it is too large Load Diff
+58 -1
View File
@@ -1824,6 +1824,7 @@ static void lib_link_brush(FileData *fd, Main *main)
brush->mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mtex.tex);
brush->mask_mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mask_mtex.tex);
brush->clone.image = newlibadr_us(fd, brush->id.lib, brush->clone.image);
brush->paint_curve = newlibadr_us(fd, brush->id.lib, brush->paint_curve);
}
}
}
@@ -1834,6 +1835,8 @@ static void direct_link_brush(FileData *fd, Brush *brush)
/* fallof curve */
brush->curve = newdataadr(fd, brush->curve);
brush->gradient = newdataadr(fd, brush->gradient);
if (brush->curve)
direct_link_curvemapping(fd, brush->curve);
else
@@ -1843,6 +1846,43 @@ static void direct_link_brush(FileData *fd, Brush *brush)
brush->icon_imbuf = NULL;
}
/* ************ READ Palette *************** */
static void lib_link_palette(FileData *UNUSED(fd), Main *main)
{
Palette *palette;
/* only link ID pointers */
for (palette = main->palettes.first; palette; palette = palette->id.next) {
if (palette->id.flag & LIB_NEED_LINK) {
palette->id.flag -= LIB_NEED_LINK;
}
}
}
static void direct_link_palette(FileData *fd, Palette *palette)
{
/* palette itself has been read */
link_list(fd, &palette->colors);
}
static void lib_link_paint_curve(FileData *UNUSED(fd), Main *main)
{
PaintCurve *pc;
/* only link ID pointers */
for (pc = main->paintcurves.first; pc; pc = pc->id.next) {
if (pc->id.flag & LIB_NEED_LINK) {
pc->id.flag -= LIB_NEED_LINK;
}
}
}
static void direct_link_paint_curve(FileData *fd, PaintCurve *pc)
{
pc->points = newdataadr(fd, pc->points);
}
static void direct_link_script(FileData *UNUSED(fd), Script *script)
{
script->id.us = 1;
@@ -3516,7 +3556,8 @@ static void direct_link_material(FileData *fd, Material *ma)
for (a = 0; a < MAX_MTEX; a++) {
ma->mtex[a] = newdataadr(fd, ma->mtex[a]);
}
ma->texpaintslot = NULL;
ma->ramp_col = newdataadr(fd, ma->ramp_col);
ma->ramp_spec = newdataadr(fd, ma->ramp_spec);
@@ -5059,6 +5100,7 @@ static void link_paint(FileData *fd, Scene *sce, Paint *p)
{
if (p) {
p->brush = newlibadr_us(fd, sce->id.lib, p->brush);
p->palette = newlibadr_us(fd, sce->id.lib, p->palette);
p->paint_cursor = NULL;
}
}
@@ -5107,6 +5149,10 @@ static void lib_link_scene(FileData *fd, Main *main)
sce->toolsettings->sculpt->gravity_object =
newlibadr_us(fd, sce->id.lib, sce->toolsettings->sculpt->gravity_object);
if (sce->toolsettings->imapaint.stencil)
sce->toolsettings->imapaint.stencil =
newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.stencil);
sce->toolsettings->skgen_template = newlibadr(fd, sce->id.lib, sce->toolsettings->skgen_template);
for (base = sce->base.first; base; base = next) {
@@ -7138,6 +7184,8 @@ static const char *dataname(short id_code)
case ID_NT: return "Data from NT";
case ID_BR: return "Data from BR";
case ID_PA: return "Data from PA";
case ID_PAL: return "Data from PAL";
case ID_PC: return "Data from PCRV";
case ID_GD: return "Data from GD";
case ID_WM: return "Data from WM";
case ID_MC: return "Data from MC";
@@ -7323,6 +7371,12 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
case ID_LS:
direct_link_linestyle(fd, (FreestyleLineStyle *)id);
break;
case ID_PAL:
direct_link_palette(fd, (Palette *)id);
break;
case ID_PC:
direct_link_paint_curve(fd, (PaintCurve *)id);
break;
}
oldnewmap_free_unused(fd->datamap);
@@ -7511,6 +7565,8 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_vfont(fd, main);
lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */
lib_link_brush(fd, main);
lib_link_palette(fd, main);
lib_link_paint_curve(fd, main);
lib_link_particlesettings(fd, main);
lib_link_movieclip(fd, main);
lib_link_mask(fd, main);
@@ -8050,6 +8106,7 @@ static void expand_brush(FileData *fd, Main *mainvar, Brush *brush)
expand_doit(fd, mainvar, brush->mtex.tex);
expand_doit(fd, mainvar, brush->mask_mtex.tex);
expand_doit(fd, mainvar, brush->clone.image);
expand_doit(fd, mainvar, brush->paint_curve);
}
static void expand_material(FileData *fd, Main *mainvar, Material *ma)
@@ -34,6 +34,7 @@
/* allow readfile to use deprecated functionality */
#define DNA_DEPRECATED_ALLOW
#include "DNA_brush_types.h"
#include "DNA_constraint_types.h"
#include "DNA_sdna_types.h"
#include "DNA_space_types.h"
@@ -309,6 +310,13 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
mat->line_col[3] = mat->alpha;
}
}
if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "int", "preview_start_resolution")) {
Scene *scene;
for (scene = main->scene.first; scene; scene = scene->id.next) {
scene->r.preview_start_resolution = 64;
}
}
}
if (!MAIN_VERSION_ATLEAST(main, 271, 2)) {
@@ -334,6 +342,20 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
if (!MAIN_VERSION_ATLEAST(main, 271, 3)) {
Scene *sce;
Brush *br;
for (sce = main->scene.first; sce; sce = sce->id.next) {
sce->toolsettings->imapaint.slot_xresolution_default = 1024;
sce->toolsettings->imapaint.slot_yresolution_default = 1024;
}
for (br = main->brush.first; br; br = br->id.next) {
br->fill_threshold = 0.2f;
}
}
if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "int", "preview_start_resolution")) {
Scene *scene;
for (scene = main->scene.first; scene; scene = scene->id.next) {
@@ -2924,6 +2924,38 @@ static void write_brushes(WriteData *wd, ListBase *idbase)
if (brush->curve)
write_curvemapping(wd, brush->curve);
if (brush->curve)
writestruct(wd, DATA, "ColorBand", 1, brush->gradient);
}
}
}
static void write_palettes(WriteData *wd, ListBase *idbase)
{
Palette *palette;
for (palette = idbase->first; palette; palette = palette->id.next) {
if (palette->id.us > 0 || wd->current) {
PaletteColor *color;
writestruct(wd, ID_PAL, "Palette", 1, palette);
if (palette->id.properties) IDP_WriteProperty(palette->id.properties, wd);
for (color = palette->colors.first; color; color= color->next)
writestruct(wd, DATA, "PaletteColor", 1, color);
}
}
}
static void write_paintcurves(WriteData *wd, ListBase *idbase)
{
PaintCurve *pc;
for (pc = idbase->first; pc; pc = pc->id.next) {
if (pc->id.us > 0 || wd->current) {
writestruct(wd, ID_PC, "PaintCurve", 1, pc);
writestruct(wd, DATA, "PaintCurvePoint", pc->tot_points, pc->points);
if (pc->id.properties) IDP_WriteProperty(pc->id.properties, wd);
}
}
}
@@ -3399,6 +3431,8 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
write_particlesettings(wd, &mainvar->particle);
write_nodetrees(wd, &mainvar->nodetree);
write_brushes (wd, &mainvar->brush);
write_palettes (wd, &mainvar->palettes);
write_paintcurves (wd, &mainvar->paintcurves);
write_scripts (wd, &mainvar->script);
write_gpencils (wd, &mainvar->gpencil);
write_linestyles(wd, &mainvar->linestyle);
@@ -93,6 +93,8 @@ if(WITH_BLENDER)
data_to_c_simple(../../../../release/datafiles/brushicons/soften.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/subtract.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/texdraw.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/texfill.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/texmask.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/thumb.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/vertexdraw.png SRC)
@@ -77,6 +77,8 @@ sources.extend((
os.path.join(env['DATA_SOURCES'], "soften.png.c"),
os.path.join(env['DATA_SOURCES'], "subtract.png.c"),
os.path.join(env['DATA_SOURCES'], "texdraw.png.c"),
os.path.join(env['DATA_SOURCES'], "texfill.png.c"),
os.path.join(env['DATA_SOURCES'], "texmask.png.c"),
os.path.join(env['DATA_SOURCES'], "thumb.png.c"),
os.path.join(env['DATA_SOURCES'], "twist.png.c"),
os.path.join(env['DATA_SOURCES'], "vertexdraw.png.c"),
@@ -150,6 +150,12 @@ extern char datatoc_subtract_png[];
extern int datatoc_texdraw_png_size;
extern char datatoc_texdraw_png[];
extern int datatoc_texfill_png_size;
extern char datatoc_texfill_png[];
extern int datatoc_texmask_png_size;
extern char datatoc_texmask_png[];
extern int datatoc_thumb_png_size;
extern char datatoc_thumb_png[];
@@ -69,8 +69,11 @@ void ED_image_point_pos__reverse(struct SpaceImage *sima, struct ARegion *ar, co
bool ED_space_image_show_render(struct SpaceImage *sima);
bool ED_space_image_show_paint(struct SpaceImage *sima);
bool ED_space_image_show_uvedit(struct SpaceImage *sima, struct Object *obedit);
bool ED_space_image_show_texpaint(struct SpaceImage *sima, struct Object *ob);
bool ED_space_image_show_uvshadow(struct SpaceImage *sima, struct Object *obedit);
bool ED_space_image_paint_curve(const struct bContext *C);
bool ED_space_image_check_show_maskedit(struct Scene *scene, struct SpaceImage *sima);
int ED_space_image_maskedit_poll(struct bContext *C);
int ED_space_image_maskedit_mask_poll(struct bContext *C);
+5 -1
View File
@@ -28,9 +28,11 @@
struct bContext;
struct RegionView3D;
struct wmKeyConfig;
struct wmOperator;
/* paint_ops.c */
void ED_operatortypes_paint(void);
void ED_operatormacros_paint(void);
void ED_keymap_paint(struct wmKeyConfig *keyconf);
/* paint_undo.c */
@@ -41,6 +43,7 @@ enum {
typedef void (*UndoRestoreCb)(struct bContext *C, struct ListBase *lb);
typedef void (*UndoFreeCb)(struct ListBase *lb);
typedef bool (*UndoCleanupCb)(struct bContext *C, struct ListBase *lb);
int ED_undo_paint_step(struct bContext *C, int type, int step, const char *name);
void ED_undo_paint_step_num(struct bContext *C, int type, int num);
@@ -48,7 +51,7 @@ const char *ED_undo_paint_get_name(struct bContext *C, int type, int nr, int *ac
void ED_undo_paint_free(void);
int ED_undo_paint_valid(int type, const char *name);
bool ED_undo_paint_empty(int type);
void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free);
void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup);
void ED_undo_paint_push_end(int type);
/* paint_image.c */
@@ -57,5 +60,6 @@ void ED_image_undo_restore(struct bContext *C, struct ListBase *lb);
void ED_image_undo_free(struct ListBase *lb);
void ED_imapaint_clear_partial_redraw(void);
void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h);
void ED_imapaint_bucket_fill(struct bContext *C, float color[3], struct wmOperator *op);
#endif /* __ED_PAINT_H__ */
@@ -98,6 +98,7 @@ enum TfmMode {
#define CTX_NDOF (1 << 5)
#define CTX_MOVIECLIP (1 << 6)
#define CTX_MASK (1 << 7)
#define CTX_PAINT_CURVE (1 << 8)
/* Standalone call to get the transformation center corresponding to the current situation
* returns 1 if successful, 0 otherwise (usually means there's no selection)
@@ -84,6 +84,7 @@ typedef struct ViewDepths {
float *ED_view3d_cursor3d_get(struct Scene *scene, struct View3D *v3d);
void ED_view3d_cursor3d_position(struct bContext *C, float fp[3], const int mval[2]);
void ED_view3d_cursor3d_update(struct bContext *C, const int mval[2]);
struct Camera *ED_view3d_camera_data_get(struct View3D *v3d, struct RegionView3D *rv3d);
@@ -976,6 +976,8 @@ DEF_ICON(BRUSH_SNAKE_HOOK)
DEF_ICON(BRUSH_SOFTEN)
DEF_ICON(BRUSH_SUBTRACT)
DEF_ICON(BRUSH_TEXDRAW)
DEF_ICON(BRUSH_TEXFILL)
DEF_ICON(BRUSH_TEXMASK)
DEF_ICON(BRUSH_THUMB)
DEF_ICON(BRUSH_ROTATE)
DEF_ICON(BRUSH_VERTEXDRAW)
@@ -75,6 +75,9 @@ struct ImBuf;
struct bNodeTree;
struct bNode;
struct bNodeSocket;
struct wmDropBox;
struct wmDrag;
struct wmEvent;
typedef struct uiBut uiBut;
typedef struct uiBlock uiBlock;
@@ -288,6 +291,9 @@ typedef enum {
#define UI_GRAD_V_ALT 9
#define UI_GRAD_L_ALT 10
#define UI_PALETTE_COLOR 20
#define UI_PALETTE_COLOR_ACTIVE 1
/* Drawing
*
* Functions to draw various shapes, taking theme settings into account.
@@ -437,6 +443,7 @@ void uiButSetDragValue(uiBut *but);
void uiButSetDragImage(uiBut *but, const char *path, int icon, struct ImBuf *ima, float scale);
bool UI_but_active_drop_name(struct bContext *C);
bool UI_but_active_drop_color(struct bContext *C);
void uiButSetFlag(uiBut *but, int flag);
void uiButClearFlag(uiBut *but, int flag);
@@ -847,6 +854,7 @@ void uiTemplateVectorscope(uiLayout *layout, struct PointerRNA *ptr, const char
void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int type,
int levels, int brush, int neg_slope);
void uiTemplateColorPicker(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic);
void uiTemplatePalette(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int color);
void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
PointerRNA *used_ptr, const char *used_propname, int active_layer);
void uiTemplateGameStates(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
@@ -916,7 +924,14 @@ void uiItemMenuEnumO(uiLayout *layout, struct bContext *C, const char *opname, c
void uiItemMenuEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name, int icon);
/* UI Operators */
typedef struct uiDragColorHandle {
float color[3];
bool gamma_corrected;
} uiDragColorHandle;
void UI_buttons_operatortypes(void);
void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop);
int UI_drop_color_poll(struct bContext *C, struct wmDrag *drag, const struct wmEvent *event);
/* Helpers for Operators */
uiBut *uiContextActiveButton(const struct bContext *C);
@@ -237,6 +237,9 @@ enum {
TH_STITCH_PREVIEW_UNSTITCHABLE,
TH_STITCH_PREVIEW_ACTIVE,
TH_PAINT_CURVE_HANDLE,
TH_PAINT_CURVE_PIVOT,
TH_UV_SHADOW,
TH_UV_OTHERS,
@@ -38,6 +38,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_brush_types.h"
#include "DNA_sensor_types.h"
#include "DNA_controller_types.h"
#include "DNA_actuator_types.h"
@@ -60,6 +61,7 @@
#include "PIL_time.h"
#include "BKE_blender.h"
#include "BKE_brush.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_idprop.h"
@@ -1189,7 +1191,7 @@ static bool ui_but_mouse_inside_icon(uiBut *but, ARegion *ar, const wmEvent *eve
BLI_rcti_rctf_copy(&rect, &but->rect);
if (but->imb) {
if (but->imb || but->type == COLOR) {
/* use button size itself */
}
else if (but->drawflag & UI_BUT_ICON_LEFT) {
@@ -1242,10 +1244,42 @@ static bool ui_but_start_drag(bContext *C, uiBut *but, uiHandleButtonData *data,
}
else
#endif
{
if (but->type == COLOR) {
bool valid = false;
uiDragColorHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__);
/* TODO support more button pointer types */
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
RNA_property_float_get_array(&but->rnapoin, but->rnaprop, drag_info->color);
drag_info->gamma_corrected = true;
valid = true;
}
else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
RNA_property_float_get_array(&but->rnapoin, but->rnaprop, drag_info->color);
drag_info->gamma_corrected = false;
valid = true;
}
else if (but->pointype == UI_BUT_POIN_FLOAT) {
copy_v3_v3(drag_info->color, (float *)but->poin);
valid = true;
}
else if (but->pointype == UI_BUT_POIN_CHAR) {
rgba_uchar_to_float(drag_info->color, (unsigned char *)but->poin);
valid = true;
}
if (valid) {
WM_event_start_drag(C, ICON_COLOR, WM_DRAG_COLOR, drag_info, 0.0, WM_DRAG_FREE_DATA);
}
else {
MEM_freeN(drag_info);
return false;
}
}
else {
wmDrag *drag;
drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but));
drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_get_but_val(but), WM_DRAG_NOP);
if (but->imb)
WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect));
}
@@ -4053,7 +4087,7 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
}
#ifdef USE_DRAG_TOGGLE
if (event->type == LEFTMOUSE && ui_is_but_drag_toggle(but)) {
if (event->type == LEFTMOUSE && event->val == KM_PRESS && (ui_is_but_drag_toggle(but))) {
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->x;
data->dragstarty = event->y;
@@ -4206,6 +4240,24 @@ static bool ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data,
static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
/* first handle click on icondrag type button */
if (event->type == LEFTMOUSE && but->dragpoin && event->val == KM_PRESS) {
if (ui_but_mouse_inside_icon(but, data->region, event)) {
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->x;
data->dragstarty = event->y;
return WM_UI_HANDLER_BREAK;
}
}
#ifdef USE_DRAG_TOGGLE
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
data->dragstartx = event->x;
data->dragstarty = event->y;
return WM_UI_HANDLER_BREAK;
}
#endif
/* regular open menu */
if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
return WM_UI_HANDLER_BREAK;
@@ -4233,6 +4285,81 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
ui_apply_button(C, but->block, but, data, true);
return WM_UI_HANDLER_BREAK;
}
else if ((int)(but->a1) == UI_PALETTE_COLOR &&
event->type == DELKEY && event->val == KM_PRESS)
{
Scene *scene = CTX_data_scene(C);
Paint *paint = BKE_paint_get_active(scene);
Palette *palette = BKE_paint_palette(paint);
PaletteColor *color = but->rnapoin.data;
BKE_palette_color_remove(palette, color);
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_BREAK;
}
}
else if (data->state == BUTTON_STATE_WAIT_DRAG) {
/* this function also ends state */
if (ui_but_start_drag(C, but, data, event)) {
return WM_UI_HANDLER_BREAK;
}
/* outside icon quit, not needed if drag activated */
if (0 == ui_but_mouse_inside_icon(but, data->region, event)) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
data->cancel = true;
return WM_UI_HANDLER_BREAK;
}
if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
if ((int)(but->a1) == UI_PALETTE_COLOR) {
Palette *palette = but->rnapoin.id.data;
PaletteColor *color = but->rnapoin.data;
palette->active_color = BLI_findindex(&palette->colors, color);
if( !event->ctrl) {
float color[3];
Scene *scene = CTX_data_scene(C);
Paint *paint = BKE_paint_get_active(scene);
Brush *brush = BKE_paint_brush(paint);
if (brush->flag & BRUSH_USE_GRADIENT) {
float *target = &brush->gradient->data[brush->gradient->cur].r;
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
RNA_property_float_get_array(&but->rnapoin, but->rnaprop, target);
ui_block_to_scene_linear_v3(but->block, target);
}
else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
RNA_property_float_get_array(&but->rnapoin, but->rnaprop, target);
}
}
else {
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
RNA_property_float_get_array(&but->rnapoin, but->rnaprop, color);
BKE_brush_color_set(scene, brush, color);
}
else if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
RNA_property_float_get_array(&but->rnapoin, but->rnaprop, color);
ui_block_to_display_space_v3(but->block, color);
BKE_brush_color_set(scene, brush, color);
}
}
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
else {
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
}
}
else {
button_activate_state(C, but, BUTTON_STATE_MENU_OPEN);
}
return WM_UI_HANDLER_BREAK;
}
}
return WM_UI_HANDLER_CONTINUE;
@@ -6250,7 +6377,7 @@ static bool ui_but_contains_pt(uiBut *but, float mx, float my)
return BLI_rctf_isect_pt(&but->rect, mx, my);
}
static uiBut *ui_but_find_activated(ARegion *ar)
uiBut *ui_but_find_activated(ARegion *ar)
{
uiBlock *block;
uiBut *but;
@@ -6305,6 +6432,17 @@ bool UI_but_active_drop_name(bContext *C)
return 0;
}
bool UI_but_active_drop_color(bContext *C)
{
ARegion *ar = CTX_wm_region(C);
uiBut *but = ui_but_find_activated(ar);
if (but && but->type == COLOR)
return true;
return false;
}
static void ui_blocks_set_tooltips(ARegion *ar, const bool enable)
{
uiBlock *block;
@@ -508,6 +508,8 @@ static void init_brush_icons(void)
INIT_BRUSH_ICON(ICON_BRUSH_SOFTEN, soften);
INIT_BRUSH_ICON(ICON_BRUSH_SUBTRACT, subtract);
INIT_BRUSH_ICON(ICON_BRUSH_TEXDRAW, texdraw);
INIT_BRUSH_ICON(ICON_BRUSH_TEXFILL, texfill);
INIT_BRUSH_ICON(ICON_BRUSH_TEXMASK, texmask);
INIT_BRUSH_ICON(ICON_BRUSH_THUMB, thumb);
INIT_BRUSH_ICON(ICON_BRUSH_ROTATE, twist);
INIT_BRUSH_ICON(ICON_BRUSH_VERTEXDRAW, vertexdraw);
@@ -186,6 +186,7 @@ struct uiBut {
* (type == LABEL), Use (a1 == 1.0f) to use a2 as a blending factor (wow, this is imaginative!).
* (type == SCROLL) Use as scroll size.
* (type == SEARCH_MENU) Use as number or rows.
* (type == COLOR) Use as indication of color palette
*/
float a1;
@@ -193,6 +194,7 @@ struct uiBut {
* (type == NUM), Use to store RNA 'precision' value, for dragging and click-step.
* (type == LABEL), If (a1 == 1.0f) use a2 as a blending factor.
* (type == SEARCH_MENU) Use as number or columns.
* (type == COLOR) Use as indication of active palette color
*/
float a2;
@@ -556,6 +558,8 @@ extern void ui_button_active_free(const struct bContext *C, uiBut *but);
extern bool ui_button_is_active(struct ARegion *ar) ATTR_WARN_UNUSED_RESULT;
extern int ui_button_open_menu_direction(uiBut *but);
extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, const bool restore);
extern uiBut *ui_but_find_activated(struct ARegion *ar);
void ui_button_clipboard_free(void);
void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa);
uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new);
@@ -35,6 +35,7 @@
#include "DNA_text_types.h" /* for UI_OT_reports_to_text */
#include "BLI_blenlib.h"
#include "BLI_math_color.h"
#include "BLF_api.h"
#include "BLF_translation.h"
@@ -44,6 +45,7 @@
#include "BKE_global.h"
#include "BKE_text.h" /* for UI_OT_reports_to_text */
#include "BKE_report.h"
#include "BKE_paint.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -55,6 +57,8 @@
#include "WM_api.h"
#include "WM_types.h"
#include "ED_paint.h"
/* only for UI_OT_editsource */
#include "ED_screen.h"
#include "BKE_main.h"
@@ -810,6 +814,91 @@ static void UI_OT_reloadtranslation(wmOperatorType *ot)
ot->exec = reloadtranslation_exec;
}
int UI_drop_color_poll(struct bContext *C, wmDrag *drag, const wmEvent *UNUSED(event))
{
/* should only return true for regions that include buttons, for now
* return true always */
if (drag->type == WM_DRAG_COLOR) {
SpaceImage *sima = CTX_wm_space_image(C);
ARegion *ar = CTX_wm_region(C);
if (UI_but_active_drop_color(C))
return 1;
if (sima && (sima->mode == SI_MODE_PAINT) &&
sima->image && (ar && ar->regiontype == RGN_TYPE_WINDOW))
{
return 1;
}
}
return 0;
}
void UI_drop_color_copy(wmDrag *drag, wmDropBox *drop)
{
uiDragColorHandle *drag_info = (uiDragColorHandle *)drag->poin;
RNA_float_set_array(drop->ptr, "color", drag_info->color);
RNA_boolean_set(drop->ptr, "gamma", drag_info->gamma_corrected);
}
static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
ARegion *ar = CTX_wm_region(C);
uiBut *but = NULL;
float color[3];
bool gamma;
RNA_float_get_array(op->ptr, "color", color);
gamma = RNA_boolean_get(op->ptr, "gamma");
/* find button under mouse, check if it has RNA color property and
* if it does copy the data */
but = ui_but_find_activated(ar);
if (but && but->type == COLOR && but->rnaprop) {
if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
if (!gamma)
ui_block_to_display_space_v3(but->block, color);
RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
RNA_property_update(C, &but->rnapoin, but->rnaprop);
}
else if (RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
if (gamma)
ui_block_to_scene_linear_v3(but->block, color);
RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
RNA_property_update(C, &but->rnapoin, but->rnaprop);
}
}
else {
if (gamma) {
srgb_to_linearrgb_v3_v3(color, color);
}
ED_imapaint_bucket_fill(C, color, op);
}
ED_region_tag_redraw(ar);
return OPERATOR_FINISHED;
}
static void UI_OT_drop_color(wmOperatorType *ot)
{
ot->name = "Drop Color";
ot->idname = "UI_OT_drop_color";
ot->description = "Drop colors to buttons";
ot->invoke = drop_color_invoke;
RNA_def_float_color(ot->srna, "color", 3, NULL, 0.0, FLT_MAX, "Color", "Source color", 0.0, 1.0);
RNA_def_boolean(ot->srna, "gamma", 0, "Gamma Corrected", "The source color is gamma corrected ");
}
/* ********************************************************* */
/* Registration */
@@ -821,7 +910,7 @@ void UI_buttons_operatortypes(void)
WM_operatortype_append(UI_OT_unset_property_button);
WM_operatortype_append(UI_OT_copy_to_selected_button);
WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */
WM_operatortype_append(UI_OT_drop_color);
#ifdef WITH_PYTHON
WM_operatortype_append(UI_OT_editsource);
WM_operatortype_append(UI_OT_edittranslation_init);
@@ -36,6 +36,7 @@
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_brush_types.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
@@ -60,6 +61,7 @@
#include "BKE_object.h"
#include "BKE_packedFile.h"
#include "BKE_particle.h"
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_sca.h"
#include "BKE_screen.h"
@@ -349,6 +351,8 @@ static const char *template_id_browse_tip(StructRNA *type)
case ID_BR: return N_("Browse Brush to be linked");
case ID_PA: return N_("Browse Particle Settings to be linked");
case ID_GD: return N_("Browse Grease Pencil Data to be linked");
case ID_PAL: return N_("Browse Palette Data to be linked");
case ID_PC: return N_("Browse Paint Curve Data to be linked");
}
}
return N_("Browse ID data to be linked");
@@ -2363,6 +2367,61 @@ void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propna
}
}
void uiTemplatePalette(uiLayout *layout, PointerRNA *ptr, const char *propname, int UNUSED(colors))
{
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
PointerRNA cptr;
Palette *palette;
PaletteColor *color;
uiBlock *block;
uiLayout *col;
int row_cols = 0, col_id = 0;
int cols_per_row = MAX2(uiLayoutGetWidth(layout) / UI_UNIT_X, 1);
if (!prop) {
RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
return;
}
cptr = RNA_property_pointer_get(ptr, prop);
if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Palette))
return;
block = uiLayoutGetBlock(layout);
palette = cptr.data;
/* first delete any pending colors */
BKE_palette_cleanup(palette);
color = palette->colors.first;
col = uiLayoutColumn(layout, true);
uiLayoutRow(col, true);
uiDefIconButO(block, BUT, "PALETTE_OT_color_add", WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
uiDefIconButO(block, BUT, "PALETTE_OT_color_delete", WM_OP_INVOKE_DEFAULT, ICON_ZOOMOUT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
col = uiLayoutColumn(layout, true);
uiLayoutRow(col, true);
for (; color; color = color->next) {
PointerRNA ptr;
if (row_cols >= cols_per_row) {
uiLayoutRow(col, true);
row_cols = 0;
}
RNA_pointer_create(&palette->id, &RNA_PaletteColor, color, &ptr);
uiDefButR(block, COLOR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, &ptr, "color", -1, 0.0, 1.0,
UI_PALETTE_COLOR, (col_id == palette->active_color) ? UI_PALETTE_COLOR_ACTIVE : 0.0, "");
row_cols++;
col_id++;
}
}
/********************* Layer Buttons Template ************************/
static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
@@ -33,6 +33,7 @@
#include <string.h>
#include <assert.h>
#include "DNA_brush_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
@@ -2825,6 +2826,17 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
widgetbase_draw(&wtb, wcol);
if (but->a1 == UI_PALETTE_COLOR && but->a2 == UI_PALETTE_COLOR_ACTIVE) {
float width = rect->xmax - rect->xmin;
float height = rect->ymax - rect->ymin;
glColor4ubv((unsigned char *)wcol->outline);
glBegin(GL_TRIANGLES);
glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.9f * height);
glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.5f * height);
glVertex2f(rect->xmin + 0.5f * width, rect->ymin + 0.9f * height);
glEnd();
}
}
static void widget_normal(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign))
+55 -2
View File
@@ -35,21 +35,25 @@
#include "MEM_guardedalloc.h"
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
#include "DNA_userdef_types.h"
#include "DNA_mesh_types.h" /* init_userdef_factory */
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_mesh_types.h" /* init_userdef_factory */
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BKE_brush.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_texture.h"
#include "BKE_library.h"
#include "BIF_gl.h"
@@ -537,6 +541,13 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->preview_stitch_active;
break;
case TH_PAINT_CURVE_HANDLE:
cp = ts->paint_curve_handle;
break;
case TH_PAINT_CURVE_PIVOT:
cp = ts->paint_curve_pivot;
break;
case TH_UV_OTHERS:
cp = ts->uv_others;
break;
@@ -871,6 +882,8 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tv3d.title, 0, 0, 0, 255);
rgba_char_args_set(btheme->tv3d.freestyle_edge_mark, 0x7f, 0xff, 0x7f, 255);
rgba_char_args_set(btheme->tv3d.freestyle_face_mark, 0x7f, 0xff, 0x7f, 51);
rgba_char_args_set_fl(btheme->tv3d.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
rgba_char_args_set_fl(btheme->tv3d.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
btheme->tv3d.facedot_size = 4;
@@ -2427,6 +2440,16 @@ void init_userdef_do_versions(void)
}
}
if (U.versionfile < 272|| (U.versionfile == 272 && U.subversionfile < 2)) {
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
rgba_char_args_set_fl(btheme->tv3d.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
rgba_char_args_set_fl(btheme->tv3d.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
rgba_char_args_set_fl(btheme->tima.paint_curve_handle, 0.5f, 1.0f, 0.5f, 0.5f);
rgba_char_args_set_fl(btheme->tima.paint_curve_pivot, 1.0f, 0.5f, 0.5f, 0.5f);
}
}
{
bTheme *btheme;
for (btheme = U.themes.first; btheme; btheme = btheme->next) {
@@ -2470,4 +2493,34 @@ void init_userdef_factory(void)
me->flag &= ~ME_TWOSIDED;
}
}
{
Brush *br;
br = BKE_brush_add(G.main, "Fill");
br->imagepaint_tool = PAINT_TOOL_FILL;
br->ob_mode = OB_MODE_TEXTURE_PAINT;
br = (Brush *)BKE_libblock_find_name(ID_BR, "Mask");
if (br) {
br->imagepaint_tool = PAINT_TOOL_MASK;
br->ob_mode |= OB_MODE_TEXTURE_PAINT;
}
}
{
Scene *scene;
for (scene = G.main->scene.first; scene; scene = scene->id.next) {
if (scene->toolsettings) {
ToolSettings *ts = scene->toolsettings;
if (ts->sculpt) {
Sculpt *sculpt = ts->sculpt;
sculpt->paint.symmetry_flags |= PAINT_SYMM_X;
sculpt->flags |= SCULPT_DYNTOPO_COLLAPSE;
sculpt->detail_size = 12;
}
}
}
}
}
@@ -165,6 +165,7 @@ void ED_render_engine_changed(Main *bmain)
bScreen *sc;
ScrArea *sa;
Scene *scene;
Material *ma;
for (sc = bmain->screen.first; sc; sc = sc->id.next)
for (sa = sc->areabase.first; sa; sa = sa->next)
@@ -174,6 +175,11 @@ void ED_render_engine_changed(Main *bmain)
for (scene = bmain->scene.first; scene; scene = scene->id.next)
ED_render_id_flush_update(bmain, &scene->id);
/* reset texture painting */
for (ma = bmain->mat.first; ma; ma = ma->id.next) {
BKE_texpaint_slots_clear(ma);
}
}
/***************************** Updates ***********************************
+2 -1
View File
@@ -4154,7 +4154,8 @@ void ED_keymap_screen(wmKeyConfig *keyconf)
/* dropbox for entire window */
lb = WM_dropboxmap_find("Window", 0, 0);
WM_dropbox_add(lb, "WM_OT_open_mainfile", open_file_drop_poll, open_file_drop_copy);
WM_dropbox_add(lb, "UI_OT_drop_color", UI_drop_color_poll, UI_drop_color_copy);
keymap_modal_set(keyconf);
}
@@ -40,6 +40,7 @@ set(INC_SYS
set(SRC
paint_cursor.c
paint_curve.c
paint_hide.c
paint_image.c
paint_image_2d.c
@@ -44,6 +44,7 @@
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_image.h"
#include "BKE_node.h"
#include "BKE_paint.h"
@@ -58,6 +59,8 @@
#include "ED_view3d.h"
#include "UI_resources.h"
#include "paint_intern.h"
/* still needed for sculpt_stroke_get_location, should be
* removed eventually (TODO) */
@@ -791,6 +794,138 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
glPopAttrib();
}
BLI_INLINE void draw_tri_point(float *co, float width, bool selected)
{
float w = width / 2.0f;
if (selected)
UI_ThemeColor4(TH_VERTEX_SELECT);
else
UI_ThemeColor4(TH_PAINT_CURVE_PIVOT);
glLineWidth(3.0);
glBegin(GL_LINE_LOOP);
glVertex2f(co[0], co[1] + w);
glVertex2f(co[0] - w, co[1] - w);
glVertex2f(co[0] + w, co[1] - w);
glEnd();
glColor4f(1.0, 1.0, 1.0, 0.5);
glLineWidth(1.0);
glBegin(GL_LINE_LOOP);
glVertex2f(co[0], co[1] + w);
glVertex2f(co[0] - w, co[1] - w);
glVertex2f(co[0] + w, co[1] - w);
glEnd();
}
BLI_INLINE void draw_rect_point(float *co, float width, bool selected)
{
float w = width / 2.0f;
if (selected)
UI_ThemeColor4(TH_VERTEX_SELECT);
else
UI_ThemeColor4(TH_PAINT_CURVE_HANDLE);
glLineWidth(3.0);
glBegin(GL_LINE_LOOP);
glVertex2f(co[0] + w, co[1] + w);
glVertex2f(co[0] - w, co[1] + w);
glVertex2f(co[0] - w, co[1] - w);
glVertex2f(co[0] + w, co[1] - w);
glEnd();
glColor4f(1.0, 1.0, 1.0, 0.5);
glLineWidth(1.0);
glBegin(GL_LINE_LOOP);
glVertex2f(co[0] + w, co[1] + w);
glVertex2f(co[0] - w, co[1] + w);
glVertex2f(co[0] - w, co[1] - w);
glVertex2f(co[0] + w, co[1] - w);
glEnd();
}
BLI_INLINE void draw_bezier_handle_lines(BezTriple *bez)
{
short line1[] = {0, 1};
short line2[] = {1, 2};
glVertexPointer(2, GL_FLOAT, 3 * sizeof(float), bez->vec);
glColor4f(0.0, 0.0, 0.0, 0.5);
glLineWidth(3.0);
glDrawArrays(GL_LINE_STRIP, 0, 3);
glLineWidth(1.0);
if (bez->f1 || bez->f2)
UI_ThemeColor4(TH_VERTEX_SELECT);
else
glColor4f(1.0, 1.0, 1.0, 0.5);
glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, line1);
if (bez->f3 || bez->f2)
UI_ThemeColor4(TH_VERTEX_SELECT);
else
glColor4f(1.0, 1.0, 1.0, 0.5);
glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, line2);
}
static void paint_draw_curve_cursor(Brush *brush)
{
if (brush->paint_curve && brush->paint_curve->points) {
int i;
PaintCurve *pc = brush->paint_curve;
PaintCurvePoint *cp = pc->points;
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glEnableClientState(GL_VERTEX_ARRAY);
/* draw the bezier handles and the curve segment between the current and next point */
for (i = 0; i < pc->tot_points - 1; i++, cp++) {
int j;
PaintCurvePoint *cp_next = cp + 1;
float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
/* use color coding to distinguish handles vs curve segments */
draw_bezier_handle_lines(&cp->bez);
draw_tri_point(&cp->bez.vec[1][0], 10.0, cp->bez.f2);
draw_rect_point(&cp->bez.vec[0][0], 8.0, cp->bez.f1 || cp->bez.f2);
draw_rect_point(&cp->bez.vec[2][0], 8.0, cp->bez.f3 || cp->bez.f2);
for (j = 0; j < 2; j++)
BKE_curve_forward_diff_bezier(
cp->bez.vec[1][j],
cp->bez.vec[2][j],
cp_next->bez.vec[0][j],
cp_next->bez.vec[1][j],
data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
glVertexPointer(2, GL_FLOAT, 0, data);
glLineWidth(3.0);
glColor4f(0.0, 0.0, 0.0, 0.5);
glDrawArrays(GL_LINE_STRIP, 0, PAINT_CURVE_NUM_SEGMENTS + 1);
glLineWidth(1.0);
glColor4f(0.9, 0.9, 1.0, 0.5);
glDrawArrays(GL_LINE_STRIP, 0, PAINT_CURVE_NUM_SEGMENTS + 1);
}
/* draw last line segment */
draw_bezier_handle_lines(&cp->bez);
draw_tri_point(&cp->bez.vec[1][0], 10.0, cp->bez.f2);
draw_rect_point(&cp->bez.vec[0][0], 8.0, cp->bez.f1 || cp->bez.f2);
draw_rect_point(&cp->bez.vec[2][0], 8.0, cp->bez.f3 || cp->bez.f2);
glLineWidth(1.0);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
glDisableClientState(GL_VERTEX_ARRAY);
}
}
/* Special actions taken when paint cursor goes over mesh */
/* TODO: sculpt only for now */
static void paint_cursor_on_hit(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc,
@@ -848,6 +983,12 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
zoomx = max_ff(zoomx, zoomy);
mode = BKE_paintmode_get_active_from_context(C);
/* skip everything and draw brush here */
if (brush->flag & BRUSH_CURVE) {
paint_draw_curve_cursor(brush);
return;
}
/* set various defaults */
translation[0] = x;
translation[1] = y;
@@ -857,8 +998,11 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* don't calculate rake angles while a stroke is active because the rake variables are global and
* we may get interference with the stroke itself. For line strokes, such interference is visible */
if (!ups->stroke_active && (brush->flag & BRUSH_RAKE))
paint_calculate_rake_rotation(ups, translation);
if (!ups->stroke_active) {
if (brush->flag & BRUSH_RAKE)
/* here, translation contains the mouse coordinates. */
paint_calculate_rake_rotation(ups, translation);
}
/* draw overlay */
paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode);
@@ -878,7 +1022,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* check if brush is subtracting, use different color then */
/* TODO: no way currently to know state of pen flip or
* invert key modifier without starting a stroke */
if ((!(brush->flag & BRUSH_INVERTED) ^
if ((!(ups->draw_inverted) ^
!(brush->flag & BRUSH_DIR_IN)) &&
ELEM(brush->sculpt_tool, SCULPT_TOOL_DRAW,
SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY,
@@ -890,12 +1034,12 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* only do if brush is over the mesh */
if (hit)
paint_cursor_on_hit(ups, brush, &vc, location);
}
if (ups->draw_anchored) {
final_radius = ups->anchored_size;
translation[0] = ups->anchored_initial_mouse[0];
translation[1] = ups->anchored_initial_mouse[1];
}
if (ups->draw_anchored) {
final_radius = ups->anchored_size;
translation[0] = ups->anchored_initial_mouse[0];
translation[1] = ups->anchored_initial_mouse[1];
}
/* make lines pretty */
@@ -0,0 +1,800 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/editors/sculpt_paint/paint_curve.c
* \ingroup edsculpt
*/
#include <string.h>
#include <limits.h>
#include "MEM_guardedalloc.h"
#include "DNA_brush_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_paint.h"
#include "BLI_math_vector.h"
#include "BLI_string.h"
#include "ED_paint.h"
#include "ED_view3d.h"
#include "WM_api.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "UI_view2d.h"
#include "paint_intern.h"
#define PAINT_CURVE_SELECT_THRESHOLD 40.0f
#define PAINT_CURVE_POINT_SELECT(pcp, i) (*(&pcp->bez.f1 + i) = SELECT)
int paint_curve_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
Paint *p;
RegionView3D *rv3d = CTX_wm_region_view3d(C);
SpaceImage *sima;
if (rv3d && !(ob && ((ob->mode & OB_MODE_ALL_PAINT) != 0)))
return false;
sima = CTX_wm_space_image(C);
if (sima && sima->mode != SI_MODE_PAINT)
return false;
p = BKE_paint_get_active_from_context(C);
if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
return true;
}
return false;
}
/* Paint Curve Undo*/
typedef struct UndoCurve {
struct UndoImageTile *next, *prev;
PaintCurvePoint *points; /* points of curve */
int tot_points;
int active_point;
char idname[MAX_ID_NAME]; /* name instead of pointer*/
} UndoCurve;
static void paintcurve_undo_restore(bContext *C, ListBase *lb)
{
Paint *p = BKE_paint_get_active_from_context(C);
UndoCurve *uc;
PaintCurve *pc;
if (p->brush) {
pc = p->brush->paint_curve;
}
if (!pc)
return;
uc = (UndoCurve *)lb->first;
if (strncmp(uc->idname, pc->id.name, BLI_strnlen(uc->idname, sizeof(uc->idname))) == 0) {
SWAP(PaintCurvePoint *, pc->points, uc->points);
SWAP(int, pc->tot_points, uc->tot_points);
SWAP(int, pc->add_index, uc->active_point);
}
}
static void paintcurve_undo_delete(ListBase *lb)
{
UndoCurve *uc;
uc = (UndoCurve *)lb->first;
if (uc->points)
MEM_freeN(uc->points);
uc->points = NULL;
}
static void paintcurve_undo_begin(bContext *C, wmOperator *op, PaintCurve *pc)
{
PaintMode mode = BKE_paintmode_get_active_from_context(C);
ListBase *lb = NULL;
int undo_stack_id;
UndoCurve *uc;
switch (mode) {
case PAINT_TEXTURE_2D:
case PAINT_TEXTURE_PROJECTIVE:
undo_stack_id = UNDO_PAINT_IMAGE;
break;
case PAINT_SCULPT:
undo_stack_id = UNDO_PAINT_MESH;
break;
default:
/* do nothing, undo is handled by global */
return;
}
ED_undo_paint_push_begin(undo_stack_id, op->type->name,
paintcurve_undo_restore, paintcurve_undo_delete, NULL);
lb = undo_paint_push_get_list(undo_stack_id);
uc = MEM_callocN(sizeof(*uc), "Undo_curve");
lb->first = uc;
BLI_strncpy(uc->idname, pc->id.name, sizeof(uc->idname));
uc->tot_points = pc->tot_points;
uc->active_point = pc->add_index;
uc->points = MEM_dupallocN(pc->points);
undo_paint_push_count_alloc(undo_stack_id, sizeof(*uc) + sizeof(*pc->points) * pc->tot_points);
ED_undo_paint_push_end(undo_stack_id);
}
#define SEL_F1 (1 << 0)
#define SEL_F2 (1 << 1)
#define SEL_F3 (1 << 2)
/* returns 0, 1, or 2 in point according to handle 1, pivot or handle 2 */
static PaintCurvePoint *paintcurve_point_get_closest(PaintCurve *pc, const float pos[2], bool ignore_pivot, const float threshold, char *point)
{
PaintCurvePoint *pcp, *closest = NULL;
int i;
float dist, closest_dist = FLT_MAX;
for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
dist = len_manhattan_v2v2(pos, pcp->bez.vec[0]);
if (dist < threshold) {
if (dist < closest_dist) {
closest = pcp;
closest_dist = dist;
if (point)
*point = SEL_F1;
}
}
if (!ignore_pivot) {
dist = len_manhattan_v2v2(pos, pcp->bez.vec[1]);
if (dist < threshold) {
if (dist < closest_dist) {
closest = pcp;
closest_dist = dist;
if (point)
*point = SEL_F2;
}
}
}
dist = len_manhattan_v2v2(pos, pcp->bez.vec[2]);
if (dist < threshold) {
if (dist < closest_dist) {
closest = pcp;
closest_dist = dist;
if (point)
*point = SEL_F3;
}
}
}
return closest;
}
static int paintcurve_point_co_index(char sel)
{
char i = 0;
while (sel != 1) {
sel >>= 1;
i++;
}
return i;
}
/******************* Operators *********************************/
static int paintcurve_new_exec(bContext *C, wmOperator *UNUSED(op))
{
Paint *p = BKE_paint_get_active_from_context(C);
Main *bmain = CTX_data_main(C);
if (p && p->brush) {
p->brush->paint_curve = BKE_paint_curve_add(bmain, "PaintCurve");
}
return OPERATOR_FINISHED;
}
void PAINTCURVE_OT_new(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add New Paint Curve";
ot->description = "Add new paint curve";
ot->idname = "PAINTCURVE_OT_new";
/* api callbacks */
ot->exec = paintcurve_new_exec;
ot->poll = paint_curve_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static void paintcurve_point_add(bContext *C, wmOperator *op, const int loc[2])
{
Paint *p = BKE_paint_get_active_from_context(C);
Brush *br = p->brush;
Main *bmain = CTX_data_main(C);
PaintCurve *pc;
PaintCurvePoint *pcp;
wmWindow *window = CTX_wm_window(C);
ARegion *ar = CTX_wm_region(C);
float vec[3] = {loc[0], loc[1], 0.0};
int add_index;
int i;
pc = br->paint_curve;
if (!pc) {
br->paint_curve = pc = BKE_paint_curve_add(bmain, "PaintCurve");
}
paintcurve_undo_begin(C, op, pc);
pcp = MEM_mallocN((pc->tot_points + 1) * sizeof(PaintCurvePoint), "PaintCurvePoint");
add_index = pc->add_index;
if (pc->points) {
if (add_index > 0)
memcpy(pcp, pc->points, add_index * sizeof(PaintCurvePoint));
if (add_index < pc->tot_points)
memcpy(pcp + add_index + 1, pc->points + add_index, (pc->tot_points - add_index) * sizeof(PaintCurvePoint));
MEM_freeN(pc->points);
}
pc->points = pcp;
pc->tot_points++;
/* initialize new point */
memset(&pcp[add_index], 0, sizeof(PaintCurvePoint));
copy_v3_v3(pcp[add_index].bez.vec[0], vec);
copy_v3_v3(pcp[add_index].bez.vec[1], vec);
copy_v3_v3(pcp[add_index].bez.vec[2], vec);
/* last step, clear selection from all bezier handles expect the next */
for (i = 0; i < pc->tot_points; i++) {
pcp[i].bez.f1 = pcp[i].bez.f2 = pcp[i].bez.f3 = 0;
}
pcp[add_index].bez.f3 = SELECT;
pcp[add_index].bez.h2 = HD_ALIGN;
pc->add_index = add_index + 1;
WM_paint_cursor_tag_redraw(window, ar);
}
static int paintcurve_add_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int loc[2] = {event->mval[0], event->mval[1]};
paintcurve_point_add(C, op, loc);
RNA_int_set_array(op->ptr, "location", loc);
return OPERATOR_FINISHED;
}
static int paintcurve_add_point_exec(bContext *C, wmOperator *op)
{
int loc[2];
if (RNA_struct_property_is_set(op->ptr, "location")) {
RNA_int_get_array(op->ptr, "location", loc);
paintcurve_point_add(C, op, loc);
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
}
void PAINTCURVE_OT_add_point(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add New Paint Curve Point";
ot->description = "Add new paint curve point";
ot->idname = "PAINTCURVE_OT_add_point";
/* api callbacks */
ot->invoke = paintcurve_add_point_invoke;
ot->exec = paintcurve_add_point_exec;
ot->poll = paint_curve_poll;
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
/* properties */
RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, SHRT_MAX,
"Location", "Location of vertex in area space", 0, SHRT_MAX);
}
static int paintcurve_delete_point_exec(bContext *C, wmOperator *op)
{
Paint *p = BKE_paint_get_active_from_context(C);
Brush *br = p->brush;
PaintCurve *pc;
PaintCurvePoint *pcp;
wmWindow *window = CTX_wm_window(C);
ARegion *ar = CTX_wm_region(C);
int i;
int tot_del = 0;
pc = br->paint_curve;
if (!pc || pc->tot_points == 0) {
return OPERATOR_CANCELLED;
}
paintcurve_undo_begin(C, op, pc);
#define DELETE_TAG 2
for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
if ((pcp->bez.f1 & SELECT) || (pcp->bez.f2 & SELECT) || (pcp->bez.f3 & SELECT)) {
pcp->bez.f2 |= DELETE_TAG;
tot_del++;
}
}
if (tot_del > 0) {
int j = 0;
int new_tot = pc->tot_points - tot_del;
PaintCurvePoint *points_new = NULL;
if (new_tot > 0)
points_new = MEM_mallocN(new_tot * sizeof(PaintCurvePoint), "PaintCurvePoint");
for (i = 0, pcp = pc->points; i < pc->tot_points; i++, pcp++) {
if (!(pcp->bez.f2 & DELETE_TAG)) {
points_new[j] = pc->points[i];
if ((i + 1) == pc->add_index) {
pc->add_index = j + 1;
}
j++;
}
else if ((i + 1) == pc->add_index) {
/* prefer previous point */
pc->add_index = j;
}
}
MEM_freeN(pc->points);
pc->points = points_new;
pc->tot_points = new_tot;
}
#undef DELETE_TAG
WM_paint_cursor_tag_redraw(window, ar);
return OPERATOR_FINISHED;
}
void PAINTCURVE_OT_delete_point(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add New Paint Curve Point";
ot->description = "Add new paint curve point";
ot->idname = "PAINTCURVE_OT_delete_point";
/* api callbacks */
ot->exec = paintcurve_delete_point_exec;
ot->poll = paint_curve_poll;
/* flags */
ot->flag = OPTYPE_UNDO;
}
static bool paintcurve_point_select(bContext *C, wmOperator *op, const int loc[2], bool toggle, bool extend)
{
wmWindow *window = CTX_wm_window(C);
ARegion *ar = CTX_wm_region(C);
Paint *p = BKE_paint_get_active_from_context(C);
Brush *br = p->brush;
PaintCurve *pc;
PaintCurvePoint *pcp;
int i;
const float loc_fl[2] = {UNPACK2(loc)};
pc = br->paint_curve;
if (!pc)
return false;
paintcurve_undo_begin(C, op, pc);
pcp = pc->points;
if (toggle) {
char select = 0;
bool selected = false;
for (i = 0; i < pc->tot_points; i++) {
if (pcp[i].bez.f1 || pcp[i].bez.f2 || pcp[i].bez.f3) {
selected = true;
break;
}
}
if (!selected) {
select = SELECT;
}
for (i = 0; i < pc->tot_points; i++) {
pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = select;
}
}
else {
PaintCurvePoint *pcp;
char selflag;
pcp = paintcurve_point_get_closest(pc, loc_fl, false, PAINT_CURVE_SELECT_THRESHOLD, &selflag);
if (pcp) {
pc->add_index = (pcp - pc->points) + 1;
if (selflag == SEL_F2) {
if (extend)
pcp->bez.f2 ^= SELECT;
else
pcp->bez.f2 |= SELECT;
}
else if (selflag == SEL_F1) {
if (extend)
pcp->bez.f1 ^= SELECT;
else
pcp->bez.f1 |= SELECT;
}
else if (selflag == SEL_F3) {
if (extend)
pcp->bez.f3 ^= SELECT;
else
pcp->bez.f3 |= SELECT;
}
}
/* clear selection for unselected points if not extending and if a point has been selected */
if (!extend && pcp) {
for (i = 0; i < pc->tot_points; i++) {
pc->points[i].bez.f1 = pc->points[i].bez.f2 = pc->points[i].bez.f3 = 0;
if ((pc->points + i) == pcp) {
char index = paintcurve_point_co_index(selflag);
PAINT_CURVE_POINT_SELECT(pcp, index);
}
}
}
if (!pcp)
return false;
}
WM_paint_cursor_tag_redraw(window, ar);
return true;
}
static int paintcurve_select_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int loc[2] = {UNPACK2(event->mval)};
bool toggle = RNA_boolean_get(op->ptr, "toggle");
bool extend = RNA_boolean_get(op->ptr, "extend");
if (paintcurve_point_select(C, op, loc, toggle, extend)) {
RNA_int_set_array(op->ptr, "location", loc);
return OPERATOR_FINISHED;
}
else {
return OPERATOR_CANCELLED;
}
}
static int paintcurve_select_point_exec(bContext *C, wmOperator *op)
{
int loc[2];
if (RNA_struct_property_is_set(op->ptr, "location")) {
bool toggle = RNA_boolean_get(op->ptr, "toggle");
bool extend = RNA_boolean_get(op->ptr, "extend");
RNA_int_get_array(op->ptr, "location", loc);
if (paintcurve_point_select(C, op, loc, toggle, extend))
return OPERATOR_FINISHED;
}
return OPERATOR_CANCELLED;
}
void PAINTCURVE_OT_select(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "Select Paint Curve Point";
ot->description = "Select a paint curve point";
ot->idname = "PAINTCURVE_OT_select";
/* api callbacks */
ot->invoke = paintcurve_select_point_invoke;
ot->exec = paintcurve_select_point_exec;
ot->poll = paint_curve_poll;
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
/* properties */
RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, SHRT_MAX,
"Location", "Location of vertex in area space", 0, SHRT_MAX);
prop = RNA_def_boolean(ot->srna, "toggle", false, "Toggle", "Select/Deselect all");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
typedef struct PointSlideData {
PaintCurvePoint *pcp;
char select;
int initial_loc[2];
float point_initial_loc[3][2];
int event;
bool align;
} PointSlideData;
static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Paint *p = BKE_paint_get_active_from_context(C);
const float loc_fl[2] = {UNPACK2(event->mval)};
char select;
int i;
bool do_select = RNA_boolean_get(op->ptr, "select");
bool align = RNA_boolean_get(op->ptr, "align");
Brush *br = p->brush;
PaintCurve *pc = br->paint_curve;
PaintCurvePoint *pcp;
if (!pc)
return OPERATOR_PASS_THROUGH;
if (do_select) {
pcp = paintcurve_point_get_closest(pc, loc_fl, align, PAINT_CURVE_SELECT_THRESHOLD, &select);
}
else {
/* just find first selected point */
for (i = 0; i < pc->tot_points; i++) {
if (pc->points[i].bez.f1 || pc->points[i].bez.f2 || pc->points[i].bez.f3) {
pcp = &pc->points[i];
select = SEL_F3;
break;
}
}
}
if (pcp) {
ARegion *ar = CTX_wm_region(C);
wmWindow *window = CTX_wm_window(C);
PointSlideData *psd = MEM_mallocN(sizeof(PointSlideData), "PointSlideData");
copy_v2_v2_int(psd->initial_loc, event->mval);
psd->event = event->type;
psd->pcp = pcp;
psd->select = paintcurve_point_co_index(select);
for (i = 0; i < 3; i++) {
copy_v2_v2(psd->point_initial_loc[i], pcp->bez.vec[i]);
}
psd->align = align;
op->customdata = psd;
if (do_select)
paintcurve_undo_begin(C, op, pc);
/* first, clear all selection from points */
for (i = 0; i < pc->tot_points; i++)
pc->points[i].bez.f1 = pc->points[i].bez.f3 = pc->points[i].bez.f2 = 0;
/* only select the active point */
PAINT_CURVE_POINT_SELECT(pcp, psd->select);
pc->add_index = (pcp - pc->points) + 1;
WM_event_add_modal_handler(C, op);
WM_paint_cursor_tag_redraw(window, ar);
return OPERATOR_RUNNING_MODAL;
}
return OPERATOR_PASS_THROUGH;
}
static int paintcurve_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
PointSlideData *psd = op->customdata;
if (event->type == psd->event && event->val == KM_RELEASE) {
MEM_freeN(psd);
return OPERATOR_FINISHED;
}
switch (event->type) {
case MOUSEMOVE:
{
ARegion *ar = CTX_wm_region(C);
wmWindow *window = CTX_wm_window(C);
float diff[2] = {event->mval[0] - psd->initial_loc[0],
event->mval[1] - psd->initial_loc[1]};
if (psd->select == 1) {
int i;
for (i = 0; i < 3; i++)
add_v2_v2v2(psd->pcp->bez.vec[i], diff, psd->point_initial_loc[i]);
}
else {
add_v2_v2(diff, psd->point_initial_loc[psd->select]);
copy_v2_v2(psd->pcp->bez.vec[psd->select], diff);
if (psd->align) {
char opposite = (psd->select == 0) ? 2 : 0;
sub_v2_v2v2(diff, psd->pcp->bez.vec[1], psd->pcp->bez.vec[psd->select]);
add_v2_v2v2(psd->pcp->bez.vec[opposite], psd->pcp->bez.vec[1], diff);
}
}
WM_paint_cursor_tag_redraw(window, ar);
break;
}
default:
break;
}
return OPERATOR_RUNNING_MODAL;
}
void PAINTCURVE_OT_slide(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Slide Paint Curve Point";
ot->description = "Select and slide paint curve point";
ot->idname = "PAINTCURVE_OT_slide";
/* api callbacks */
ot->invoke = paintcurve_slide_invoke;
ot->modal = paintcurve_slide_modal;
ot->poll = paint_curve_poll;
/* flags */
ot->flag = OPTYPE_UNDO;
/* properties */
RNA_def_boolean(ot->srna, "align", false, "Align Handles", "Aligns opposite point handle during transform");
RNA_def_boolean(ot->srna, "select", true, "Select", "Attempt to select a point handle before transform");
}
static int paintcurve_draw_exec(bContext *C, wmOperator *UNUSED(op))
{
PaintMode mode = BKE_paintmode_get_active_from_context(C);
const char *name;
switch (mode) {
case PAINT_TEXTURE_2D:
case PAINT_TEXTURE_PROJECTIVE:
name = "PAINT_OT_image_paint";
break;
case PAINT_WEIGHT:
name = "PAINT_OT_weight_paint";
break;
case PAINT_VERTEX:
name = "PAINT_OT_vertex_paint";
break;
case PAINT_SCULPT:
name = "SCULPT_OT_brush_stroke";
break;
default:
return OPERATOR_PASS_THROUGH;
}
return WM_operator_name_call(C, name, WM_OP_INVOKE_DEFAULT, NULL);
}
void PAINTCURVE_OT_draw(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Draw Curve";
ot->description = "Draw curve";
ot->idname = "PAINTCURVE_OT_draw";
/* api callbacks */
ot->exec = paintcurve_draw_exec;
ot->poll = paint_curve_poll;
/* flags */
ot->flag = OPTYPE_UNDO;
}
static int paintcurve_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
op->customdata = SET_INT_IN_POINTER(event->type);
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
}
static int paintcurve_cursor_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->type == GET_INT_FROM_POINTER(op->customdata) && event->val == KM_RELEASE)
return OPERATOR_FINISHED;
if (event->type == MOUSEMOVE) {
PaintMode mode = BKE_paintmode_get_active_from_context(C);
switch (mode) {
case PAINT_TEXTURE_2D:
{
ARegion *ar = CTX_wm_region(C);
SpaceImage *sima = CTX_wm_space_image(C);
float location[2];
if (!sima)
return OPERATOR_CANCELLED;
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]);
copy_v2_v2(sima->cursor, location);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL);
break;
}
default:
ED_view3d_cursor3d_update(C, event->mval);
break;
}
}
return OPERATOR_RUNNING_MODAL;
}
void PAINTCURVE_OT_cursor(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Place Cursor";
ot->description = "Place cursor";
ot->idname = "PAINTCURVE_OT_cursor";
/* api callbacks */
ot->invoke = paintcurve_cursor_invoke;
ot->modal = paintcurve_cursor_modal;
ot->poll = paint_curve_poll;
/* flags */
ot->flag = 0;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -38,7 +38,9 @@ struct bglMats;
struct Brush;
struct ImagePool;
struct ColorSpace;
struct ColorManagedDisplay;
struct ListBase;
struct Material;
struct Mesh;
struct MTex;
struct Object;
@@ -65,7 +67,7 @@ typedef void (*StrokeUpdateStep)(struct bContext *C, struct PaintStroke *stroke,
typedef void (*StrokeRedraw)(const struct bContext *C, struct PaintStroke *stroke, bool final);
typedef void (*StrokeDone)(const struct bContext *C, struct PaintStroke *stroke);
struct PaintStroke *paint_stroke_new(struct bContext *C,
struct PaintStroke *paint_stroke_new(struct bContext *C, struct wmOperator *op,
StrokeGetLocation get_location, StrokeTestStart test_start,
StrokeUpdateStep update_step, StrokeRedraw redraw,
StrokeDone done, int event_type);
@@ -84,6 +86,7 @@ int paint_stroke_exec(struct bContext *C, struct wmOperator *op);
void paint_stroke_cancel(struct bContext *C, struct wmOperator *op);
struct ViewContext *paint_stroke_view_context(struct PaintStroke *stroke);
void *paint_stroke_mode_data(struct PaintStroke *stroke);
float paint_stroke_distance_get(struct PaintStroke *stroke);
void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data);
int paint_poll(struct bContext *C);
void paint_cursor_start(struct bContext *C, int (*poll)(struct bContext *C));
@@ -117,7 +120,7 @@ void PAINT_OT_weight_gradient(struct wmOperatorType *ot);
void PAINT_OT_vertex_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_vertex_paint(struct wmOperatorType *ot);
unsigned int vpaint_get_current_col(struct VPaint *vp);
unsigned int vpaint_get_current_col(struct Scene *scene, struct VPaint *vp);
/* paint_vertex_proj.c */
@@ -144,32 +147,42 @@ typedef struct ImagePaintPartialRedraw {
#define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS)
int image_texture_paint_poll(struct bContext *C);
void *image_undo_find_tile(struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask);
void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile);
void *image_undo_find_tile(struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate);
void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **, bool **valid, bool proj);
void image_undo_remove_masks(void);
void image_undo_init_locks(void);
void image_undo_end_locks(void);
void imapaint_image_update(struct SpaceImage *sima, struct Image *image, struct ImBuf *ibuf, short texpaint);
struct ImagePaintPartialRedraw *get_imapaintpartial(void);
void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr);
void imapaint_region_tiles(struct ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty, int *tw, int *th);
int get_imapaint_zoom(struct bContext *C, float *zoomx, float *zoomy);
void *paint_2d_new_stroke(struct bContext *, struct wmOperator *);
void *paint_2d_new_stroke(struct bContext *, struct wmOperator *, int mode);
void paint_2d_redraw(const bContext *C, void *ps, bool final);
void paint_2d_stroke_done(void *ps);
void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], int eraser);
void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], int eraser, float pressure, float distance, float size);
void paint_2d_bucket_fill(const struct bContext *C, const float color[3], struct Brush *br, const float mouse_init[2], void *ps);
void paint_2d_gradient_fill (const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps);
void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const float mouse[2], int mode);
void paint_proj_stroke(struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2]);
void paint_proj_redraw(const bContext *C, void *pps, bool final);
void paint_proj_stroke(const struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2], float pressure, float distance, float size);
void paint_proj_redraw(const struct bContext *C, void *pps, bool final);
void paint_proj_stroke_done(void *ps);
void paint_proj_mesh_data_ensure(bContext *C, struct Object *ob, struct wmOperator *op);
bool proj_paint_add_slot(bContext *C, int type, struct Material *ma);
void paint_brush_color_get(struct Scene *scene, struct Brush *br, bool color_correction, bool invert, float distance, float pressure, float color[3], struct ColorManagedDisplay *display);
bool paint_use_opacity_masking(struct Brush *brush);
void paint_brush_init_tex(struct Brush *brush);
void paint_brush_exit_tex(struct Brush *brush);
void PAINT_OT_grab_clone(struct wmOperatorType *ot);
void PAINT_OT_sample_color(struct wmOperatorType *ot);
void PAINT_OT_brush_colors_flip(struct wmOperatorType *ot);
void PAINT_OT_texture_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_project_image(struct wmOperatorType *ot);
void PAINT_OT_image_from_view(struct wmOperatorType *ot);
/* new texture painting */
void PAINT_OT_add_texture_paint_slot(struct wmOperatorType *ot);
void PAINT_OT_image_paint(struct wmOperatorType *ot);
/* uv sculpting */
@@ -202,7 +215,7 @@ float paint_calc_object_space_radius(struct ViewContext *vc, const float center[
float paint_get_tex_pixel(struct MTex *mtex, float u, float v, struct ImagePool *pool, int thread);
void paint_get_tex_pixel_col(struct MTex *mtex, float u, float v, float rgba[4], struct ImagePool *pool, int thread, bool convert, struct ColorSpace *colorspace);
void paint_sample_color(const struct bContext *C, struct ARegion *ar, int x, int y);
void paint_sample_color(bContext *C, struct ARegion *ar, int x, int y, bool texpaint_proj, bool palette);
void BRUSH_OT_curve_preset(struct wmOperatorType *ot);
void PAINT_OT_face_select_linked(struct wmOperatorType *ot);
@@ -213,8 +226,10 @@ void PAINT_OT_face_select_reveal(struct wmOperatorType *ot);
void PAINT_OT_vert_select_all(struct wmOperatorType *ot);
void PAINT_OT_vert_select_ungrouped(struct wmOperatorType *ot);
int vert_paint_poll(struct bContext *C);
int mask_paint_poll(struct bContext *C);
int paint_curve_poll(struct bContext *C);
int facemask_paint_poll(struct bContext *C);
void flip_v3_v3(float out[3], const float in[3], const char symm);
@@ -229,7 +244,6 @@ typedef enum BrushStrokeMode {
/* paint_undo.c */
struct ListBase *undo_paint_push_get_list(int type);
void undo_paint_push_count_alloc(int type, int size);
bool sculpt_undo_cleanup(struct bContext *C, struct ListBase *lb);
/* paint_hide.c */
@@ -258,4 +272,29 @@ typedef enum {
void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot);
void PAINT_OT_mask_lasso_gesture(struct wmOperatorType *ot);
/* paint_curve.c */
void PAINTCURVE_OT_new(struct wmOperatorType *ot);
void PAINTCURVE_OT_add_point(struct wmOperatorType *ot);
void PAINTCURVE_OT_delete_point(struct wmOperatorType *ot);
void PAINTCURVE_OT_select(struct wmOperatorType *ot);
void PAINTCURVE_OT_slide(struct wmOperatorType *ot);
void PAINTCURVE_OT_draw(struct wmOperatorType *ot);
void PAINTCURVE_OT_cursor(struct wmOperatorType *ot);
/* image painting blur kernel */
typedef struct {
float *wdata; /* actual kernel */
int side; /* kernel side */
int side_squared; /* data side */
int pixel_len; /* pixels around center that kernel is wide */
} BlurKernel;
enum BlurKernelType;
/* can be extended to other blur kernels later */
BlurKernel *paint_new_blur_kernel(struct Brush *br);
void paint_delete_blur_kernel(BlurKernel *);
/* paint curve defines */
#define PAINT_CURVE_NUM_SEGMENTS 40
#endif /* __PAINT_INTERN_H__ */
+171 -5
View File
@@ -149,11 +149,112 @@ static void BRUSH_OT_scale_size(wmOperatorType *ot)
RNA_def_float(ot->srna, "scalar", 1, 0, 2, "Scalar", "Factor to scale brush size by", 0, 2);
}
/* Palette operators */
static int palette_new_exec(bContext *C, wmOperator *UNUSED(op))
{
Paint *paint = BKE_paint_get_active_from_context(C);
Main *bmain = CTX_data_main(C);
Palette *palette;
palette = BKE_palette_add(bmain, "Palette");
BKE_paint_palette_set(paint, palette);
return OPERATOR_FINISHED;
}
static void PALETTE_OT_new(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add New Palette";
ot->description = "Add new palette";
ot->idname = "PALETTE_OT_new";
/* api callbacks */
ot->exec = palette_new_exec;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int palette_poll(bContext *C)
{
Paint *paint = BKE_paint_get_active_from_context(C);
if (paint && paint->palette != NULL)
return true;
return false;
}
static int palette_color_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = paint->brush;
PaintMode mode = BKE_paintmode_get_active_from_context(C);
Palette *palette = paint->palette;
PaletteColor *color = BKE_palette_color_add(palette);
if (ELEM(mode, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D, PAINT_VERTEX)) {
copy_v3_v3(color->rgb, BKE_brush_color_get(scene, brush));
color->value = 0.0;
}
else if (mode == PAINT_WEIGHT) {
zero_v3(color->rgb);
color->value = brush->weight;
}
return OPERATOR_FINISHED;
}
static void PALETTE_OT_color_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "New Palette Color";
ot->description = "Add new color to active palette";
ot->idname = "PALETTE_OT_color_add";
/* api callbacks */
ot->exec = palette_color_add_exec;
ot->poll = palette_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int palette_color_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
Paint *paint = BKE_paint_get_active_from_context(C);
Palette *palette = paint->palette;
BKE_palette_color_delete(palette);
return OPERATOR_FINISHED;
}
static void PALETTE_OT_color_delete(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Delete Palette Color";
ot->description = "Remove active color from palette";
ot->idname = "PALETTE_OT_color_delete";
/* api callbacks */
ot->exec = palette_color_delete_exec;
ot->poll = palette_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int vertex_color_set_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
Object *obact = CTX_data_active_object(C);
unsigned int paintcol = vpaint_get_current_col(scene->toolsettings->vpaint);
unsigned int paintcol = vpaint_get_current_col(scene, scene->toolsettings->vpaint);
if (ED_vpaint_fill(obact, paintcol)) {
ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
@@ -332,6 +433,7 @@ static int brush_generic_tool_set(Main *bmain, Paint *paint, const int tool,
if (brush) {
BKE_paint_brush_set(paint, brush);
BKE_paint_invalidate_overlay_all();
WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);
return OPERATOR_FINISHED;
}
@@ -928,8 +1030,37 @@ static void ed_keymap_stencil(wmKeyMap *keymap)
/**************************** registration **********************************/
void ED_operatormacros_paint(void)
{
wmOperatorType *ot;
wmOperatorTypeMacro *otmacro;
ot = WM_operatortype_append_macro("PAINTCURVE_OT_add_point_slide", "Add Curve Point and Slide",
"Add new curve point and slide it", OPTYPE_UNDO);
ot->description = "Add new curve point and slide it";
WM_operatortype_macro_define(ot, "PAINTCURVE_OT_add_point");
otmacro = WM_operatortype_macro_define(ot, "PAINTCURVE_OT_slide");
RNA_boolean_set(otmacro->ptr, "align", true);
RNA_boolean_set(otmacro->ptr, "select", false);
}
void ED_operatortypes_paint(void)
{
/* palette */
WM_operatortype_append(PALETTE_OT_new);
WM_operatortype_append(PALETTE_OT_color_add);
WM_operatortype_append(PALETTE_OT_color_delete);
/* paint curve */
WM_operatortype_append(PAINTCURVE_OT_new);
WM_operatortype_append(PAINTCURVE_OT_add_point);
WM_operatortype_append(PAINTCURVE_OT_delete_point);
WM_operatortype_append(PAINTCURVE_OT_select);
WM_operatortype_append(PAINTCURVE_OT_slide);
WM_operatortype_append(PAINTCURVE_OT_draw);
WM_operatortype_append(PAINTCURVE_OT_cursor);
/* brush */
WM_operatortype_append(BRUSH_OT_add);
WM_operatortype_append(BRUSH_OT_scale_size);
@@ -950,6 +1081,8 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_grab_clone);
WM_operatortype_append(PAINT_OT_project_image);
WM_operatortype_append(PAINT_OT_image_from_view);
WM_operatortype_append(PAINT_OT_brush_colors_flip);
WM_operatortype_append(PAINT_OT_add_texture_paint_slot);
/* weight */
WM_operatortype_append(PAINT_OT_weight_paint_toggle);
@@ -1119,12 +1252,44 @@ static void paint_partial_visibility_keys(wmKeyMap *keymap)
RNA_enum_set(kmi->ptr, "area", PARTIALVIS_ALL);
}
static void paint_keymap_curve(wmKeyMap *keymap)
{
wmKeyMapItem *kmi;
WM_keymap_add_item(keymap, "PAINTCURVE_OT_add_point_slide", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "PAINTCURVE_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "PAINTCURVE_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "extend", true);
WM_keymap_add_item(keymap, "PAINTCURVE_OT_slide", ACTIONMOUSE, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "PAINTCURVE_OT_slide", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "align", true);
kmi = WM_keymap_add_item(keymap, "PAINTCURVE_OT_select", AKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "toggle", true);
WM_keymap_add_item(keymap, "PAINTCURVE_OT_cursor", ACTIONMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PAINTCURVE_OT_delete_point", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PAINTCURVE_OT_draw", RETKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", GKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0);
RNA_boolean_set(kmi->ptr, "release_confirm", true);
WM_keymap_add_item(keymap, "TRANSFORM_OT_rotate", RKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "TRANSFORM_OT_resize", SKEY, KM_PRESS, 0, 0);
}
void ED_keymap_paint(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
wmKeyMapItem *kmi;
int i;
keymap = WM_keymap_find(keyconf, "Paint Curve", 0, 0);
keymap->poll = paint_curve_poll;
paint_keymap_curve(keymap);
/* Sculpt mode */
keymap = WM_keymap_find(keyconf, "Sculpt", 0, 0);
keymap->poll = sculpt_mode_poll;
@@ -1191,7 +1356,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "create_missing", 1);
/* */
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.sculpt.brush.stroke_method");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SKEY, KM_PRESS, KM_SHIFT, 0);
@@ -1225,7 +1390,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", RKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.texture_angle_source_random");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.stroke_method");
/* Weight Paint mode */
@@ -1250,7 +1415,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
ed_keymap_stencil(keymap);
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.stroke_method");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", MKEY, KM_PRESS, 0, 0); /* face mask toggle */
@@ -1283,6 +1448,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "mode", BRUSH_STROKE_NORMAL);
RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "mode", BRUSH_STROKE_INVERT);
WM_keymap_add_item(keymap, "PAINT_OT_brush_colors_flip", XKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PAINT_OT_grab_clone", RIGHTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "PAINT_OT_sample_color", SKEY, KM_PRESS, 0, 0);
@@ -1301,7 +1467,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", RKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.image_paint.brush.texture_angle_source_random");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", AKEY, KM_PRESS, 0, 0);
kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", EKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.image_paint.brush.stroke_method");
/* face-mask mode */
@@ -36,16 +36,19 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_rand.h"
#include "BLI_listbase.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
#include "RNA_access.h"
#include "BKE_context.h"
#include "BKE_paint.h"
#include "BKE_brush.h"
#include "BKE_curve.h"
#include "BKE_colortools.h"
#include "BKE_image.h"
@@ -72,7 +75,7 @@ typedef struct PaintSample {
typedef struct PaintStroke {
void *mode_data;
void *smooth_stroke_cursor;
void *stroke_cursor;
wmTimer *timer;
/* Cached values */
@@ -81,6 +84,9 @@ typedef struct PaintStroke {
Brush *brush;
UnifiedPaintSettings *ups;
/* used for lines and curves */
ListBase line;
/* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
* to smooth the stroke */
PaintSample samples[PAINT_MAX_INPUT_SAMPLES];
@@ -88,6 +94,8 @@ typedef struct PaintStroke {
int cur_sample;
float last_mouse_position[2];
/* space distance covered so far */
float stroke_distance;
/* Set whether any stroke step has yet occurred
* e.g. in sculpt mode, stroke doesn't start until cursor
@@ -116,18 +124,17 @@ typedef struct PaintStroke {
StrokeDone done;
} PaintStroke;
/*** Cursor ***/
static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata)
/*** Cursors ***/
static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata)
{
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
PaintStroke *stroke = customdata;
if (stroke && brush && (brush->flag & BRUSH_SMOOTH_STROKE)) {
glColor4ubv(paint->paint_cursor_col);
if (stroke && brush) {
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glColor4ubv(paint->paint_cursor_col);
sdrawline(x, y, (int)stroke->last_mouse_position[0],
(int)stroke->last_mouse_position[1]);
glDisable(GL_BLEND);
@@ -135,6 +142,33 @@ static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata
}
}
static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
{
Paint *paint = BKE_paint_get_active_from_context(C);
PaintStroke *stroke = customdata;
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glEnable(GL_LINE_STIPPLE);
glLineStipple(3, 0xAAAA);
glColor4ub(0, 0, 0, paint->paint_cursor_col[3]);
glLineWidth(3.0);
sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
x, y);
glColor4ub(255, 255, 255, paint->paint_cursor_col[3]);
glLineWidth(1.0);
sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
x, y);
glDisable(GL_LINE_STIPPLE);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
}
static bool paint_tool_require_location(Brush *brush, PaintMode mode)
{
switch (mode) {
@@ -155,13 +189,18 @@ static bool paint_tool_require_location(Brush *brush, PaintMode mode)
}
/* Initialize the stroke cache variants from operator properties */
static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
struct PaintStroke *stroke,
const float mouse[2], float pressure)
static bool paint_brush_update(bContext *C,
Brush *brush,
PaintMode mode,
struct PaintStroke *stroke,
const float mouse_init[2],
float mouse[2], float pressure,
float location[3])
{
Scene *scene = CTX_data_scene(C);
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
UnifiedPaintSettings *ups = stroke->ups;
bool location_sampled = false;
bool location_success = false;
/* XXX: Use pressure value from first brush step for brushes which don't
* support strokes (grab, thumb). They depends on initial state and
* brush coord/pressure/etc.
@@ -222,14 +261,14 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
else {
copy_v2_v2(ups->tex_mouse, mouse);
}
}
/* take care of mask texture, if any */
if (brush->mask_mtex.tex) {
if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
BKE_brush_randomize_texture_coordinates(ups, true);
else {
copy_v2_v2(ups->mask_tex_mouse, mouse);
/* take care of mask texture, if any */
if (brush->mask_mtex.tex) {
if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
BKE_brush_randomize_texture_coordinates(ups, true);
else {
copy_v2_v2(ups->mask_tex_mouse, mouse);
}
}
}
@@ -246,14 +285,14 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
ups->brush_rotation = atan2(dx, dy) + M_PI;
if (brush->flag & BRUSH_EDGE_TO_EDGE) {
float out[3];
halfway[0] = dx * 0.5f + stroke->initial_mouse[0];
halfway[1] = dy * 0.5f + stroke->initial_mouse[1];
if (stroke->get_location) {
if (stroke->get_location(C, out, halfway)) {
if (stroke->get_location(C, location, halfway)) {
hit = true;
location_sampled = true;
location_success = true;
}
else if (!paint_tool_require_location(brush, mode)) {
hit = true;
@@ -266,17 +305,43 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
if (hit) {
copy_v2_v2(ups->anchored_initial_mouse, halfway);
copy_v2_v2(ups->tex_mouse, halfway);
copy_v2_v2(ups->mask_tex_mouse, halfway);
copy_v2_v2(mouse, halfway);
ups->anchored_size /= 2.0f;
ups->pixel_radius /= 2.0f;
stroke->stroke_distance = ups->pixel_radius;
}
else
else {
copy_v2_v2(ups->anchored_initial_mouse, stroke->initial_mouse);
copy_v2_v2(mouse, stroke->initial_mouse);
stroke->stroke_distance = ups->pixel_radius;
}
ups->pixel_radius /= stroke->zoom_2d;
ups->draw_anchored = true;
}
else if (brush->flag & BRUSH_RAKE) {
paint_calculate_rake_rotation(ups, mouse);
/* here we are using the initial mouse coordinate because we do not want the rake
* result to depend on jittering */
if (!stroke->brush_init)
copy_v2_v2(ups->last_rake, mouse_init);
else
paint_calculate_rake_rotation(ups, mouse_init);
}
if (!location_sampled) {
if (stroke->get_location) {
if (stroke->get_location(C, location, mouse))
location_success = true;
else if (!paint_tool_require_location(brush, mode))
location_success = true;
}
else {
zero_v3(location);
location_success = true;
}
}
return location_success;
}
@@ -284,12 +349,11 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float mouse_in[2], float pressure)
{
Scene *scene = CTX_data_scene(C);
wmWindow *window = CTX_wm_window(C);
ARegion *ar = CTX_wm_region(C);
Paint *paint = BKE_paint_get_active_from_context(C);
PaintMode mode = BKE_paintmode_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
PaintStroke *stroke = op->customdata;
UnifiedPaintSettings *ups = stroke->ups;
float mouse_out[2];
PointerRNA itemptr;
float location[3];
@@ -315,8 +379,6 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float
copy_v2_v2(stroke->last_mouse_position, mouse_in);
stroke->last_pressure = pressure;
paint_brush_update(C, brush, mode, stroke, mouse_in, pressure);
{
float delta[2];
float factor = stroke->zoom_2d;
@@ -336,22 +398,13 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float
}
}
/* TODO: can remove the if statement once all modes have this */
if (stroke->get_location) {
if (!stroke->get_location(C, location, mouse_out)) {
if (paint_tool_require_location(brush, mode)) {
if (ar && (paint->flags & PAINT_SHOW_BRUSH))
WM_paint_cursor_tag_redraw(window, ar);
return;
}
}
if (!paint_brush_update(C, brush, mode, stroke, mouse_in, mouse_out, pressure, location)) {
return;
}
else
zero_v3(location);
/* Add to stroke */
RNA_collection_add(op->ptr, "stroke", &itemptr);
RNA_float_set(&itemptr, "size", ups->pixel_radius);
RNA_float_set_array(&itemptr, "location", location);
RNA_float_set_array(&itemptr, "mouse", mouse_out);
RNA_boolean_set(&itemptr, "pen_flip", stroke->pen_flip);
@@ -362,20 +415,12 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float
/* don't record this for now, it takes up a lot of memory when doing long
* strokes with small brush size, and operators have register disabled */
RNA_collection_clear(op->ptr, "stroke");
/* always redraw region if brush is shown */
if (ar && (paint->flags & PAINT_SHOW_BRUSH))
WM_paint_cursor_tag_redraw(window, ar);
}
/* Returns zero if no sculpt changes should be made, non-zero otherwise */
static int paint_smooth_stroke(PaintStroke *stroke, float output[2], float *outpressure,
const PaintSample *sample, PaintMode mode)
{
output[0] = sample->mouse[0];
output[1] = sample->mouse[1];
*outpressure = sample->pressure;
if (paint_supports_smooth_stroke(stroke->brush, mode)) {
float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d;
float u = stroke->brush->smooth_stroke_factor, v = 1.0f - u;
@@ -391,6 +436,11 @@ static int paint_smooth_stroke(PaintStroke *stroke, float output[2], float *outp
output[1] = sample->mouse[1] * v + stroke->last_mouse_position[1] * u;
*outpressure = sample->pressure * v + stroke->last_pressure * u;
}
else {
output[0] = sample->mouse[0];
output[1] = sample->mouse[1];
*outpressure = sample->pressure;
}
return 1;
}
@@ -413,6 +463,55 @@ static float paint_space_stroke_spacing(const Scene *scene, PaintStroke *stroke,
return max_ff(1.0, size_clamp * spacing / 50.0f);
}
static float paint_stroke_overlapped_curve(Brush *br, float x, float spacing)
{
int i;
const int n = 100 / spacing;
const float h = spacing / 50.0f;
const float x0 = x - 1;
float sum;
sum = 0;
for (i = 0; i < n; i++) {
float xx;
xx = fabs(x0 + i * h);
if (xx < 1.0f)
sum += BKE_brush_curve_strength(br, xx, 1);
}
return sum;
}
static float paint_stroke_integrate_overlap(Brush *br, float factor)
{
int i;
int m;
float g;
float max;
float spacing = br->spacing * factor;
if (!(br->flag & BRUSH_SPACE_ATTEN && (br->spacing < 100)))
return 1.0;
m = 10;
g = 1.0f / m;
max = 0;
for (i = 0; i < m; i++) {
float overlap = paint_stroke_overlapped_curve(br, i * g, spacing);
if (overlap > max)
max = overlap;
}
return 1.0f / max;
}
static float paint_space_stroke_spacing_variable(const Scene *scene, PaintStroke *stroke, float pressure, float dpressure, float length)
{
if (BKE_brush_use_size_pressure(scene, stroke->brush)) {
@@ -444,40 +543,42 @@ static int paint_space_stroke(bContext *C, wmOperator *op, const float final_mou
{
const Scene *scene = CTX_data_scene(C);
PaintStroke *stroke = op->customdata;
PaintMode mode = BKE_paintmode_get_active_from_context(C);
UnifiedPaintSettings *ups = stroke->ups;
int cnt = 0;
if (paint_space_stroke_enabled(stroke->brush, mode)) {
float pressure, dpressure;
float mouse[2], dmouse[2];
float length;
float pressure, dpressure;
float mouse[2], dmouse[2];
float length;
float no_pressure_spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
pressure = stroke->last_pressure;
dpressure = final_pressure - stroke->last_pressure;
pressure = stroke->last_pressure;
dpressure = final_pressure - stroke->last_pressure;
length = normalize_v2(dmouse);
length = normalize_v2(dmouse);
while (length > 0.0f) {
float spacing = paint_space_stroke_spacing_variable(scene, stroke, pressure, dpressure, length);
if (length >= spacing) {
mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing;
pressure = stroke->last_pressure + (spacing / length) * dpressure;
while (length > 0.0f) {
float spacing = paint_space_stroke_spacing_variable(scene, stroke, pressure, dpressure, length);
paint_brush_stroke_add_step(C, op, mouse, pressure);
if (length >= spacing) {
mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing;
pressure = stroke->last_pressure + (spacing / length) * dpressure;
length -= spacing;
pressure = stroke->last_pressure;
dpressure = final_pressure - stroke->last_pressure;
ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, spacing / no_pressure_spacing);
cnt++;
}
else {
break;
}
stroke->stroke_distance += spacing / stroke->zoom_2d;
paint_brush_stroke_add_step(C, op, mouse, pressure);
length -= spacing;
pressure = stroke->last_pressure;
dpressure = final_pressure - stroke->last_pressure;
cnt++;
}
else {
break;
}
}
@@ -487,6 +588,7 @@ static int paint_space_stroke(bContext *C, wmOperator *op, const float final_mou
/**** Public API ****/
PaintStroke *paint_stroke_new(bContext *C,
wmOperator *op,
StrokeGetLocation get_location,
StrokeTestStart test_start,
StrokeUpdateStep update_step,
@@ -497,6 +599,7 @@ PaintStroke *paint_stroke_new(bContext *C,
ToolSettings *toolsettings = CTX_data_tool_settings(C);
UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
Brush *br = stroke->brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
float zoomx, zoomy;
view3d_set_viewcontext(C, &stroke->vc);
if (stroke->vc.v3d)
@@ -510,6 +613,18 @@ PaintStroke *paint_stroke_new(bContext *C,
stroke->event_type = event_type; /* for modal, return event */
stroke->ups = ups;
get_imapaint_zoom(C, &zoomx, &zoomy);
stroke->zoom_2d = max_ff(zoomx, zoomy);
if ((br->flag & BRUSH_CURVE) &&
RNA_struct_property_is_set(op->ptr, "mode"))
{
RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL);
}
/* initialize here */
ups->overlap_factor = 1.0;
ups->stroke_active = true;
/* initialize here to avoid initialization conflict with threaded strokes */
curvemapping_initialize(br->curve);
@@ -521,8 +636,7 @@ PaintStroke *paint_stroke_new(bContext *C,
void paint_stroke_data_free(struct wmOperator *op)
{
BKE_paint_set_overlay_override(0);
MEM_freeN(op->customdata);
op->customdata = NULL;
MEM_SAFE_FREE(op->customdata);
}
static void stroke_done(struct bContext *C, struct wmOperator *op)
@@ -552,8 +666,10 @@ static void stroke_done(struct bContext *C, struct wmOperator *op)
stroke->timer);
}
if (stroke->smooth_stroke_cursor)
WM_paint_cursor_end(CTX_wm_manager(C), stroke->smooth_stroke_cursor);
if (stroke->stroke_cursor)
WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor);
BLI_freelistN(&stroke->line);
paint_stroke_data_free(op);
}
@@ -584,6 +700,16 @@ bool paint_supports_dynamic_size(Brush *br, PaintMode mode)
if (sculpt_is_grab_tool(br))
return false;
break;
case PAINT_TEXTURE_2D: /* fall through */
case PAINT_TEXTURE_PROJECTIVE:
if ((br->imagepaint_tool == PAINT_TOOL_FILL) &&
(br->flag & BRUSH_USE_GRADIENT))
{
return false;
}
break;
default:
break;
}
@@ -593,8 +719,7 @@ bool paint_supports_dynamic_size(Brush *br, PaintMode mode)
bool paint_supports_smooth_stroke(Brush *br, PaintMode mode)
{
if (!(br->flag & BRUSH_SMOOTH_STROKE) ||
(br->flag & BRUSH_ANCHORED) ||
(br->flag & BRUSH_DRAG_DOT))
(br->flag & (BRUSH_ANCHORED | BRUSH_DRAG_DOT | BRUSH_LINE)))
{
return false;
}
@@ -701,28 +826,141 @@ static void paint_stroke_sample_average(const PaintStroke *stroke,
/*printf("avg=(%f, %f), num=%d\n", average->mouse[0], average->mouse[1], stroke->num_samples);*/
}
/**
* Slightly different version of spacing for line/curve strokes,
* makes sure the dabs stay on the line path.
*/
static void paint_line_strokes_spacing(
bContext *C, wmOperator *op, PaintStroke *stroke, float spacing, float *length_residue,
const float old_pos[2], const float new_pos[2])
{
UnifiedPaintSettings *ups = stroke->ups;
float mouse[2], dmouse[2];
float length;
sub_v2_v2v2(dmouse, new_pos, old_pos);
copy_v2_v2(stroke->last_mouse_position, old_pos);
length = normalize_v2(dmouse);
BLI_assert(length >= 0.0f);
if (length == 0.0f)
return;
while (length > 0.0f) {
float spacing_final = spacing - *length_residue;
length += *length_residue;
*length_residue = 0.0;
if (length >= spacing) {
mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing_final;
mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing_final;
ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, 1.0);
stroke->stroke_distance += spacing / stroke->zoom_2d;
paint_brush_stroke_add_step(C, op, mouse, 1.0);
length -= spacing;
spacing_final = spacing;
}
else {
break;
}
}
*length_residue = length;
}
static void paint_stroke_line_end(bContext *C, wmOperator *op, PaintStroke *stroke, float mouse[2])
{
Brush *br = stroke->brush;
if (stroke->stroke_started && (br->flag & BRUSH_LINE)) {
stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
paint_brush_stroke_add_step(C, op, stroke->last_mouse_position, 1.0);
paint_space_stroke(C, op, mouse, 1.0);
}
}
static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *stroke)
{
Brush *br = stroke->brush;
if (br->flag & BRUSH_CURVE) {
const Scene *scene = CTX_data_scene(C);
const float spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
PaintCurve *pc = br->paint_curve;
PaintCurvePoint *pcp;
float length_residue = 0.0f;
int i;
if (!pc)
return true;
pcp = pc->points;
stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
for (i = 0; i < pc->tot_points - 1; i++, pcp++) {
int j;
float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
PaintCurvePoint *pcp_next = pcp + 1;
for (j = 0; j < 2; j++)
BKE_curve_forward_diff_bezier(
pcp->bez.vec[1][j],
pcp->bez.vec[2][j],
pcp_next->bez.vec[0][j],
pcp_next->bez.vec[1][j],
data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
for (j = 0; j < PAINT_CURVE_NUM_SEGMENTS; j++) {
if (!stroke->stroke_started) {
stroke->last_pressure = 1.0;
copy_v2_v2(stroke->last_mouse_position, data + 2 * j);
stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position);
if (stroke->stroke_started) {
paint_brush_stroke_add_step(C, op, data + 2 * j, 1.0);
paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
}
}
else {
paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
}
}
}
stroke_done(C, op);
return true;
}
return false;
}
int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Paint *p = BKE_paint_get_active_from_context(C);
PaintMode mode = BKE_paintmode_get_active_from_context(C);
PaintStroke *stroke = op->customdata;
Brush *br = stroke->brush;
PaintSample sample_average;
float mouse[2];
bool first_dab = false;
bool first_modal = false;
float zoomx, zoomy;
bool redraw = false;
float pressure;
/* see if tablet affects event */
pressure = WM_event_tablet_data(event, &stroke->pen_flip, NULL);
/* see if tablet affects event. Line, anchored and drag dot strokes do not support pressure */
pressure = (br->flag & (BRUSH_LINE | BRUSH_ANCHORED | BRUSH_DRAG_DOT)) ? 1.0f : WM_event_tablet_data(event, &stroke->pen_flip, NULL);
paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure);
paint_stroke_sample_average(stroke, &sample_average);
get_imapaint_zoom(C, &zoomx, &zoomy);
stroke->zoom_2d = max_ff(zoomx, zoomy);
/* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously!
* this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it
* since the 2D deltas are zero -- code in this file needs to be updated to use the
@@ -732,8 +970,12 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* one time initialization */
if (!stroke->stroke_init) {
stroke->smooth_stroke_cursor =
WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_smooth_stroke, stroke);
if (paint_stroke_curve_end(C, op, stroke))
return OPERATOR_FINISHED;
if (paint_supports_smooth_stroke(br, mode))
stroke->stroke_cursor =
WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_smooth_cursor, stroke);
stroke->stroke_init = true;
first_modal = true;
@@ -747,9 +989,14 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */
if (stroke->stroke_started) {
if (stroke->brush->flag & BRUSH_AIRBRUSH)
if (br->flag & BRUSH_AIRBRUSH)
stroke->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, stroke->brush->rate);
if (br->flag & BRUSH_LINE) {
stroke->stroke_cursor =
WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_line_cursor, stroke);
}
first_dab = true;
}
}
@@ -765,20 +1012,42 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
if (event->type == stroke->event_type && event->val == KM_RELEASE && !first_modal) {
if (event->type == stroke->event_type && !first_modal) {
if (event->val == KM_RELEASE) {
paint_stroke_line_end (C, op, stroke, sample_average.mouse);
stroke_done(C, op);
return OPERATOR_FINISHED;
}
}
else if (ELEM(event->type, RETKEY, SPACEKEY)) {
paint_stroke_line_end(C, op, stroke, sample_average.mouse);
stroke_done(C, op);
return OPERATOR_FINISHED;
}
else if (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) ||
(event->type == TIMER && (event->customdata == stroke->timer)) )
else if ((br->flag & BRUSH_LINE) && stroke->stroke_started &&
(first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))))
{
if (br->flag & BRUSH_RAKE) {
copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position);
paint_calculate_rake_rotation(stroke->ups, sample_average.mouse);
}
}
else if (first_modal ||
/* regular dabs */
(!(br->flag & (BRUSH_AIRBRUSH)) && (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))) ||
/* airbrush */
((br->flag & BRUSH_AIRBRUSH) && event->type == TIMER && event->customdata == stroke->timer))
{
if (paint_smooth_stroke(stroke, mouse, &pressure, &sample_average, mode)) {
if (stroke->stroke_started) {
if (paint_space_stroke_enabled(stroke->brush, mode)) {
if (paint_space_stroke_enabled(br, mode)) {
if (paint_space_stroke(C, op, mouse, pressure))
redraw = true;
}
else {
float dmouse[2];
sub_v2_v2v2(dmouse, mouse, stroke->last_mouse_position);
stroke->stroke_distance += len_v2(dmouse);
paint_brush_stroke_add_step(C, op, mouse, pressure);
redraw = true;
}
@@ -789,19 +1058,27 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* we want the stroke to have the first daub at the start location
* instead of waiting till we have moved the space distance */
if (first_dab &&
paint_space_stroke_enabled(stroke->brush, mode) &&
!(stroke->brush->flag & BRUSH_ANCHORED) &&
!(stroke->brush->flag & BRUSH_SMOOTH_STROKE))
paint_space_stroke_enabled(br, mode) &&
!(br->flag & BRUSH_SMOOTH_STROKE))
{
paint_brush_stroke_add_step(C, op, mouse, pressure);
stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
paint_brush_stroke_add_step(C, op, sample_average.mouse, sample_average.pressure);
redraw = true;
}
/* do updates for redraw. if event is inbetween mousemove there are more
* coming, so postpone potentially slow redraw updates until all are done */
if (event->type != INBETWEEN_MOUSEMOVE)
if (event->type != INBETWEEN_MOUSEMOVE) {
wmWindow *window = CTX_wm_window(C);
ARegion *ar = CTX_wm_region(C);
/* At the very least, invalidate the cursor */
if (ar && (p->flags & PAINT_SHOW_BRUSH))
WM_paint_cursor_tag_redraw(window, ar);
if (redraw && stroke->redraw)
stroke->redraw(C, stroke, false);
}
return OPERATOR_RUNNING_MODAL;
}
@@ -843,6 +1120,11 @@ void *paint_stroke_mode_data(struct PaintStroke *stroke)
return stroke->mode_data;
}
float paint_stroke_distance_get(struct PaintStroke *stroke)
{
return stroke->stroke_distance;
}
void paint_stroke_set_mode_data(PaintStroke *stroke, void *mode_data)
{
stroke->mode_data = mode_data;
@@ -856,6 +1138,6 @@ int paint_poll(bContext *C)
ARegion *ar = CTX_wm_region(C);
return p && ob && BKE_paint_brush(p) &&
(sa && sa->spacetype == SPACE_VIEW3D) &&
(sa && ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) &&
(ar && ar->regiontype == RGN_TYPE_WINDOW);
}
@@ -51,19 +51,17 @@ typedef struct UndoElem {
UndoRestoreCb restore;
UndoFreeCb free;
UndoCleanupCb cleanup;
} UndoElem;
typedef bool (*UndoCleanupCb)(struct bContext *C, ListBase *lb);
typedef struct UndoStack {
int type;
ListBase elems;
UndoElem *current;
UndoCleanupCb cleanup;
} UndoStack;
static UndoStack ImageUndoStack = {UNDO_PAINT_IMAGE, {NULL, NULL}, NULL, NULL};
static UndoStack MeshUndoStack = {UNDO_PAINT_MESH, {NULL, NULL}, NULL, sculpt_undo_cleanup};
static UndoStack ImageUndoStack = {UNDO_PAINT_IMAGE, {NULL, NULL}, NULL};
static UndoStack MeshUndoStack = {UNDO_PAINT_MESH, {NULL, NULL}, NULL};
/* Generic */
@@ -81,7 +79,7 @@ static void undo_elem_free(UndoStack *UNUSED(stack), UndoElem *uel)
}
}
static void undo_stack_push_begin(UndoStack *stack, const char *name, UndoRestoreCb restore, UndoFreeCb free)
static void undo_stack_push_begin(UndoStack *stack, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup)
{
UndoElem *uel;
int nr;
@@ -101,6 +99,7 @@ static void undo_stack_push_begin(UndoStack *stack, const char *name, UndoRestor
stack->current = uel = MEM_callocN(sizeof(UndoElem), "undo file");
uel->restore = restore;
uel->free = free;
uel->cleanup = cleanup;
BLI_addtail(&stack->elems, uel);
/* name can be a dynamic string */
@@ -179,25 +178,24 @@ static void undo_stack_cleanup(UndoStack *stack, bContext *C)
UndoElem *uel = stack->elems.first;
bool stack_reset = false;
if (stack->cleanup) {
while (uel) {
if (stack->cleanup(C, &uel->elems)) {
UndoElem *uel_tmp = uel->next;
if (stack->current == uel) {
stack->current = NULL;
stack_reset = true;
}
undo_elem_free(stack, uel);
BLI_freelinkN(&stack->elems, uel);
uel = uel_tmp;
while (uel) {
if (uel->cleanup && uel->cleanup(C, &uel->elems)) {
UndoElem *uel_tmp = uel->next;
if (stack->current == uel) {
stack->current = NULL;
stack_reset = true;
}
else
uel = uel->next;
}
if (stack_reset) {
stack->current = stack->elems.last;
undo_elem_free(stack, uel);
BLI_freelinkN(&stack->elems, uel);
uel = uel_tmp;
}
else
uel = uel->next;
}
if (stack_reset) {
stack->current = stack->elems.last;
}
}
static int undo_stack_step(bContext *C, UndoStack *stack, int step, const char *name)
@@ -255,23 +253,25 @@ static void undo_stack_free(UndoStack *stack)
/* Exported Functions */
void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free)
void ED_undo_paint_push_begin(int type, const char *name, UndoRestoreCb restore, UndoFreeCb free, UndoCleanupCb cleanup)
{
if (type == UNDO_PAINT_IMAGE)
undo_stack_push_begin(&ImageUndoStack, name, restore, free);
undo_stack_push_begin(&ImageUndoStack, name, restore, free, cleanup);
else if (type == UNDO_PAINT_MESH)
undo_stack_push_begin(&MeshUndoStack, name, restore, free);
undo_stack_push_begin(&MeshUndoStack, name, restore, free, cleanup);
}
ListBase *undo_paint_push_get_list(int type)
{
if (type == UNDO_PAINT_IMAGE) {
if (ImageUndoStack.current)
if (ImageUndoStack.current) {
return &ImageUndoStack.current->elems;
}
}
else if (type == UNDO_PAINT_MESH) {
if (MeshUndoStack.current)
if (MeshUndoStack.current) {
return &MeshUndoStack.current->elems;
}
}
return NULL;
+286 -10
View File
@@ -35,23 +35,28 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_material_types.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "BLI_math.h"
#include "BLI_math_color.h"
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_rect.h"
#include "BLF_translation.h"
#include "BKE_scene.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_DerivedMesh.h"
#include "BKE_material.h"
#include "BKE_image.h"
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_image.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -67,6 +72,10 @@
#include "ED_view3d.h"
#include "ED_screen.h"
#include "ED_uvedit.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "BLI_sys_types.h"
#include "ED_mesh.h" /* for face mask functions */
@@ -205,6 +214,175 @@ void paint_get_tex_pixel_col(MTex *mtex, float u, float v, float rgba[4], struct
CLAMP(rgba[3], 0.0f, 1.0f);
}
/* 3D Paint */
static void imapaint_project(float matrix[4][4], const float co[3], float pco[4])
{
copy_v3_v3(pco, co);
pco[3] = 1.0f;
mul_m4_v4(matrix, pco);
}
static void imapaint_tri_weights(float matrix[4][4], GLint view[4],
const float v1[3], const float v2[3], const float v3[3],
const float co[2], float w[3])
{
float pv1[4], pv2[4], pv3[4], h[3], divw;
float wmat[3][3], invwmat[3][3];
/* compute barycentric coordinates */
/* project the verts */
imapaint_project(matrix, v1, pv1);
imapaint_project(matrix, v2, pv2);
imapaint_project(matrix, v3, pv3);
/* do inverse view mapping, see gluProject man page */
h[0] = (co[0] - view[0]) * 2.0f / view[2] - 1.0f;
h[1] = (co[1] - view[1]) * 2.0f / view[3] - 1.0f;
h[2] = 1.0f;
/* solve for (w1,w2,w3)/perspdiv in:
* h * perspdiv = Project * Model * (w1 * v1 + w2 * v2 + w3 * v3) */
wmat[0][0] = pv1[0]; wmat[1][0] = pv2[0]; wmat[2][0] = pv3[0];
wmat[0][1] = pv1[1]; wmat[1][1] = pv2[1]; wmat[2][1] = pv3[1];
wmat[0][2] = pv1[3]; wmat[1][2] = pv2[3]; wmat[2][2] = pv3[3];
invert_m3_m3(invwmat, wmat);
mul_m3_v3(invwmat, h);
copy_v3_v3(w, h);
/* w is still divided by perspdiv, make it sum to one */
divw = w[0] + w[1] + w[2];
if (divw != 0.0f) {
mul_v3_fl(w, 1.0f / divw);
}
}
/* compute uv coordinates of mouse in face */
static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, const int xy[2], float uv[2])
{
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
MTFace *tf_base, *tf;
Material *ma;
TexPaintSlot *slot;
int numfaces = dm->getNumTessFaces(dm), a, findex;
float p[2], w[3], absw, minabsw;
MFace mf;
MVert mv[4];
float matrix[4][4], proj[4][4];
GLint view[4];
/* compute barycentric coordinates */
/* double lookup */
const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
if (index_mf_to_mpoly == NULL) {
index_mp_to_orig = NULL;
}
/* get the needed opengl matrices */
glGetIntegerv(GL_VIEWPORT, view);
glGetFloatv(GL_MODELVIEW_MATRIX, (float *)matrix);
glGetFloatv(GL_PROJECTION_MATRIX, (float *)proj);
view[0] = view[1] = 0;
mul_m4_m4m4(matrix, matrix, ob->obmat);
mul_m4_m4m4(matrix, proj, matrix);
minabsw = 1e10;
uv[0] = uv[1] = 0.0;
/* test all faces in the derivedmesh with the original index of the picked face */
for (a = 0; a < numfaces; a++) {
findex = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
if (findex == faceindex) {
dm->getTessFace(dm, a, &mf);
ma = dm->mat[mf.mat_nr];
slot = &ma->texpaintslot[ma->paint_active_slot];
dm->getVert(dm, mf.v1, &mv[0]);
dm->getVert(dm, mf.v2, &mv[1]);
dm->getVert(dm, mf.v3, &mv[2]);
if (mf.v4)
dm->getVert(dm, mf.v4, &mv[3]);
if (!slot->uvname[0] || !(tf_base = CustomData_get_layer_named(&dm->faceData, CD_MTFACE, slot->uvname)))
tf_base = CustomData_get_layer(&dm->faceData, CD_MTFACE);
tf = &tf_base[a];
p[0] = xy[0];
p[1] = xy[1];
if (mf.v4) {
/* the triangle with the largest absolute values is the one
* with the most negative weights */
imapaint_tri_weights(matrix, view, mv[0].co, mv[1].co, mv[3].co, p, w);
absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
if (absw < minabsw) {
uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[3][0] * w[2];
uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[3][1] * w[2];
minabsw = absw;
}
imapaint_tri_weights(matrix, view, mv[1].co, mv[2].co, mv[3].co, p, w);
absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
if (absw < minabsw) {
uv[0] = tf->uv[1][0] * w[0] + tf->uv[2][0] * w[1] + tf->uv[3][0] * w[2];
uv[1] = tf->uv[1][1] * w[0] + tf->uv[2][1] * w[1] + tf->uv[3][1] * w[2];
minabsw = absw;
}
}
else {
imapaint_tri_weights(matrix, view, mv[0].co, mv[1].co, mv[2].co, p, w);
absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
if (absw < minabsw) {
uv[0] = tf->uv[0][0] * w[0] + tf->uv[1][0] * w[1] + tf->uv[2][0] * w[2];
uv[1] = tf->uv[0][1] * w[0] + tf->uv[1][1] * w[1] + tf->uv[2][1] * w[2];
minabsw = absw;
}
}
}
}
dm->release(dm);
}
/* returns 0 if not found, otherwise 1 */
static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *r_index, unsigned int totface)
{
if (totface == 0)
return 0;
/* sample only on the exact position */
*r_index = view3d_sample_backbuf(vc, mval[0], mval[1]);
if ((*r_index) == 0 || (*r_index) > (unsigned int)totface) {
return 0;
}
(*r_index)--;
return 1;
}
static Image *imapaint_face_image(DerivedMesh *dm, int face_index)
{
Image *ima;
MFace *mf = dm->getTessFaceArray(dm) + face_index;
Material *ma = dm->mat[mf->mat_nr];
ima = ma->texpaintslot[ma->paint_active_slot].ima;
return ima;
}
/* Uses symm to selectively flip any axis of a coordinate. */
void flip_v3_v3(float out[3], const float in[3], const char symm)
{
@@ -223,25 +401,123 @@ void flip_v3_v3(float out[3], const float in[3], const char symm)
}
/* used for both 3d view and image window */
void paint_sample_color(const bContext *C, ARegion *ar, int x, int y) /* frontbuf */
void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_proj, bool use_palette)
{
Scene *scene = CTX_data_scene(C);
Paint *paint = BKE_paint_get_active_from_context(C);
Palette *palette = BKE_paint_palette(paint);
PaletteColor *color;
Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
unsigned int col;
const char *cp;
const unsigned char *cp;
CLAMP(x, 0, ar->winx);
CLAMP(y, 0, ar->winy);
glReadBuffer(GL_FRONT);
glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
glReadBuffer(GL_BACK);
if (use_palette) {
if (!palette) {
palette = BKE_palette_add(CTX_data_main(C), "Palette");
BKE_paint_palette_set(paint, palette);
}
cp = (char *)&col;
color = BKE_palette_color_add(palette);
}
if (CTX_wm_view3d(C) && texpaint_proj) {
/* first try getting a colour directly from the mesh faces if possible */
Object *ob = OBACT;
bool sample_success = false;
if (ob) {
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
ViewContext vc;
const int mval[2] = {x, y};
unsigned int faceindex;
unsigned int totface = dm->getNumTessFaces(dm);
MTFace *dm_mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);
DM_update_materials(dm, ob);
if (dm_mtface) {
view3d_set_viewcontext(C, &vc);
view3d_operator_needs_opengl(C);
if (imapaint_pick_face(&vc, mval, &faceindex, totface)) {
Image *image = imapaint_face_image(dm, faceindex);
ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
if (ibuf && ibuf->rect) {
float uv[2];
float u, v;
imapaint_pick_uv(scene, ob, faceindex, mval, uv);
sample_success = true;
u = fmodf(uv[0], 1.0f);
v = fmodf(uv[1], 1.0f);
if (u < 0.0f) u += 1.0f;
if (v < 0.0f) v += 1.0f;
u = u * ibuf->x - 0.5f;
v = v * ibuf->y - 0.5f;
if (ibuf->rect_float) {
float rgba_f[4];
bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
straight_to_premul_v4(rgba_f);
if (use_palette) {
linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
}
else {
linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
BKE_brush_color_set(scene, br, rgba_f);
}
}
else {
unsigned char rgba[4];
bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
if (use_palette) {
rgb_uchar_to_float(color->rgb, rgba);
}
else {
float rgba_f[3];
rgb_uchar_to_float(rgba_f, rgba);
BKE_brush_color_set(scene, br, rgba_f);
}
}
}
BKE_image_release_ibuf(image, ibuf, NULL);
}
}
dm->release(dm);
}
if (!sample_success) {
glReadBuffer(GL_FRONT);
glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
glReadBuffer(GL_BACK);
}
else
return;
}
else {
glReadBuffer(GL_FRONT);
glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
glReadBuffer(GL_BACK);
}
cp = (unsigned char *)&col;
if (br) {
br->rgb[0] = cp[0] / 255.0f;
br->rgb[1] = cp[1] / 255.0f;
br->rgb[2] = cp[2] / 255.0f;
if (use_palette) {
rgb_uchar_to_float(color->rgb, cp);
}
else {
float rgba_f[3];
rgb_uchar_to_float(rgba_f, cp);
BKE_brush_color_set(scene, br, rgba_f);
}
}
@@ -197,11 +197,11 @@ static int *get_indexarray(Mesh *me)
return MEM_mallocN(sizeof(int) * (me->totpoly + 1), "vertexpaint");
}
unsigned int vpaint_get_current_col(VPaint *vp)
unsigned int vpaint_get_current_col(Scene *scene, VPaint *vp)
{
Brush *brush = BKE_paint_brush(&vp->paint);
unsigned char col[4];
rgb_float_to_uchar(col, brush->rgb);
rgb_float_to_uchar(col, BKE_brush_color_get(scene, brush));
col[3] = 255; /* alpha isn't used, could even be removed to speedup paint a little */
return *(unsigned int *)col;
}
@@ -2547,14 +2547,17 @@ static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int retval;
op->customdata = paint_stroke_new(C, NULL, wpaint_stroke_test_start,
op->customdata = paint_stroke_new(C, op, NULL, wpaint_stroke_test_start,
wpaint_stroke_update_step, NULL,
wpaint_stroke_done, event->type);
if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
paint_stroke_data_free(op);
return OPERATOR_FINISHED;
}
/* add modal handler */
WM_event_add_modal_handler(C, op);
retval = op->type->modal(C, op, event);
OPERATOR_RETVAL_CHECK(retval);
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
@@ -2563,7 +2566,7 @@ static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int wpaint_exec(bContext *C, wmOperator *op)
{
op->customdata = paint_stroke_new(C, NULL, wpaint_stroke_test_start,
op->customdata = paint_stroke_new(C, op, NULL, wpaint_stroke_test_start,
wpaint_stroke_update_step, NULL,
wpaint_stroke_done, 0);
@@ -2778,7 +2781,8 @@ static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me)
static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float UNUSED(mouse[2]))
{
ToolSettings *ts = CTX_data_tool_settings(C);
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
struct PaintStroke *stroke = op->customdata;
VPaint *vp = ts->vpaint;
Brush *brush = BKE_paint_brush(&vp->paint);
@@ -2810,7 +2814,7 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
vpd->vp_handle = ED_vpaint_proj_handle_create(vpd->vc.scene, ob, &vpd->vertexcosnos);
vpd->indexar = get_indexarray(me);
vpd->paintcol = vpaint_get_current_col(vp);
vpd->paintcol = vpaint_get_current_col(scene, vp);
vpd->is_texbrush = !(brush->vertexpaint_tool == PAINT_BLEND_BLUR) &&
brush->mtex.tex;
@@ -3062,14 +3066,18 @@ static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int retval;
op->customdata = paint_stroke_new(C, NULL, vpaint_stroke_test_start,
op->customdata = paint_stroke_new(C, op, NULL, vpaint_stroke_test_start,
vpaint_stroke_update_step, NULL,
vpaint_stroke_done, event->type);
if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
paint_stroke_data_free(op);
return OPERATOR_FINISHED;
}
/* add modal handler */
WM_event_add_modal_handler(C, op);
retval = op->type->modal(C, op, event);
OPERATOR_RETVAL_CHECK(retval);
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
@@ -3078,7 +3086,7 @@ static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int vpaint_exec(bContext *C, wmOperator *op)
{
op->customdata = paint_stroke_new(C, NULL, vpaint_stroke_test_start,
op->customdata = paint_stroke_new(C, op, NULL, vpaint_stroke_test_start,
vpaint_stroke_update_step, NULL,
vpaint_stroke_done, 0);
+22 -69
View File
@@ -663,47 +663,6 @@ static bool sculpt_brush_test_cyl(SculptBrushTest *test, float co[3], float loca
/* ===== Sculpting =====
*
*/
static float overlapped_curve(Brush *br, float x)
{
int i;
const int n = 100 / br->spacing;
const float h = br->spacing / 50.0f;
const float x0 = x - 1;
float sum;
sum = 0;
for (i = 0; i < n; i++) {
float xx;
xx = fabsf(x0 + i * h);
if (xx < 1.0f)
sum += BKE_brush_curve_strength(br, xx, 1);
}
return sum;
}
static float integrate_overlap(Brush *br)
{
int i;
int m = 10;
float g = 1.0f / m;
float max;
max = 0;
for (i = 0; i < m; i++) {
float overlap = overlapped_curve(br, i * g);
if (overlap > max)
max = overlap;
}
return max;
}
static void flip_v3(float v[3], const char symm)
{
flip_v3_v3(v, v, symm);
@@ -776,7 +735,7 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
/* Return modified brush strength. Includes the direction of the brush, positive
* values pull vertices, negative values push. Uses tablet pressure and a
* special multiplier found experimentally to scale the strength factor. */
static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather)
static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather, UnifiedPaintSettings *ups)
{
const Scene *scene = cache->vc->scene;
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -788,13 +747,10 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather)
float pressure = BKE_brush_use_alpha_pressure(scene, brush) ? cache->pressure : 1;
float pen_flip = cache->pen_flip ? -1 : 1;
float invert = cache->invert ? -1 : 1;
float accum = integrate_overlap(brush);
float overlap = ups->overlap_factor;
/* spacing is integer percentage of radius, divide by 50 to get
* normalized diameter */
float overlap = (brush->flag & BRUSH_SPACE_ATTEN &&
brush->flag & BRUSH_SPACE &&
!(brush->flag & BRUSH_ANCHORED) &&
(brush->spacing < 100)) ? 1.0f / accum : 1;
float flip = dir * invert * pen_flip;
switch (brush->sculpt_tool) {
@@ -3377,7 +3333,7 @@ static void calc_brushdata_symm(Sculpt *sd, StrokeCache *cache, const char symm,
/* XXX This reduces the length of the grab delta if it approaches the line of symmetry
* XXX However, a different approach appears to be needed */
#if 0
if (sd->flags & SCULPT_SYMMETRY_FEATHER) {
if (sd->paint.symmetry_flags & SCULPT_SYMMETRY_FEATHER) {
float frac = 1.0f / max_overlap_count(sd);
float reduce = (feather - frac) / (1 - frac);
@@ -3437,7 +3393,7 @@ static void sculpt_fix_noise_tear(Sculpt *sd, Object *ob)
}
static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob,
BrushActionFunc action)
BrushActionFunc action, UnifiedPaintSettings *ups)
{
Brush *brush = BKE_paint_brush(&sd->paint);
SculptSession *ss = ob->sculpt;
@@ -3447,7 +3403,7 @@ static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob,
float feather = calc_symmetry_feather(sd, ss->cache);
cache->bstrength = brush_strength(sd, cache, feather);
cache->bstrength = brush_strength(sd, cache, feather, ups);
cache->symmetry = symm;
/* symm is a bit combination of XYZ - 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
@@ -3733,8 +3689,8 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio
/* not very nice, but with current events system implementation
* we can't handle brush appearance inversion hotkey separately (sergey) */
if (cache->invert) brush->flag |= BRUSH_INVERTED;
else brush->flag &= ~BRUSH_INVERTED;
if (cache->invert) ups->draw_inverted = true;
else ups->draw_inverted = false;
/* Alt-Smooth */
if (cache->alt_smooth) {
@@ -3992,16 +3948,9 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob,
cache->radius_squared = cache->radius * cache->radius;
if (brush->flag & BRUSH_ANCHORED) {
/* true location has been calculated as part of the stroke system already here */
if (brush->flag & BRUSH_EDGE_TO_EDGE) {
float halfway[2];
float out[3];
halfway[0] = 0.5f * (cache->mouse[0] + cache->initial_mouse[0]);
halfway[1] = 0.5f * (cache->mouse[1] + cache->initial_mouse[1]);
if (sculpt_stroke_get_location(C, out, halfway)) {
copy_v3_v3(cache->anchored_location, out);
copy_v3_v3(cache->true_location, cache->anchored_location);
}
RNA_float_get_array(ptr, "location", cache->true_location);
}
cache->radius = paint_calc_object_space_radius(cache->vc,
@@ -4393,10 +4342,10 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *UNUSED(st
}
if (sculpt_stroke_dynamic_topology(ss, brush)) {
do_symmetrical_brush_actions(sd, ob, sculpt_topology_update);
do_symmetrical_brush_actions(sd, ob, sculpt_topology_update, ups);
}
do_symmetrical_brush_actions(sd, ob, do_brush_action);
do_symmetrical_brush_actions(sd, ob, do_brush_action, ups);
sculpt_combine_proxies(sd, ob);
@@ -4446,8 +4395,9 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
/* Finished */
if (ss->cache) {
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
Brush *brush = BKE_paint_brush(&sd->paint);
brush->flag &= ~BRUSH_INVERTED;
ups->draw_inverted = false;
sculpt_stroke_modifiers_check(C, ob);
@@ -4506,7 +4456,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
if (!sculpt_brush_stroke_init(C, op))
return OPERATOR_CANCELLED;
stroke = paint_stroke_new(C, sculpt_stroke_get_location,
stroke = paint_stroke_new(C, op, sculpt_stroke_get_location,
sculpt_stroke_test_start,
sculpt_stroke_update_step, NULL,
sculpt_stroke_done, event->type);
@@ -4521,10 +4471,13 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_PASS_THROUGH;
}
if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
paint_stroke_data_free(op);
return OPERATOR_FINISHED;
}
/* add modal handler */
WM_event_add_modal_handler(C, op);
retval = op->type->modal(C, op, event);
OPERATOR_RETVAL_CHECK(retval);
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
@@ -4536,7 +4489,7 @@ static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
if (!sculpt_brush_stroke_init(C, op))
return OPERATOR_CANCELLED;
op->customdata = paint_stroke_new(C, sculpt_stroke_get_location, sculpt_stroke_test_start,
op->customdata = paint_stroke_new(C, op, sculpt_stroke_get_location, sculpt_stroke_test_start,
sculpt_stroke_update_step, NULL, sculpt_stroke_done, 0);
/* frees op->customdata */
@@ -5062,11 +5015,11 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
ts->sculpt->paint.flags |= PAINT_SHOW_BRUSH;
/* Make sure at least dyntopo subdivision is enabled */
ts->sculpt->flags |= SCULPT_DYNTOPO_SUBDIVIDE;
ts->sculpt->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE;
}
if (!ts->sculpt->detail_size) {
ts->sculpt->detail_size = 30;
ts->sculpt->detail_size = 12;
}
if (ts->sculpt->constant_detail == 0.0f)
@@ -543,7 +543,7 @@ static void sculpt_undo_free(ListBase *lb)
}
}
bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
static bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
{
Object *ob = CTX_data_active_object(C);
SculptUndoNode *unode;
@@ -551,10 +551,8 @@ bool sculpt_undo_cleanup(bContext *C, ListBase *lb)
unode = lb->first;
if (unode && strcmp(unode->idname, ob->id.name) != 0) {
for (unode = lb->first; unode; unode = unode->next) {
if (unode->bm_entry)
BM_log_cleanup_entry(unode->bm_entry);
}
if (unode->bm_entry)
BM_log_cleanup_entry(unode->bm_entry);
return true;
}
@@ -881,7 +879,7 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
void sculpt_undo_push_begin(const char *name)
{
ED_undo_paint_push_begin(UNDO_PAINT_MESH, name,
sculpt_undo_restore, sculpt_undo_free);
sculpt_undo_restore, sculpt_undo_free, sculpt_undo_cleanup);
}
void sculpt_undo_push_end(void)
@@ -144,6 +144,7 @@ void ED_spacetypes_init(void)
ED_operatormacros_curve();
ED_operatormacros_mask();
ED_operatormacros_sequencer();
ED_operatormacros_paint();
/* register dropboxes (can use macros) */
spacetypes = BKE_spacetypes_list();
@@ -28,6 +28,7 @@
* \ingroup spimage
*/
#include "DNA_brush_types.h"
#include "DNA_mask_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -297,44 +298,51 @@ bool ED_space_image_show_render(SpaceImage *sima)
bool ED_space_image_show_paint(SpaceImage *sima)
{
if (ED_space_image_show_render(sima))
return 0;
return false;
return (sima->mode == SI_MODE_PAINT);
}
bool ED_space_image_show_texpaint(SpaceImage *sima, Object *ob)
{
return (ob && ob->type == OB_MESH &&
ob->mode == OB_MODE_TEXTURE_PAINT &&
!(sima->flag & SI_NO_DRAW_TEXPAINT));
}
bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
{
if (sima && (ED_space_image_show_render(sima) || ED_space_image_show_paint(sima)))
return 0;
return false;
if (obedit && obedit->type == OB_MESH) {
struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
int ret;
bool ret;
ret = EDBM_mtexpoly_check(em);
return ret;
}
return 0;
return false;
}
bool ED_space_image_show_uvshadow(SpaceImage *sima, Object *obedit)
{
if (ED_space_image_show_render(sima))
return 0;
return false;
if (ED_space_image_show_paint(sima))
if (obedit && obedit->type == OB_MESH) {
struct BMEditMesh *em = BKE_editmesh_from_object(obedit);
int ret;
bool ret;
ret = EDBM_mtexpoly_check(em);
return ret;
return ret && !(sima->flag & SI_NO_DRAW_TEXPAINT);
}
return 0;
return false;
}
/* matches clip function */
@@ -361,6 +369,21 @@ int ED_space_image_maskedit_poll(bContext *C)
return false;
}
bool ED_space_image_paint_curve(const bContext *C)
{
SpaceImage *sima = CTX_wm_space_image(C);
if (sima && sima->mode == SI_MODE_PAINT) {
Brush *br = CTX_data_tool_settings(C)->imapaint.paint.brush;
if (br && (br->flag & BRUSH_CURVE))
return true;
}
return false;
}
int ED_space_image_maskedit_mask_poll(bContext *C)
{
if (ED_space_image_maskedit_poll(C)) {
+10 -1
View File
@@ -1896,6 +1896,7 @@ static int image_new_exec(bContext *C, wmOperator *op)
SpaceImage *sima;
Scene *scene;
Object *obedit;
Object *ob;
Image *ima;
Main *bmain;
PointerRNA ptr, idptr;
@@ -1910,6 +1911,7 @@ static int image_new_exec(bContext *C, wmOperator *op)
scene = CTX_data_scene(C);
obedit = CTX_data_edit_object(C);
bmain = CTX_data_main(C);
ob = OBACT;
prop = RNA_struct_find_property(op->ptr, "name");
RNA_property_string_get(op->ptr, prop, name);
@@ -1955,6 +1957,13 @@ static int image_new_exec(bContext *C, wmOperator *op)
tex->ima = ima;
ED_area_tag_redraw(CTX_wm_area(C));
}
else if (ob && ob->mode == OB_MODE_TEXTURE_PAINT) {
ImagePaintSettings *imapaint = &(CTX_data_tool_settings(C)->imapaint);
if (imapaint->stencil)
id_us_min(&imapaint->stencil->id);
imapaint->stencil = ima;
}
}
BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE);
@@ -2037,7 +2046,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
if (support_undo) {
ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
ED_image_undo_restore, ED_image_undo_free);
ED_image_undo_restore, ED_image_undo_free, NULL);
/* not strictly needed, because we only imapaint_dirty_region to invalidate all tiles
* but better do this right in case someone copies this for a tool that uses partial redraw better */
ED_imapaint_clear_partial_redraw();
@@ -633,6 +633,12 @@ static void image_main_area_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
/* image paint polls for mode */
keymap = WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
keymap = WM_keymap_find(wm->defaultconf, "Paint Curve", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
keymap = WM_keymap_find(wm->defaultconf, "Image Paint", 0, 0);
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
@@ -657,6 +663,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
Object *obact = CTX_data_active_object(C);
Object *obedit = CTX_data_edit_object(C);
Mask *mask = NULL;
bool curve = false;
Scene *scene = CTX_data_scene(C);
View2D *v2d = &ar->v2d;
//View2DScrollers *scrollers;
@@ -702,6 +709,9 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
else if (sima->mode == SI_MODE_MASK) {
mask = ED_space_image_get_mask(sima);
}
else if (ED_space_image_paint_curve(C)) {
curve = true;
}
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
@@ -753,6 +763,11 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
draw_image_cursor(ar, sima->cursor);
UI_view2d_view_restore(C);
}
else if (curve) {
UI_view2d_view_ortho(v2d);
draw_image_cursor(ar, sima->cursor);
UI_view2d_view_restore(C);
}
draw_image_cache(C, ar);
+89 -17
View File
@@ -212,12 +212,16 @@ static Material *give_current_material_or_def(Object *ob, int matnr)
static struct TextureDrawState {
Object *ob;
Image *stencil;
bool stencil_invert;
bool use_game_mat;
int is_lit, is_tex;
int color_profile;
bool use_backface_culling;
unsigned char obcol[4];
} Gtexdraw = {NULL, false, 0, 0, 0, false, {0, 0, 0, 0}};
float stencil_col[4];
bool is_texpaint;
} Gtexdraw = {NULL, NULL, false, false, 0, 0, 0, false, {0, 0, 0, 0}, {0.0f, 0.0f, 0.0f, 1.0f}, false};
static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw)
{
@@ -229,13 +233,15 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
static int c_lit;
static int c_has_texface;
Object *litob = NULL; /* to get mode to turn off mipmap in painting mode */
int backculled = 1;
int alphablend = GPU_BLEND_SOLID;
int textured = 0;
int lit = 0;
int has_texface = texface != NULL;
bool need_set_tpage = false;
bool texpaint = ((gtexdraw.ob->mode & OB_MODE_TEXTURE_PAINT) != 0);
Image *ima = NULL;
if (ma != NULL) {
if (ma->mode & MA_TRANSP) {
@@ -248,10 +254,10 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
memset(&c_texface, 0, sizeof(MTFace));
c_badtex = false;
c_has_texface = -1;
c_ma = NULL;
}
else {
textured = gtexdraw.is_tex;
litob = gtexdraw.ob;
}
/* convert number of lights into boolean */
@@ -266,14 +272,16 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
}
}
if (texface) {
if (texface && !texpaint) {
textured = textured && (texface->tpage);
/* no material, render alpha if texture has depth=32 */
if (!ma && BKE_image_has_alpha(texface->tpage))
alphablend = GPU_BLEND_ALPHA;
}
else if (texpaint && ma) {
ima = ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
}
else
textured = 0;
@@ -287,11 +295,25 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
/* need to re-set tpage if textured flag changed or existsment of texface changed.. */
need_set_tpage = textured != c_textured || has_texface != c_has_texface;
/* ..or if settings inside texface were changed (if texface was used) */
need_set_tpage |= texface && memcmp(&c_texface, texface, sizeof(c_texface));
need_set_tpage |= (texpaint && c_ma != ma) || (texface && memcmp(&c_texface, texface, sizeof(c_texface)));
if (need_set_tpage) {
if (textured) {
c_badtex = !GPU_set_tpage(texface, !(litob->mode & OB_MODE_TEXTURE_PAINT), alphablend);
if (texpaint) {
c_badtex = false;
if (GPU_verify_image(ima, NULL, 0, 1, 0, false)) {
glEnable(GL_TEXTURE_2D);
}
else {
c_badtex = true;
GPU_clear_tpage(true);
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
}
}
else {
c_badtex = !GPU_set_tpage(texface, !texpaint, alphablend);
}
}
else {
GPU_set_tpage(NULL, 0, 0);
@@ -325,6 +347,7 @@ static bool set_draw_settings_cached(int clearcache, MTFace *texface, Material *
glDisable(GL_COLOR_MATERIAL);
}
c_lit = lit;
c_ma = ma;
}
return c_badtex;
@@ -335,6 +358,7 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
unsigned char obcol[4];
bool is_tex, solidtex;
Mesh *me = ob->data;
ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
/* XXX scene->obedit warning */
@@ -364,8 +388,34 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
else is_tex = false;
Gtexdraw.ob = ob;
Gtexdraw.stencil = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? imapaint->stencil : NULL;
Gtexdraw.stencil_invert = ((imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0);
Gtexdraw.is_texpaint = (ob->mode == OB_MODE_TEXTURE_PAINT);
copy_v3_v3(Gtexdraw.stencil_col, imapaint->stencil_col);
Gtexdraw.is_tex = is_tex;
/* load the stencil texture here */
if (Gtexdraw.is_texpaint && (Gtexdraw.stencil != NULL)) {
glActiveTexture(GL_TEXTURE1);
if (GPU_verify_image(Gtexdraw.stencil, NULL, false, false, false, false)) {
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, Gtexdraw.stencil_col);
if (!Gtexdraw.stencil_invert) {
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_ONE_MINUS_SRC_COLOR);
}
else {
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
}
}
glActiveTexture(GL_TEXTURE0);
}
Gtexdraw.color_profile = BKE_scene_check_color_management_enabled(scene);
Gtexdraw.use_game_mat = (RE_engines_find(scene->r.engine)->flag & RE_GAME) != 0;
Gtexdraw.use_backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0;
@@ -379,8 +429,24 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
static void draw_textured_end(void)
{
/* switch off textures */
GPU_set_tpage(NULL, 0, 0);
if (Gtexdraw.ob->mode & OB_MODE_TEXTURE_PAINT) {
if (Gtexdraw.stencil != NULL) {
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
}
/* manual reset, since we don't use tpage */
glBindTexture(GL_TEXTURE_2D, 0);
/* force switch off textures */
GPU_clear_tpage(true);
}
else {
/* switch off textures */
GPU_set_tpage(NULL, 0, 0);
}
glShadeModel(GL_FLAT);
glDisable(GL_CULL_FACE);
@@ -456,7 +522,7 @@ static DMDrawOption draw_tface__set_draw(MTFace *tface, const bool UNUSED(has_mc
if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0;
if (tface)
if (tface || Gtexdraw.is_texpaint)
set_draw_settings_cached(0, tface, ma, Gtexdraw);
/* always use color from mcol, as set in update_tface_color_layer */
@@ -770,7 +836,8 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
Object *ob, DerivedMesh *dm, const int draw_flags)
{
Mesh *me = ob->data;
DMDrawFlag uvflag = DM_DRAW_USE_ACTIVE_UV;
/* correct for negative scale */
if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
else glFrontFace(GL_CCW);
@@ -780,6 +847,10 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
if (ob->mode & OB_MODE_TEXTURE_PAINT) {
uvflag = DM_DRAW_USE_TEXPAINT_UV;
}
if (ob->mode & OB_MODE_EDIT) {
drawEMTFMapped_userData data;
@@ -789,7 +860,7 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
data.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
data.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data);
dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data, 0);
}
else if (draw_flags & DRAW_FACE_SELECT) {
if (ob->mode & OB_MODE_WEIGHT_PAINT)
@@ -801,15 +872,15 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
userData.me = me;
dm->drawMappedFacesTex(dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, compareDrawOptions, &userData);
dm->drawMappedFacesTex(dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, compareDrawOptions, &userData, uvflag);
}
}
else {
if (GPU_buffer_legacy(dm)) {
if (draw_flags & DRAW_MODIFIERS_PREVIEW)
dm->drawFacesTex(dm, draw_mcol__set_draw_legacy, NULL, NULL);
dm->drawFacesTex(dm, draw_mcol__set_draw_legacy, NULL, NULL, uvflag);
else
dm->drawFacesTex(dm, draw_tface__set_draw_legacy, NULL, NULL);
dm->drawFacesTex(dm, draw_tface__set_draw_legacy, NULL, NULL, uvflag);
}
else {
drawTFace_userData userData;
@@ -820,7 +891,7 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
userData.me = NULL;
dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData);
dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData, uvflag);
}
}
@@ -955,7 +1026,8 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
/* if not cycles, or preview-modifiers, or drawing matcaps */
if ((draw_flags & DRAW_MODIFIERS_PREVIEW) ||
(v3d->flag2 & V3D_SHOW_SOLID_MATCAP) ||
(BKE_scene_use_new_shading_nodes(scene) == false))
(BKE_scene_use_new_shading_nodes(scene) == false) ||
((ob->mode & OB_MODE_TEXTURE_PAINT) && ELEM(v3d->drawtype, OB_TEXTURE, OB_SOLID)))
{
draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags);
return;
@@ -301,7 +301,7 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
if (BKE_scene_use_new_shading_nodes(scene))
return false;
return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID);
return ((scene->gm.matmode == GAME_MAT_GLSL) || (v3d->drawtype == OB_MATERIAL)) && (dt > OB_SOLID);
}
static bool check_alpha_pass(Base *base)
@@ -483,6 +483,12 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
keymap = WM_keymap_find(wm->defaultconf, "Object Mode", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
keymap = WM_keymap_find(wm->defaultconf, "Paint Curve", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
keymap = WM_keymap_find(wm->defaultconf, "Curve", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
keymap = WM_keymap_find(wm->defaultconf, "Image Paint", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
@@ -673,7 +679,7 @@ static void view3d_dropboxes(void)
WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_mesh_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
}
@@ -860,14 +866,18 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN
switch (wmn->data) {
case ND_SHADING:
case ND_NODES:
{
Object *ob = OBACT;
if ((v3d->drawtype == OB_MATERIAL) ||
(ob && (ob->mode == OB_MODE_TEXTURE_PAINT)) ||
(v3d->drawtype == OB_TEXTURE &&
(scene->gm.matmode == GAME_MAT_GLSL ||
BKE_scene_use_new_shading_nodes(scene))))
(scene->gm.matmode == GAME_MAT_GLSL ||
BKE_scene_use_new_shading_nodes(scene))))
{
ED_region_tag_redraw(ar);
}
break;
}
case ND_SHADING_DRAW:
case ND_SHADING_LINKS:
ED_region_tag_redraw(ar);
@@ -1099,6 +1109,11 @@ static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
if (wmn->data == ND_DATA || wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
break;
case NC_IMAGE:
/* Update for the image layers in texture paint. */
if (wmn->action == NA_EDITED)
ED_region_tag_redraw(ar);
break;
}
}
@@ -1287,6 +1287,12 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
{
/* do nothing */
}
/* texture paint mode sampling */
else if (base && (base->object->mode & OB_MODE_TEXTURE_PAINT) &&
(v3d->drawtype > OB_WIRE))
{
/* do nothing */
}
else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
v3d->drawtype > OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT))
{
@@ -2509,7 +2515,7 @@ CustomDataMask ED_view3d_datamask(Scene *scene, View3D *v3d)
mask |= CD_MASK_ORCO;
}
else {
if (scene->gm.matmode == GAME_MAT_GLSL)
if (scene->gm.matmode == GAME_MAT_GLSL || v3d->drawtype == OB_MATERIAL)
mask |= CD_MASK_ORCO;
}
}
@@ -4435,7 +4435,7 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
}
}
static void view3d_cursor3d_update(bContext *C, const int *mval)
void ED_view3d_cursor3d_update(bContext *C, const int mval[2])
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -4451,7 +4451,7 @@ static void view3d_cursor3d_update(bContext *C, const int *mval)
static int view3d_cursor3d_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
view3d_cursor3d_update(C, event->mval);
ED_view3d_cursor3d_update(C, event->mval);
op->customdata = SET_INT_IN_POINTER(event->type);
WM_event_add_modal_handler(C, op);
@@ -4468,7 +4468,7 @@ static int view3d_cursor3d_modal(bContext *C, wmOperator *op, const wmEvent *eve
switch (event->type) {
case MOUSEMOVE:
view3d_cursor3d_update(C, event->mval);
ED_view3d_cursor3d_update(C, event->mval);
break;
case LEFTMOUSE:
return OPERATOR_FINISHED;
@@ -32,6 +32,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "DNA_brush_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -45,6 +46,7 @@
#include "BKE_depsgraph.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_paint.h"
#include "BKE_screen.h"
#include "BKE_editmesh.h"
@@ -336,8 +338,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
uiItemR(layout, &v3dptr, "viewport_shade", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
if (obedit == NULL && is_paint) {
if (ob->mode & OB_MODE_WEIGHT_PAINT) {
if (ob->mode & OB_MODE_ALL_PAINT) {
/* Only for Weight Paint. makes no sense in other paint modes. */
row = uiLayoutRow(layout, true);
uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
+53 -18
View File
@@ -192,7 +192,7 @@ static bool transdata_check_local_center(TransInfo *t, short around)
(t->flag & (T_OBJECT | T_POSE)) ||
(t->obedit && ELEM(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)) ||
(t->spacetype == SPACE_IPO) ||
(t->options & (CTX_MOVIECLIP | CTX_MASK)))
(t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE)))
);
}
@@ -263,17 +263,27 @@ static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy)
void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy)
{
if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) {
const float mval_f[2] = {(float)dx, (float)dy};
ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac);
if (t->options & CTX_PAINT_CURVE) {
r_vec[0] = dx;
r_vec[1] = dy;
}
else { const float mval_f[2] = {(float)dx, (float)dy};
ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac);
}
}
else if (t->spacetype == SPACE_IMAGE) {
float aspx, aspy;
if (t->options & CTX_MASK) {
convertViewVec2D_mask(t->view, r_vec, dx, dy);
ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy);
}
else if (t->options & CTX_PAINT_CURVE) {
r_vec[0] = dx;
r_vec[1] = dy;
aspx = aspy = 1.0;
}
else {
convertViewVec2D(t->view, r_vec, dx, dy);
ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
@@ -351,6 +361,10 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr
adr[0] = v[0];
adr[1] = v[1];
}
else if (t->options & CTX_PAINT_CURVE) {
adr[0] = vec[0];
adr[1] = vec[1];
}
else {
float aspx, aspy, v[2];
@@ -452,7 +466,11 @@ void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV
switch (t->spacetype) {
case SPACE_VIEW3D:
{
if (t->ar->regiontype == RGN_TYPE_WINDOW) {
if (t->options & CTX_PAINT_CURVE) {
adr[0] = vec[0];
adr[1] = vec[1];
}
else if (t->ar->regiontype == RGN_TYPE_WINDOW) {
/* allow points behind the view [#33643] */
if (ED_view3d_project_float_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) {
/* XXX, 2.64 and prior did this, weak! */
@@ -480,7 +498,7 @@ void projectFloatView(TransInfo *t, const float vec[3], float adr[2])
void applyAspectRatio(TransInfo *t, float vec[2])
{
if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) {
if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION) && !(t->options & CTX_PAINT_CURVE)) {
SpaceImage *sima = t->sa->spacedata.first;
float aspx, aspy;
@@ -557,17 +575,23 @@ void removeAspectRatio(TransInfo *t, float vec[2])
static void viewRedrawForce(const bContext *C, TransInfo *t)
{
if (t->spacetype == SPACE_VIEW3D) {
/* Do we need more refined tags? */
if (t->flag & T_POSE)
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
else
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
if (t->options & CTX_PAINT_CURVE) {
wmWindow *window = CTX_wm_window(C);
WM_paint_cursor_tag_redraw(window, t->ar);
}
else {
/* Do we need more refined tags? */
if (t->flag & T_POSE)
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
else
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
/* for realtime animation record - send notifiers recognised by animation editors */
// XXX: is this notifier a lame duck?
if ((t->animtimer) && IS_AUTOKEY_ON(t->scene))
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
/* for realtime animation record - send notifiers recognised by animation editors */
// XXX: is this notifier a lame duck?
if ((t->animtimer) && IS_AUTOKEY_ON(t->scene))
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
}
}
else if (t->spacetype == SPACE_ACTION) {
//SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
@@ -593,6 +617,10 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
}
else if (t->options & CTX_PAINT_CURVE) {
wmWindow *window = CTX_wm_window(C);
WM_paint_cursor_tag_redraw(window, t->ar);
}
else {
// XXX how to deal with lock?
SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
@@ -3592,8 +3620,15 @@ static void initRotation(TransInfo *t)
if (t->flag & T_2D_EDIT)
t->flag |= T_NO_CONSTRAINT;
negate_v3_v3(t->axis, t->viewinv[2]);
normalize_v3(t->axis);
if (t->options & CTX_PAINT_CURVE) {
t->axis[0] = 0.0;
t->axis[1] = 0.0;
t->axis[2] = -1.0;
}
else {
negate_v3_v3(t->axis, t->viewinv[2]);
normalize_v3(t->axis);
}
copy_v3_v3(t->axis_orig, t->axis);
}
@@ -532,6 +532,7 @@ void flushTransNodes(TransInfo *t);
void flushTransSeq(TransInfo *t);
void flushTransTracking(TransInfo *t);
void flushTransMasking(TransInfo *t);
void flushTransPaintCurve(TransInfo *t);
void restoreBones(TransInfo *t);
/*********************** exported from transform_manipulator.c ********** */
@@ -756,6 +756,9 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
/* untested - mask aspect is TODO */
ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy);
}
else if (t->options & CTX_PAINT_CURVE) {
aspx = aspy = 1.0;
}
else {
ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
}
@@ -33,6 +33,7 @@
#include <math.h>
#include "DNA_anim_types.h"
#include "DNA_brush_types.h"
#include "DNA_armature_types.h"
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
@@ -80,6 +81,7 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_paint.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
@@ -5847,6 +5849,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else if (t->options & CTX_PAINT_CURVE) {
/* pass */
}
else if ((t->scene->basact) &&
(ob = t->scene->basact->object) &&
(ob->mode & OB_MODE_PARTICLE_EDIT) &&
@@ -7026,6 +7031,172 @@ void flushTransMasking(TransInfo *t)
}
}
typedef struct TransDataPaintCurve {
PaintCurvePoint *pcp; /* initial curve point */
char id;
} TransDataPaintCurve;
#define PC_IS_ANY_SEL(pc) (((pc)->bez.f1 | (pc)->bez.f2 | (pc)->bez.f3) & SELECT)
static void PaintCurveConvertHandle(PaintCurvePoint *pcp, int id, TransData2D *td2d, TransDataPaintCurve *tdpc, TransData *td) {
BezTriple *bezt = &pcp->bez;
copy_v2_v2(td2d->loc, bezt->vec[id]);
td2d->loc[2] = 0.0f;
td2d->loc2d = bezt->vec[id];
td->flag = 0;
td->loc = td2d->loc;
copy_v3_v3(td->center, bezt->vec[1]);
copy_v3_v3(td->iloc, td->loc);
memset(td->axismtx, 0, sizeof(td->axismtx));
td->axismtx[2][2] = 1.0f;
td->ext = NULL;
td->val = NULL;
td->flag |= TD_SELECTED;
td->dist = 0.0;
unit_m3(td->mtx);
unit_m3(td->smtx);
tdpc->id = id;
tdpc->pcp = pcp;
}
static void PaintCurvePointToTransData(PaintCurvePoint *pcp, TransData *td, TransData2D *td2d, TransDataPaintCurve *tdpc)
{
BezTriple *bezt = &pcp->bez;
if (pcp->bez.f2 == SELECT) {
int i;
for (i = 0; i < 3; i++) {
copy_v2_v2(td2d->loc, bezt->vec[i]);
td2d->loc[2] = 0.0f;
td2d->loc2d = bezt->vec[i];
td->flag = 0;
td->loc = td2d->loc;
copy_v3_v3(td->center, bezt->vec[1]);
copy_v3_v3(td->iloc, td->loc);
memset(td->axismtx, 0, sizeof(td->axismtx));
td->axismtx[2][2] = 1.0f;
td->ext = NULL;
td->val = NULL;
td->flag |= TD_SELECTED;
td->dist = 0.0;
unit_m3(td->mtx);
unit_m3(td->smtx);
tdpc->id = i;
tdpc->pcp = pcp;
td++;
td2d++;
tdpc++;
}
}
else {
if (bezt->f3 & SELECT) {
PaintCurveConvertHandle(pcp, 2, td2d, tdpc, td);
td2d++;
tdpc++;
td++;
}
if (bezt->f1 & SELECT) {
PaintCurveConvertHandle(pcp, 0, td2d, tdpc, td);
}
}
}
static void createTransPaintCurveVerts(bContext *C, TransInfo *t)
{
Paint *paint = BKE_paint_get_active_from_context(C);
PaintCurve *pc;
PaintCurvePoint *pcp;
Brush *br;
TransData *td = NULL;
TransData2D *td2d = NULL;
TransDataPaintCurve *tdpc = NULL;
int i;
int total = 0;
t->total = 0;
if (!paint || !paint->brush || !paint->brush->paint_curve)
return;
br = paint->brush;
pc = br->paint_curve;
for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
if (PC_IS_ANY_SEL(pcp)) {
if (pcp->bez.f2 & SELECT) {
total += 3;
continue;
}
else {
if (pcp->bez.f1 & SELECT)
total++;
if (pcp->bez.f3 & SELECT)
total++;
}
}
}
if (!total)
return;
t->total = total;
td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransData2D");
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransData");
tdpc = t->customData = MEM_callocN(t->total * sizeof(TransDataPaintCurve), "TransDataPaintCurve");
t->flag |= T_FREE_CUSTOMDATA;
for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) {
if (PC_IS_ANY_SEL(pcp)) {
PaintCurvePointToTransData (pcp, td, td2d, tdpc);
if (pcp->bez.f2 & SELECT) {
td += 3;
td2d += 3;
tdpc += 3;
}
else {
if (pcp->bez.f1 & SELECT) {
td++;
td2d++;
tdpc++;
}
if (pcp->bez.f3 & SELECT) {
td++;
td2d++;
tdpc++;
}
}
}
}
}
void flushTransPaintCurve(TransInfo *t)
{
int i;
TransData2D *td2d = t->data2d;
TransDataPaintCurve *tdpc = (TransDataPaintCurve *)t->customData;
for (i = 0; i < t->total; i++, tdpc++, td2d++) {
PaintCurvePoint *pcp = tdpc->pcp;
copy_v2_v2(pcp->bez.vec[tdpc->id], td2d->loc);
}
}
void createTransData(bContext *C, TransInfo *t)
{
Scene *scene = t->scene;
@@ -7058,6 +7229,10 @@ void createTransData(bContext *C, TransInfo *t)
sort_trans_data_dist(t);
}
}
else if (t->options & CTX_PAINT_CURVE) {
if(!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN))
createTransPaintCurveVerts(C, t);
}
else if (t->obedit) {
createTransUVs(C, t);
if (t->data && (t->flag & T_PROP_EDIT)) {
@@ -7164,7 +7339,7 @@ void createTransData(bContext *C, TransInfo *t)
// XXX active-layer checking isn't done as that should probably be checked through context instead
createTransPose(t, ob);
}
else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) {
/* important that ob_armature can be set even when its not selected [#23412]
* lines below just check is also visible */
Object *ob_armature = modifiers_isDeformedByArmature(ob);
@@ -7189,12 +7364,11 @@ void createTransData(bContext *C, TransInfo *t)
sort_trans_data_dist(t);
}
}
else if (ob && (ob->mode & (OB_MODE_ALL_PAINT))) {
/* sculpt mode and project paint have own undo stack
* transform ops redo clears sculpt/project undo stack.
*
* Could use 'OB_MODE_ALL_PAINT' since there are key conflicts,
* transform + paint isn't well supported. */
else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
t->flag |= T_POINTS | T_2D_EDIT;
createTransPaintCurveVerts(C, t);
}
}
else {
createTransObject(C, t);
@@ -38,6 +38,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_brush_types.h"
#include "DNA_lattice_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
@@ -74,6 +75,7 @@
#include "BKE_lattice.h"
#include "BKE_nla.h"
#include "BKE_context.h"
#include "BKE_paint.h"
#include "BKE_sequencer.h"
#include "BKE_editmesh.h"
#include "BKE_tracking.h"
@@ -98,6 +100,7 @@
#include "WM_api.h"
#include "UI_resources.h"
#include "UI_view2d.h"
#include "transform.h"
@@ -653,6 +656,9 @@ static void recalcData_image(TransInfo *t)
if (t->options & CTX_MASK) {
recalcData_mask_common(t);
}
else if (t->options & CTX_PAINT_CURVE) {
flushTransPaintCurve(t);
}
else if (t->obedit && t->obedit->type == OB_MESH) {
SpaceImage *sima = t->sa->spacedata.first;
@@ -965,6 +971,9 @@ void recalcData(TransInfo *t)
else if (t->options & CTX_EDGE) {
recalcData_objects(t);
}
else if (t->options & CTX_PAINT_CURVE) {
flushTransPaintCurve(t);
}
else if (t->spacetype == SPACE_IMAGE) {
recalcData_image(t);
}
@@ -1073,6 +1082,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
ARegion *ar = CTX_wm_region(C);
ScrArea *sa = CTX_wm_area(C);
Object *obedit = CTX_data_edit_object(C);
Object *ob = CTX_data_active_object(C);
PropertyRNA *prop;
t->scene = sce;
@@ -1198,6 +1208,13 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
}
if (ob && ob->mode & OB_MODE_ALL_PAINT) {
Paint *p = BKE_paint_get_active_from_context(C);
if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
t->options |= CTX_PAINT_CURVE;
}
}
/* initialize UV transform from */
if (op && ((prop = RNA_struct_find_property(op->ptr, "correct_uv")))) {
if (RNA_property_is_set(op->ptr, prop)) {
@@ -1226,9 +1243,13 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
else if (sima->mode == SI_MODE_MASK) {
t->options |= CTX_MASK;
}
else {
/* image not in uv edit, nor in mask mode, can happen for some tools */
else if (sima->mode == SI_MODE_PAINT) {
Paint *p = &sce->toolsettings->imapaint.paint;
if (p->brush && (p->brush->flag & BRUSH_CURVE)) {
t->options |= CTX_PAINT_CURVE;
}
}
/* image not in uv edit, nor in mask mode, can happen for some tools */
}
else if (t->spacetype == SPACE_NODE) {
// XXX for now, get View2D from the active region
@@ -1409,7 +1430,7 @@ void postTrans(bContext *C, TransInfo *t)
}
if (t->spacetype == SPACE_IMAGE) {
if (t->options & CTX_MASK) {
if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
/* pass */
}
else {
@@ -1539,6 +1560,13 @@ void calculateCenterCursor(TransInfo *t, float r_center[3])
invert_m3_m3(imat, mat);
mul_m3_v3(imat, r_center);
}
else if (t->options & CTX_PAINT_CURVE) {
if (ED_view3d_project_float_global(t->ar, cursor, r_center, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
r_center[0] = t->ar->winx / 2.0f;
r_center[1] = t->ar->winy / 2.0f;
}
r_center[2] = 0.0f;
}
}
void calculateCenterCursor2D(TransInfo *t, float r_center[2])
@@ -1586,6 +1614,12 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2])
r_center[0] = co[0] * aspx;
r_center[1] = co[1] * aspy;
}
else if (t->options & CTX_PAINT_CURVE) {
if (t->spacetype == SPACE_IMAGE) {
r_center[0] = UI_view2d_view_to_region_x(&t->ar->v2d, cursor[0]);
r_center[1] = UI_view2d_view_to_region_y(&t->ar->v2d, cursor[1]);
}
}
else {
r_center[0] = cursor[0] * aspx;
r_center[1] = cursor[1] * aspy;
@@ -1720,6 +1754,14 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
}
}
}
else if (t->options & CTX_PAINT_CURVE) {
Paint *p = BKE_paint_get_active(t->scene);
Brush *br = p->brush;
PaintCurve *pc = br->paint_curve;
copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]);
r_center[2] = 0.0f;
ok = true;
}
else {
/* object mode */
Scene *scene = t->scene;
@@ -2383,6 +2383,9 @@ static void applyGridIncrement(TransInfo *t, float *val, int max_index, float fa
if (t->options & CTX_MASK) {
ED_space_image_get_aspect(t->sa->spacedata.first, asp, asp + 1);
}
else if (t->options & CTX_PAINT_CURVE) {
asp[0] = asp[1] = 1.0;
}
else {
ED_space_image_get_uv_aspect(t->sa->spacedata.first, asp, asp + 1);
}
+31 -2
View File
@@ -33,6 +33,7 @@
#include <stdlib.h>
#include <string.h>
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -48,6 +49,8 @@
#include "BKE_DerivedMesh.h"
#include "BKE_editmesh.h"
#include "BKE_material.h"
#include "BKE_scene.h"
#include "BIF_gl.h"
@@ -479,13 +482,39 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
{
const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
Image *curimage = ED_space_image(sima);
Mesh *me = ob->data;
Material *ma;
if (sima->flag & SI_DRAW_OTHER) {
draw_uvs_other(scene, ob, curimage, new_shading_nodes);
}
UI_ThemeColor(TH_UV_SHADOW);
draw_uvs_other_mesh(ob, curimage, new_shading_nodes);
ma = give_current_material(ob, ob->actcol);
if (me->mtpoly) {
MPoly *mpoly = me->mpoly;
MLoopUV *mloopuv, *mloopuv_base;
int a, b;
if (!(ma && ma->texpaintslot && ma->texpaintslot[ma->paint_active_slot].uvname[0] &&
(mloopuv = CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, ma->texpaintslot[ma->paint_active_slot].uvname))))
{
mloopuv = me->mloopuv;
}
mloopuv_base = mloopuv;
for (a = me->totpoly; a > 0; a--, mpoly++) {
glBegin(GL_LINE_LOOP);
mloopuv = mloopuv_base + mpoly->loopstart;
for (b = 0; b < mpoly->totloop; b++, mloopuv++) {
glVertex2fv(mloopuv->uv);
}
glEnd();
}
}
}
#ifdef USE_EDBM_LOOPTRIS
@@ -922,7 +951,7 @@ void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedi
ToolSettings *toolsettings = scene->toolsettings;
int show_uvedit, show_uvshadow, show_texpaint_uvshadow;
show_texpaint_uvshadow = (obact && obact->type == OB_MESH && obact->mode == OB_MODE_TEXTURE_PAINT);
show_texpaint_uvshadow = ED_space_image_show_texpaint(sima, obact);
show_uvedit = ED_space_image_show_uvedit(sima, obedit);
show_uvshadow = ED_space_image_show_uvshadow(sima, obedit);
+2 -1
View File
@@ -3827,7 +3827,8 @@ static void UV_OT_reveal(wmOperatorType *ot)
static int uv_set_2d_cursor_poll(bContext *C)
{
return ED_operator_uvedit_space_image(C) ||
ED_space_image_maskedit_poll(C);
ED_space_image_maskedit_poll(C) ||
ED_space_image_paint_curve(C);
}
static int uv_set_2d_cursor_exec(bContext *C, wmOperator *op)
+1
View File
@@ -139,6 +139,7 @@ void GPU_drawobject_free(struct DerivedMesh *dm);
void GPU_vertex_setup(struct DerivedMesh *dm);
void GPU_normal_setup(struct DerivedMesh *dm);
void GPU_uv_setup(struct DerivedMesh *dm);
void GPU_texpaint_uv_setup(struct DerivedMesh *dm);
/* colType is the cddata MCol type to use! */
void GPU_color_setup(struct DerivedMesh *dm, int colType);
void GPU_edge_setup(struct DerivedMesh *dm); /* does not mix with other data */
+1 -1
View File
@@ -87,7 +87,7 @@ int GPU_get_material_alpha_blend(void);
* - passing NULL clears the state again */
int GPU_set_tpage(struct MTFace *tface, int mipmap, int transp);
void GPU_clear_tpage(bool force);
/* Lights
* - returns how many lights were enabled
* - this affects fixed functions materials and texface, not glsl */
+105 -8
View File
@@ -46,11 +46,13 @@
#include "BLI_ghash.h"
#include "BLI_threads.h"
#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_ccg.h"
#include "BKE_DerivedMesh.h"
#include "BKE_paint.h"
#include "BKE_material.h"
#include "BKE_pbvh.h"
#include "DNA_userdef_types.h"
@@ -63,13 +65,16 @@
typedef enum {
GPU_BUFFER_VERTEX_STATE = 1,
GPU_BUFFER_NORMAL_STATE = 2,
GPU_BUFFER_TEXCOORD_STATE = 4,
GPU_BUFFER_COLOR_STATE = 8,
GPU_BUFFER_ELEMENT_STATE = 16,
GPU_BUFFER_TEXCOORD_UNIT_0_STATE = 4,
GPU_BUFFER_TEXCOORD_UNIT_1_STATE = 8,
GPU_BUFFER_COLOR_STATE = 16,
GPU_BUFFER_ELEMENT_STATE = 32,
} GPUBufferState;
#define MAX_GPU_ATTRIB_DATA 32
#define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n))
/* -1 - undefined, 0 - vertex arrays, 1 - VBOs */
static int useVBOs = -1;
static GPUBufferState GLStates = 0;
@@ -836,6 +841,61 @@ static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int *
}
}
static void GPU_buffer_copy_uv_texpaint(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
{
int start;
int i, totface;
int totmaterial = dm->totmat;
MTFace **mtface_base;
MTFace *stencil_base;
int stencil;
MFace *mf;
/* should have been checked for before, reassert */
BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
mf = dm->getTessFaceArray(dm);
mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
for (i = 0; i < totmaterial; i++) {
mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
}
stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
totface = dm->getNumTessFaces(dm);
for (i = 0; i < totface; i++, mf++) {
int mat_i = mf->mat_nr;
start = index[mat_orig_to_new[mat_i]];
/* v1 v2 v3 */
copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[0]);
copy_v2_v2(&varray[start + 2], stencil_base[i].uv[0]);
copy_v2_v2(&varray[start + 4], mtface_base[mat_i][i].uv[1]);
copy_v2_v2(&varray[start + 6], stencil_base[i].uv[1]);
copy_v2_v2(&varray[start + 8], mtface_base[mat_i][i].uv[2]);
copy_v2_v2(&varray[start + 10], stencil_base[i].uv[2]);
index[mat_orig_to_new[mat_i]] += 12;
if (mf->v4) {
/* v3 v4 v1 */
copy_v2_v2(&varray[start + 12], mtface_base[mat_i][i].uv[2]);
copy_v2_v2(&varray[start + 14], stencil_base[i].uv[2]);
copy_v2_v2(&varray[start + 16], mtface_base[mat_i][i].uv[3]);
copy_v2_v2(&varray[start + 18], stencil_base[i].uv[3]);
copy_v2_v2(&varray[start + 20], mtface_base[mat_i][i].uv[0]);
copy_v2_v2(&varray[start + 22], stencil_base[i].uv[0]);
index[mat_orig_to_new[mat_i]] += 12;
}
}
MEM_freeN(mtface_base);
}
static void copy_mcol_uc3(unsigned char *v, unsigned char *col)
{
v[0] = col[3];
@@ -925,6 +985,7 @@ typedef enum {
GPU_BUFFER_NORMAL,
GPU_BUFFER_COLOR,
GPU_BUFFER_UV,
GPU_BUFFER_UV_TEXPAINT,
GPU_BUFFER_EDGE,
GPU_BUFFER_UVEDGE,
} GPUBufferType;
@@ -940,6 +1001,7 @@ const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
{GPU_buffer_copy_normal, GL_ARRAY_BUFFER_ARB, 3},
{GPU_buffer_copy_mcol, GL_ARRAY_BUFFER_ARB, 3},
{GPU_buffer_copy_uv, GL_ARRAY_BUFFER_ARB, 2},
{GPU_buffer_copy_uv_texpaint, GL_ARRAY_BUFFER_ARB, 4},
{GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
{GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER_ARB, 4}
};
@@ -956,6 +1018,8 @@ static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBuffer
return &gdo->colors;
case GPU_BUFFER_UV:
return &gdo->uv;
case GPU_BUFFER_UV_TEXPAINT:
return &gdo->uv;
case GPU_BUFFER_EDGE:
return &gdo->edges;
case GPU_BUFFER_UVEDGE:
@@ -977,6 +1041,8 @@ static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
return sizeof(char) * 3 * dm->drawObject->tot_triangle_point;
case GPU_BUFFER_UV:
return sizeof(float) * 2 * dm->drawObject->tot_triangle_point;
case GPU_BUFFER_UV_TEXPAINT:
return sizeof(float) * 4 * dm->drawObject->tot_triangle_point;
case GPU_BUFFER_EDGE:
return sizeof(int) * 2 * dm->drawObject->totedge;
case GPU_BUFFER_UVEDGE:
@@ -1005,7 +1071,7 @@ static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType)))
return NULL;
}
else if (type == GPU_BUFFER_UV) {
else if (ELEM(type, GPU_BUFFER_UV, GPU_BUFFER_UV_TEXPAINT)) {
if (!DM_get_tessface_data_layer(dm, CD_MTFACE))
return NULL;
}
@@ -1081,9 +1147,35 @@ void GPU_uv_setup(DerivedMesh *dm)
glTexCoordPointer(2, GL_FLOAT, 0, dm->drawObject->uv->pointer);
}
GLStates |= GPU_BUFFER_TEXCOORD_STATE;
GLStates |= GPU_BUFFER_TEXCOORD_UNIT_0_STATE;
}
void GPU_texpaint_uv_setup(DerivedMesh *dm)
{
if (!gpu_buffer_setup_common(dm, GPU_BUFFER_UV_TEXPAINT))
return;
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if (useVBOs) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id);
glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0);
glClientActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), BUFFER_OFFSET(2 * sizeof(float)));
glClientActiveTexture(GL_TEXTURE0);
}
else {
glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), dm->drawObject->uv->pointer);
glClientActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)dm->drawObject->uv->pointer + 2 * sizeof(float));
glClientActiveTexture(GL_TEXTURE0);
}
GLStates |= GPU_BUFFER_TEXCOORD_UNIT_0_STATE | GPU_BUFFER_TEXCOORD_UNIT_1_STATE;
}
void GPU_color_setup(DerivedMesh *dm, int colType)
{
if (!dm->drawObject) {
@@ -1241,8 +1333,13 @@ void GPU_buffer_unbind(void)
glDisableClientState(GL_VERTEX_ARRAY);
if (GLStates & GPU_BUFFER_NORMAL_STATE)
glDisableClientState(GL_NORMAL_ARRAY);
if (GLStates & GPU_BUFFER_TEXCOORD_STATE)
if (GLStates & GPU_BUFFER_TEXCOORD_UNIT_0_STATE)
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (GLStates & GPU_BUFFER_TEXCOORD_UNIT_1_STATE) {
glClientActiveTexture(GL_TEXTURE1);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
}
if (GLStates & GPU_BUFFER_COLOR_STATE)
glDisableClientState(GL_COLOR_ARRAY);
if (GLStates & GPU_BUFFER_ELEMENT_STATE) {
@@ -1251,8 +1348,8 @@ void GPU_buffer_unbind(void)
}
}
GLStates &= ~(GPU_BUFFER_VERTEX_STATE | GPU_BUFFER_NORMAL_STATE |
GPU_BUFFER_TEXCOORD_STATE | GPU_BUFFER_COLOR_STATE |
GPU_BUFFER_ELEMENT_STATE);
GPU_BUFFER_TEXCOORD_UNIT_0_STATE | GPU_BUFFER_TEXCOORD_UNIT_1_STATE |
GPU_BUFFER_COLOR_STATE | GPU_BUFFER_ELEMENT_STATE);
for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
if (attribData[i].index != -1) {
+3 -3
View File
@@ -370,9 +370,9 @@ static void gpu_make_repbind(Image *ima)
BKE_image_release_ibuf(ima, ibuf, NULL);
}
static void gpu_clear_tpage(void)
void GPU_clear_tpage(bool force)
{
if (GTS.lasttface==NULL)
if (GTS.lasttface==NULL && !force)
return;
GTS.lasttface= NULL;
@@ -866,7 +866,7 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend)
/* check if we need to clear the state */
if (tface==NULL) {
gpu_clear_tpage();
GPU_clear_tpage(false);
return 0;
}
+18 -2
View File
@@ -163,6 +163,22 @@ typedef enum IMB_BlendMode {
IMB_BLEND_DARKEN = 5,
IMB_BLEND_ERASE_ALPHA = 6,
IMB_BLEND_ADD_ALPHA = 7,
IMB_BLEND_OVERLAY = 8,
IMB_BLEND_HARDLIGHT = 9,
IMB_BLEND_COLORBURN = 10,
IMB_BLEND_LINEARBURN = 11,
IMB_BLEND_COLORDODGE = 12,
IMB_BLEND_SCREEN = 13,
IMB_BLEND_SOFTLIGHT = 14,
IMB_BLEND_PINLIGHT = 15,
IMB_BLEND_VIVIDLIGHT = 16,
IMB_BLEND_LINEARLIGHT = 17,
IMB_BLEND_DIFFERENCE = 18,
IMB_BLEND_EXCLUSION = 19,
IMB_BLEND_HUE = 20,
IMB_BLEND_SATURATION = 21,
IMB_BLEND_LUMINOSITY = 22,
IMB_BLEND_COLOR = 23,
IMB_BLEND_COPY = 1000,
IMB_BLEND_COPY_RGB = 1001,
@@ -179,9 +195,9 @@ void IMB_rectclip(struct ImBuf *dbuf, struct ImBuf *sbuf, int *destx,
void IMB_rectcpy(struct ImBuf *drect, struct ImBuf *srect, int destx,
int desty, int srcx, int srcy, int width, int height);
void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *obuf, struct ImBuf *sbuf,
unsigned short *dmask, unsigned short *smask, unsigned short mask_max,
unsigned short *dmask, unsigned short *curvemask, unsigned short *mmask, float mask_max,
int destx, int desty, int origx, int origy, int srcx, int srcy,
int width, int height, IMB_BlendMode mode);
int width, int height, IMB_BlendMode mode, bool accumulate);
/**
*
+240 -30
View File
@@ -65,6 +65,39 @@ void IMB_blend_color_byte(unsigned char dst[4], unsigned char src1[4], unsigned
blend_color_erase_alpha_byte(dst, src1, src2); break;
case IMB_BLEND_ADD_ALPHA:
blend_color_add_alpha_byte(dst, src1, src2); break;
case IMB_BLEND_OVERLAY:
blend_color_overlay_byte(dst, src1, src2); break;
case IMB_BLEND_HARDLIGHT:
blend_color_hardlight_byte(dst, src1, src2); break;
case IMB_BLEND_COLORBURN:
blend_color_burn_byte(dst, src1, src2); break;
case IMB_BLEND_LINEARBURN:
blend_color_linearburn_byte(dst, src1, src2); break;
case IMB_BLEND_COLORDODGE:
blend_color_dodge_byte(dst, src1, src2); break;
case IMB_BLEND_SCREEN:
blend_color_screen_byte(dst, src1, src2); break;
case IMB_BLEND_SOFTLIGHT:
blend_color_softlight_byte(dst, src1, src2); break;
case IMB_BLEND_PINLIGHT:
blend_color_pinlight_byte(dst, src1, src2); break;
case IMB_BLEND_LINEARLIGHT:
blend_color_linearlight_byte(dst, src1, src2); break;
case IMB_BLEND_VIVIDLIGHT:
blend_color_vividlight_byte(dst, src1, src2); break;
case IMB_BLEND_DIFFERENCE:
blend_color_difference_byte(dst, src1, src2); break;
case IMB_BLEND_EXCLUSION:
blend_color_exclusion_byte(dst, src1, src2); break;
case IMB_BLEND_COLOR:
blend_color_color_byte(dst, src1, src2); break;
case IMB_BLEND_HUE:
blend_color_hue_byte(dst, src1, src2); break;
case IMB_BLEND_SATURATION:
blend_color_saturation_byte(dst, src1, src2); break;
case IMB_BLEND_LUMINOSITY:
blend_color_luminosity_byte(dst, src1, src2); break;
default:
dst[0] = src1[0];
dst[1] = src1[1];
@@ -93,6 +126,38 @@ void IMB_blend_color_float(float dst[4], float src1[4], float src2[4], IMB_Blend
blend_color_erase_alpha_float(dst, src1, src2); break;
case IMB_BLEND_ADD_ALPHA:
blend_color_add_alpha_float(dst, src1, src2); break;
case IMB_BLEND_OVERLAY:
blend_color_overlay_float(dst, src1, src2); break;
case IMB_BLEND_HARDLIGHT:
blend_color_hardlight_float(dst, src1, src2); break;
case IMB_BLEND_COLORBURN:
blend_color_burn_float(dst, src1, src2); break;
case IMB_BLEND_LINEARBURN:
blend_color_linearburn_float(dst, src1, src2); break;
case IMB_BLEND_COLORDODGE:
blend_color_dodge_float(dst, src1, src2); break;
case IMB_BLEND_SCREEN:
blend_color_screen_float(dst, src1, src2); break;
case IMB_BLEND_SOFTLIGHT:
blend_color_softlight_float(dst, src1, src2); break;
case IMB_BLEND_PINLIGHT:
blend_color_pinlight_float(dst, src1, src2); break;
case IMB_BLEND_LINEARLIGHT:
blend_color_linearlight_float(dst, src1, src2); break;
case IMB_BLEND_VIVIDLIGHT:
blend_color_vividlight_float(dst, src1, src2); break;
case IMB_BLEND_DIFFERENCE:
blend_color_difference_float(dst, src1, src2); break;
case IMB_BLEND_EXCLUSION:
blend_color_exclusion_float(dst, src1, src2); break;
case IMB_BLEND_COLOR:
blend_color_color_float(dst, src1, src2); break;
case IMB_BLEND_HUE:
blend_color_hue_float(dst, src1, src2); break;
case IMB_BLEND_SATURATION:
blend_color_saturation_float(dst, src1, src2); break;
case IMB_BLEND_LUMINOSITY:
blend_color_luminosity_float(dst, src1, src2); break;
default:
dst[0] = src1[0];
dst[1] = src1[1];
@@ -226,22 +291,23 @@ static void imb_rectclip3(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, int *destx,
void IMB_rectcpy(ImBuf *dbuf, ImBuf *sbuf, int destx,
int desty, int srcx, int srcy, int width, int height)
{
IMB_rectblend(dbuf, dbuf, sbuf, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, width, height, IMB_BLEND_COPY);
IMB_rectblend(dbuf, dbuf, sbuf, NULL, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, width, height, IMB_BLEND_COPY, false);
}
typedef void (*IMB_blend_func)(unsigned char *dst, const unsigned char *src1, const unsigned char *src2);
typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2);
void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
unsigned short *smask, unsigned short mask_max,
void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, unsigned short *curvemask,
unsigned short *texmask, float mask_max,
int destx, int desty, int origx, int origy, int srcx, int srcy, int width, int height,
IMB_BlendMode mode)
IMB_BlendMode mode, bool accumulate)
{
unsigned int *drect = NULL, *orect, *srect = NULL, *dr, *or, *sr;
float *drectf = NULL, *orectf, *srectf = NULL, *drf, *orf, *srf;
unsigned short *smaskrect = smask, *smr;
unsigned short *cmaskrect = curvemask, *cmr;
unsigned short *dmaskrect = dmask, *dmr;
unsigned short *texmaskrect = texmask, *tmr;
int do_float, do_char, srcskip, destskip, origskip, x;
IMB_blend_func func = NULL;
IMB_blend_func_float func_float = NULL;
@@ -277,8 +343,11 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
if (do_float) srectf = sbuf->rect_float + (srcy * sbuf->x + srcx) * 4;
srcskip = sbuf->x;
if (smaskrect)
smaskrect += srcy * sbuf->x + srcx;
if (cmaskrect)
cmaskrect += srcy * sbuf->x + srcx;
if (texmaskrect)
texmaskrect += srcy * sbuf->x + srcx;
}
else {
srect = drect;
@@ -388,6 +457,70 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
func = blend_color_add_alpha_byte;
func_float = blend_color_add_alpha_float;
break;
case IMB_BLEND_OVERLAY:
func = blend_color_overlay_byte;
func_float = blend_color_overlay_float;
break;
case IMB_BLEND_HARDLIGHT:
func = blend_color_hardlight_byte;
func_float = blend_color_hardlight_float;
break;
case IMB_BLEND_COLORBURN:
func = blend_color_burn_byte;
func_float = blend_color_burn_float;
break;
case IMB_BLEND_LINEARBURN:
func = blend_color_linearburn_byte;
func_float = blend_color_linearburn_float;
break;
case IMB_BLEND_COLORDODGE:
func = blend_color_dodge_byte;
func_float = blend_color_dodge_float;
break;
case IMB_BLEND_SCREEN:
func = blend_color_screen_byte;
func_float = blend_color_screen_float;
break;
case IMB_BLEND_SOFTLIGHT:
func = blend_color_softlight_byte;
func_float = blend_color_softlight_float;
break;
case IMB_BLEND_PINLIGHT:
func = blend_color_pinlight_byte;
func_float = blend_color_pinlight_float;
break;
case IMB_BLEND_LINEARLIGHT:
func = blend_color_linearlight_byte;
func_float = blend_color_linearlight_float;
break;
case IMB_BLEND_VIVIDLIGHT:
func = blend_color_vividlight_byte;
func_float = blend_color_vividlight_float;
break;
case IMB_BLEND_DIFFERENCE:
func = blend_color_difference_byte;
func_float = blend_color_difference_float;
break;
case IMB_BLEND_EXCLUSION:
func = blend_color_exclusion_byte;
func_float = blend_color_exclusion_float;
break;
case IMB_BLEND_COLOR:
func = blend_color_color_byte;
func_float = blend_color_color_float;
break;
case IMB_BLEND_HUE:
func = blend_color_hue_byte;
func_float = blend_color_hue_float;
break;
case IMB_BLEND_SATURATION:
func = blend_color_saturation_byte;
func_float = blend_color_saturation_float;
break;
case IMB_BLEND_LUMINOSITY:
func = blend_color_luminosity_byte;
func_float = blend_color_luminosity_float;
break;
default:
break;
}
@@ -399,22 +532,61 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
or = orect;
sr = srect;
if (dmaskrect && smaskrect) {
if (cmaskrect) {
/* mask accumulation for painting */
dmr = dmaskrect;
smr = smaskrect;
cmr = cmaskrect;
tmr = texmaskrect;
for (x = width; x > 0; x--, dr++, or++, sr++, dmr++, smr++) {
unsigned char *src = (unsigned char *)sr;
/* destination mask present, do max alpha masking */
if (dmaskrect) {
dmr = dmaskrect;
for (x = width; x > 0; x--, dr++, or++, sr++, dmr++, cmr++) {
unsigned char *src = (unsigned char *)sr;
float mask_lim = mask_max * (*cmr);
if (src[3] && *smr) {
unsigned short mask = *dmr + (((mask_max - *dmr) * (*smr)) / 65535);
if (texmaskrect)
mask_lim *= ((*tmr++) / 65535.0f);
if (mask > *dmr) {
if (src[3] && mask_lim) {
float mask;
if (accumulate)
mask = *dmr + mask_lim;
else
mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
mask = min_ff(mask, 65535.0);
if (mask > *dmr) {
unsigned char mask_src[4];
*dmr = mask;
mask_src[0] = src[0];
mask_src[1] = src[1];
mask_src[2] = src[2];
mask_src[3] = divide_round_i(src[3] * mask, 65535);
func((unsigned char *)dr, (unsigned char *)or, mask_src);
}
}
}
dmaskrect += origskip;
}
/* no destination mask buffer, do regular blend with masktexture if present */
else {
for (x = width; x > 0; x--, dr++, or++, sr++, cmr++) {
unsigned char *src = (unsigned char *)sr;
float mask = (float)mask_max * ((float)(*cmr));
if (texmaskrect)
mask *= ((float)(*tmr++) / 65535.0f);
mask = min_ff(mask, 65535.0);
if (src[3] && (mask > 0.0f)) {
unsigned char mask_src[4];
*dmr = mask;
mask_src[0] = src[0];
mask_src[1] = src[1];
mask_src[2] = src[2];
@@ -425,8 +597,9 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
}
}
dmaskrect += origskip;
smaskrect += srcskip;
cmaskrect += srcskip;
if (texmaskrect)
texmaskrect += srcskip;
}
else {
/* regular blending */
@@ -446,28 +619,65 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
orf = orectf;
srf = srectf;
if (dmaskrect && smaskrect) {
if (cmaskrect) {
/* mask accumulation for painting */
dmr = dmaskrect;
smr = smaskrect;
cmr = cmaskrect;
tmr = texmaskrect;
for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, smr++) {
if (srf[3] != 0 && *smr) {
unsigned short mask = *dmr + (((mask_max - *dmr) * (*smr)) / 65535);
/* destination mask present, do max alpha masking */
if (dmaskrect) {
dmr = dmaskrect;
for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, cmr++) {
float mask_lim = mask_max * (*cmr);
if (mask > *dmr) {
if (texmaskrect)
mask_lim *= ((*tmr++) / 65535.0f);
if (srf[3] && mask_lim) {
float mask;
if (accumulate)
mask = min_ff(*dmr + mask_lim, 65535.0);
else
mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
mask = min_ff(mask, 65535.0);
if (mask > *dmr) {
float mask_srf[4];
*dmr = mask;
mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
func_float(drf, orf, mask_srf);
}
}
}
dmaskrect += origskip;
}
/* no destination mask buffer, do regular blend with masktexture if present */
else {
for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, cmr++) {
float mask = (float)mask_max * ((float)(*cmr));
if (texmaskrect)
mask *= ((float)(*tmr++) / 65535.0f);
mask = min_ff(mask, 65535.0);
if (srf[3] && (mask > 0.0f)) {
float mask_srf[4];
*dmr = mask;
mul_v4_v4fl(mask_srf, srf, mask * (1.0f / 65535.0f));
mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
func_float(drf, orf, mask_srf);
}
}
}
dmaskrect += origskip;
smaskrect += srcskip;
cmaskrect += srcskip;
if (texmaskrect)
texmaskrect += srcskip;
}
else {
/* regular blending */
+2
View File
@@ -213,6 +213,8 @@ typedef struct PreviewImage {
#define ID_MC MAKE_ID2('M', 'C') /* MovieClip */
#define ID_MSK MAKE_ID2('M', 'S') /* Mask */
#define ID_LS MAKE_ID2('L', 'S') /* FreestyleLineStyle */
#define ID_PAL MAKE_ID2('P', 'L') /* Palette */
#define ID_PC MAKE_ID2('P', 'C') /* Paint Curve */
/* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */
#define ID_SEQ MAKE_ID2('S', 'Q')
+86 -8
View File
@@ -35,6 +35,7 @@
#include "DNA_ID.h"
#include "DNA_texture_types.h" /* for MTex */
#include "DNA_curve_types.h"
//#ifndef MAX_MTEX // XXX Not used?
//#define MAX_MTEX 18
@@ -62,6 +63,9 @@ typedef struct Brush {
struct ImBuf *icon_imbuf;
PreviewImage *preview;
struct ColorBand *gradient; /* color gradient */
struct PaintCurve *paint_curve;
char icon_filepath[1024]; /* 1024 = FILE_MAX */
float normal_weight;
@@ -71,6 +75,7 @@ typedef struct Brush {
float weight; /* brush weight */
int size; /* brush diameter */
int flag; /* general purpose flag */
int mask_pressure; /* pressure influence for mask */
float jitter; /* jitter the position of the brush */
int jitter_absolute; /* absolute jitter in pixels */
int overlay_flags;
@@ -82,10 +87,17 @@ typedef struct Brush {
float rgb[3]; /* color */
float alpha; /* opacity */
float secondary_rgb[3]; /* background color */
int sculpt_plane; /* the direction of movement for sculpt vertices */
float plane_offset; /* offset for plane brushes (clay, flatten, fill, scrape) */
float pad;
int gradient_spacing;
int gradient_stroke_mode; /* source for stroke color gradient application */
int gradient_fill_mode; /* source for fill tool color gradient application */
char sculpt_tool; /* active sculpt tool */
char vertexpaint_tool; /* active vertex/weight paint blend mode (poorly named) */
char imagepaint_tool; /* active image paint tool */
@@ -100,12 +112,21 @@ typedef struct Brush {
float texture_sample_bias;
/* overlay */
int texture_overlay_alpha;
int mask_overlay_alpha;
int cursor_overlay_alpha;
float unprojected_radius;
/* soften/sharpen */
float sharp_threshold;
int blur_kernel_radius;
int blur_mode;
/* fill tool */
float fill_threshold;
float add_col[3];
float sub_col[3];
@@ -116,6 +137,52 @@ typedef struct Brush {
float mask_stencil_dimension[2];
} Brush;
typedef struct PaletteColor
{
struct PaletteColor *next, *prev;
/* two values, one to store rgb, other to store values for sculpt/weight */
float rgb[3];
float value;
} PaletteColor;
typedef struct Palette
{
ID id;
/* pointer to individual colours */
ListBase colors;
ListBase deleted;
int num_of_colours;
int active_color;
} Palette;
typedef struct PaintCurvePoint
{
BezTriple bez; /* bezier handle */
float pressure; /* pressure on that point */
} PaintCurvePoint;
typedef struct PaintCurve
{
ID id;
PaintCurvePoint *points; /* points of curve */
int tot_points;
int add_index; /* index where next point will be added */
} PaintCurve;
/* Brush.gradient_source */
typedef enum BrushGradientSourceStroke {
BRUSH_GRADIENT_PRESSURE = 0, /* gradient from pressure */
BRUSH_GRADIENT_SPACING_REPEAT = 1, /* gradient from spacing */
BRUSH_GRADIENT_SPACING_CLAMP = 2 /* gradient from spacing */
} BrushGradientSourceStroke;
typedef enum BrushGradientSourceFill {
BRUSH_GRADIENT_LINEAR = 0, /* gradient from pressure */
BRUSH_GRADIENT_RADIAL = 1 /* gradient from spacing */
} BrushGradientSourceFill;
/* Brush.flag */
typedef enum BrushFlags {
BRUSH_AIRBRUSH = (1 << 0),
@@ -124,7 +191,7 @@ typedef enum BrushFlags {
BRUSH_SIZE_PRESSURE = (1 << 3),
BRUSH_JITTER_PRESSURE = (1 << 4),
BRUSH_SPACING_PRESSURE = (1 << 5),
// BRUSH_FIXED_TEX = (1 << 6), /* obsolete, use mtex->brush_map_mode = MTEX_MAP_MODE_TILED instead */
BRUSH_UNUSED = (1 << 6),
BRUSH_RAKE = (1 << 7),
BRUSH_ANCHORED = (1 << 8),
BRUSH_DIR_IN = (1 << 9),
@@ -138,7 +205,7 @@ typedef enum BrushFlags {
BRUSH_SPACE_ATTEN = (1 << 18),
BRUSH_ADAPTIVE_SPACE = (1 << 19),
BRUSH_LOCK_SIZE = (1 << 20),
// BRUSH_TEXTURE_OVERLAY = (1 << 21), /* obsolete, use overlay_flags |= BRUSH_OVERLAY_PRIMARY instead */
BRUSH_USE_GRADIENT = (1 << 21),
BRUSH_EDGE_TO_EDGE = (1 << 22),
BRUSH_DRAG_DOT = (1 << 23),
BRUSH_INVERSE_SMOOTH_PRESSURE = (1 << 24),
@@ -146,13 +213,16 @@ typedef enum BrushFlags {
BRUSH_PLANE_TRIM = (1 << 26),
BRUSH_FRONTFACE = (1 << 27),
BRUSH_CUSTOM_ICON = (1 << 28),
/* temporary flag which sets up automatically for correct brush
* drawing when inverted modal operator is running */
BRUSH_INVERTED = (1 << 29),
BRUSH_ABSOLUTE_JITTER = (1 << 30)
BRUSH_LINE = (1 << 29),
BRUSH_ABSOLUTE_JITTER = (1 << 30),
BRUSH_CURVE = (1 << 31)
} BrushFlags;
typedef enum {
BRUSH_MASK_PRESSURE_RAMP = (1 << 1),
BRUSH_MASK_PRESSURE_CUTOFF = (1 << 2)
} BrushMaskPressureFlags;
/* Brush.overlay_flags */
typedef enum OverlayFlags {
BRUSH_OVERLAY_CURSOR = (1),
@@ -195,7 +265,9 @@ typedef enum BrushImagePaintTool {
PAINT_TOOL_DRAW = 0,
PAINT_TOOL_SOFTEN = 1,
PAINT_TOOL_SMEAR = 2,
PAINT_TOOL_CLONE = 3
PAINT_TOOL_CLONE = 3,
PAINT_TOOL_FILL = 4,
PAINT_TOOL_MASK = 5
} BrushImagePaintTool;
/* direction that the brush displaces along */
@@ -222,6 +294,12 @@ typedef enum {
BRUSH_MASK_SMOOTH = 1
} BrushMaskTool;
/* blur kernel types, Brush.blur_mode */
typedef enum BlurKernelType {
KERNEL_GAUSSIAN,
KERNEL_BOX
} BlurKernelType;
#define MAX_BRUSH_PIXEL_RADIUS 200
#endif
+14 -1
View File
@@ -41,6 +41,7 @@
#endif
struct MTex;
struct Image;
struct ColorBand;
struct Group;
struct bNodeTree;
@@ -82,6 +83,11 @@ typedef struct GameSettings {
int pad1;
} GameSettings;
typedef struct TexPaintSlot {
struct Image *ima; /* image to be painted on */
char uvname[64]; /* customdata index for uv layer, MAX_NAME*/
} TexPaintSlot;
typedef struct Material {
ID id;
struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
@@ -182,8 +188,15 @@ typedef struct Material {
float line_col[4];
short line_priority;
short vcol_alpha;
int pad4;
/* texture painting */
short paint_active_slot;
short paint_clone_slot;
short tot_slots;
short pad4[3];
struct TexPaintSlot *texpaintslot; /* cached slot for painting. Make sure to recalculate before use
* with refresh_texpaint_image_cache */
ListBase gpumaterial; /* runtime */
} Material;
+27 -6
View File
@@ -811,7 +811,8 @@ typedef struct TimeMarker {
/* Paint Tool Base */
typedef struct Paint {
struct Brush *brush;
struct Palette *palette;
/* WM Paint cursor */
void *paint_cursor;
unsigned char paint_cursor_col[4];
@@ -840,9 +841,17 @@ typedef struct ImagePaintSettings {
short seam_bleed, normal_angle;
short screen_grab_size[2]; /* capture size for re-projection */
/* new layer default resolution */
int slot_xresolution_default;
int slot_yresolution_default;
int pad1;
void *paintcursor; /* wm handle */
struct Image *stencil; /* workaround until we support true layer masks */
float slot_color_default[4];
float stencil_col[3];
float pad2;
} ImagePaintSettings;
/* ------------------------------------------- */
@@ -966,6 +975,11 @@ typedef struct UnifiedPaintSettings {
/* unified brush weight, [0, 1] */
float weight;
/* unified brush color */
float rgb[3];
/* unified brush secondary color */
float secondary_rgb[3];
/* user preferences for sculpt and paint */
int flag;
@@ -973,7 +987,6 @@ typedef struct UnifiedPaintSettings {
/* record movement of mouse so that rake can start at an intuitive angle */
float last_rake[2];
int pad;
float brush_rotation;
@@ -981,7 +994,14 @@ typedef struct UnifiedPaintSettings {
* all data below are used to communicate with cursor drawing and tex sampling *
*********************************************************************************/
int draw_anchored;
int anchored_size;
int anchored_size;
char draw_inverted;
char pad3[7];
float overlap_factor; /* normalization factor due to accumulated value of curve along spacing.
* Calculated when brush spacing changes to dampen strength of stroke
* if space attenuation is used*/
float anchored_initial_mouse[2];
/* check is there an ongoing stroke right now */
@@ -1001,15 +1021,16 @@ typedef struct UnifiedPaintSettings {
struct ColorSpace *colorspace;
/* radius of brush, premultiplied with pressure.
* In case of anchored brushes contains that radius */
* In case of anchored brushes contains the anchored radius */
float pixel_radius;
int pad2;
int pad4;
} UnifiedPaintSettings;
typedef enum {
UNIFIED_PAINT_SIZE = (1 << 0),
UNIFIED_PAINT_ALPHA = (1 << 1),
UNIFIED_PAINT_WEIGHT = (1 << 5),
UNIFIED_PAINT_COLOR = (1 << 6),
/* only used if unified size is enabled, mirrors the brush flags
* BRUSH_LOCK_SIZE and BRUSH_SIZE_PRESSURE */
@@ -1647,7 +1668,7 @@ enum {
typedef enum {
PAINT_SHOW_BRUSH = (1 << 0),
PAINT_FAST_NAVIGATE = (1 << 1),
PAINT_SHOW_BRUSH_ON_SURFACE = (1 << 2),
PAINT_SHOW_BRUSH_ON_SURFACE = (1 << 2)
} PaintFlags;
/* Paint.symmetry_flags
@@ -809,6 +809,8 @@ typedef enum eSpaceImage_Flag {
SI_DRAW_OTHER = (1 << 23),
SI_COLOR_CORRECTION = (1 << 24),
SI_NO_DRAW_TEXPAINT = (1 << 25)
} eSpaceImage_Flag;
/* Text Editor ============================================ */
+3 -1
View File
@@ -154,7 +154,6 @@ typedef struct uiGradientColors {
char high_gradient[4];
int show_grad;
int pad2;
} uiGradientColors;
typedef struct ThemeUI {
@@ -328,6 +327,9 @@ typedef struct ThemeSpace {
char info_warning[4], info_warning_text[4];
char info_info[4], info_info_text[4];
char info_debug[4], info_debug_text[4];
char paint_curve_pivot[4];
char paint_curve_handle[4];
} ThemeSpace;
+3
View File
@@ -427,6 +427,9 @@ extern StructRNA RNA_OrController;
extern StructRNA RNA_OutflowFluidSettings;
extern StructRNA RNA_PackedFile;
extern StructRNA RNA_Paint;
extern StructRNA RNA_PaintCurve;
extern StructRNA RNA_Palette;
extern StructRNA RNA_PaletteColor;
extern StructRNA RNA_Panel;
extern StructRNA RNA_Particle;
extern StructRNA RNA_ParticleBrush;
+5
View File
@@ -153,6 +153,8 @@ short RNA_type_to_ID_code(StructRNA *type)
if (RNA_struct_is_a(type, &RNA_WindowManager)) return ID_WM;
if (RNA_struct_is_a(type, &RNA_MovieClip)) return ID_MC;
if (RNA_struct_is_a(type, &RNA_Mask)) return ID_MSK;
if (RNA_struct_is_a(type, &RNA_Palette)) return ID_PAL;
if (RNA_struct_is_a(type, &RNA_PaintCurve)) return ID_PC;
return 0;
}
@@ -190,6 +192,9 @@ StructRNA *ID_code_to_RNA_type(short idcode)
case ID_WM: return &RNA_WindowManager;
case ID_MC: return &RNA_MovieClip;
case ID_MSK: return &RNA_Mask;
case ID_PAL: return &RNA_Palette;
case ID_PC: return &RNA_PaintCurve;
default: return &RNA_ID;
}
}
+307 -44
View File
@@ -55,6 +55,8 @@ static EnumPropertyItem sculpt_stroke_method_items[] = {
{BRUSH_SPACE, "SPACE", 0, "Space", "Limit brush application to the distance specified by spacing"},
{BRUSH_AIRBRUSH, "AIRBRUSH", 0, "Airbrush", "Keep applying paint effect while holding mouse (spray)"},
{BRUSH_ANCHORED, "ANCHORED", 0, "Anchored", "Keep the brush anchored to the initial location"},
{BRUSH_LINE, "LINE", 0, "Line", "Draw a line with dabs separated according to spacing"},
{BRUSH_CURVE, "CURVE", 0, "Curve", "Define the stroke curve with a bezier curve. Dabs are separated according to spacing"},
{0, NULL, 0, NULL, NULL}
};
@@ -99,6 +101,8 @@ EnumPropertyItem brush_image_tool_items[] = {
{PAINT_TOOL_SOFTEN, "SOFTEN", ICON_BRUSH_SOFTEN, "Soften", ""},
{PAINT_TOOL_SMEAR, "SMEAR", ICON_BRUSH_SMEAR, "Smear", ""},
{PAINT_TOOL_CLONE, "CLONE", ICON_BRUSH_CLONE, "Clone", ""},
{PAINT_TOOL_FILL, "FILL", ICON_BRUSH_TEXFILL, "Fill", ""},
{PAINT_TOOL_MASK, "MASK", ICON_BRUSH_TEXMASK, "Mask", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -222,17 +226,35 @@ static int rna_SculptToolCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
Brush *br = (Brush *)ptr->data;
return (!(br->flag & BRUSH_ANCHORED) &&
!(br->flag & BRUSH_DRAG_DOT) &&
!ELEM(br->sculpt_tool,
SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
!(br->flag & BRUSH_LINE) &&
!(br->flag & BRUSH_CURVE) &&
!ELEM(br->sculpt_tool,
SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB));
}
static int rna_BrushCapabilities_has_smooth_stroke_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return (!(br->flag & BRUSH_ANCHORED) &&
!(br->flag & BRUSH_DRAG_DOT) &&
!(br->flag & BRUSH_LINE) &&
!(br->flag & BRUSH_CURVE));
}
static int rna_SculptToolCapabilities_has_space_attenuation_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return ((br->flag & BRUSH_SPACE) &&
!ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SNAKE_HOOK));
return ((br->flag & (BRUSH_SPACE | BRUSH_LINE | BRUSH_CURVE)) &&
!ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SNAKE_HOOK));
}
static int rna_ImapaintToolCapabilities_has_space_attenuation_get(PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
return (br->flag & (BRUSH_SPACE | BRUSH_LINE | BRUSH_CURVE)) &&
br->imagepaint_tool != PAINT_TOOL_FILL;
}
static int rna_BrushCapabilities_has_spacing_get(PointerRNA *ptr)
@@ -273,11 +295,40 @@ static int rna_BrushCapabilities_has_texture_angle_source_get(PointerRNA *ptr)
MTEX_MAP_MODE_RANDOM);
}
static PointerRNA rna_Sculpt_sculpt_tool_capabilities_get(PointerRNA *ptr)
static int rna_ImapaintToolCapabilities_has_accumulate_get(PointerRNA *ptr)
{
/* only support for draw tool */
Brush *br = (Brush *)ptr->data;
return ((br->flag & BRUSH_AIRBRUSH) ||
(br->flag & BRUSH_DRAG_DOT) ||
(br->flag & BRUSH_ANCHORED) ||
(br->imagepaint_tool == PAINT_TOOL_SOFTEN) ||
(br->imagepaint_tool == PAINT_TOOL_SMEAR) ||
(br->imagepaint_tool == PAINT_TOOL_FILL) ||
(br->mtex.tex && !ELEM(br->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_STENCIL, MTEX_MAP_MODE_3D))
) ? false : true;
}
static int rna_ImapaintToolCapabilities_has_radius_get(PointerRNA *ptr)
{
/* only support for draw tool */
Brush *br = (Brush *)ptr->data;
return (br->imagepaint_tool != PAINT_TOOL_FILL);
}
static PointerRNA rna_Sculpt_tool_capabilities_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_SculptToolCapabilities, ptr->id.data);
}
static PointerRNA rna_Imapaint_tool_capabilities_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_ImapaintToolCapabilities, ptr->id.data);
}
static PointerRNA rna_Brush_capabilities_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilities, ptr->id.data);
@@ -328,7 +379,6 @@ static void rna_Brush_size_update(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Brush_sculpt_tool_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
BKE_paint_invalidate_overlay_all();
rna_Brush_reset_icon(br, "sculpt");
rna_Brush_update(bmain, scene, ptr);
}
@@ -336,7 +386,6 @@ static void rna_Brush_sculpt_tool_update(Main *bmain, Scene *scene, PointerRNA *
static void rna_Brush_vertex_tool_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
BKE_paint_invalidate_overlay_all();
rna_Brush_reset_icon(br, "vertex_paint");
rna_Brush_update(bmain, scene, ptr);
}
@@ -344,11 +393,16 @@ static void rna_Brush_vertex_tool_update(Main *bmain, Scene *scene, PointerRNA *
static void rna_Brush_imagepaint_tool_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
BKE_paint_invalidate_overlay_all();
rna_Brush_reset_icon(br, "image_paint");
rna_Brush_update(bmain, scene, ptr);
}
static void rna_Brush_stroke_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, scene);
rna_Brush_update(bmain, scene, ptr);
}
static void rna_Brush_icon_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Brush *br = (Brush *)ptr->data;
@@ -388,6 +442,17 @@ static void rna_Brush_set_size(PointerRNA *ptr, int value)
brush->size = value;
}
static void rna_Brush_use_gradient_set(PointerRNA *ptr, int value)
{
Brush *br = (Brush *)ptr->data;
if (value) br->flag |= BRUSH_USE_GRADIENT;
else br->flag &= ~BRUSH_USE_GRADIENT;
if ((br->flag & BRUSH_USE_GRADIENT) && br->gradient == NULL)
br->gradient = add_colorband(true);
}
static void rna_Brush_set_unprojected_radius(PointerRNA *ptr, float value)
{
Brush *brush = ptr->data;
@@ -397,13 +462,16 @@ static void rna_Brush_set_unprojected_radius(PointerRNA *ptr, float value)
brush->unprojected_radius = value;
}
static EnumPropertyItem *rna_Brush_direction_itemf(bContext *UNUSED(C), PointerRNA *ptr,
static EnumPropertyItem *rna_Brush_direction_itemf(bContext *C, PointerRNA *ptr,
PropertyRNA *UNUSED(prop), bool *UNUSED(r_free))
{
PaintMode mode = BKE_paintmode_get_active_from_context(C);
static EnumPropertyItem prop_default_items[] = {
{0, NULL, 0, NULL, NULL}
};
/* sculpt mode */
static EnumPropertyItem prop_flatten_contrast_items[] = {
{0, "FLATTEN", 0, "Flatten", "Add effect of brush"},
{BRUSH_DIR_IN, "CONTRAST", 0, "Contrast", "Subtract effect of brush"},
@@ -434,41 +502,66 @@ static EnumPropertyItem *rna_Brush_direction_itemf(bContext *UNUSED(C), PointerR
{0, NULL, 0, NULL, NULL}
};
/* texture paint mode */
static EnumPropertyItem prop_soften_sharpen_items[] = {
{0, "SOFTEN", 0, "Soften", "Blur effect of brush"},
{BRUSH_DIR_IN, "SHARPEN", 0, "Sharpen", "Sharpen effect of brush"},
{0, NULL, 0, NULL, NULL}
};
Brush *me = (Brush *)(ptr->data);
switch (me->sculpt_tool) {
case SCULPT_TOOL_DRAW:
case SCULPT_TOOL_CREASE:
case SCULPT_TOOL_BLOB:
case SCULPT_TOOL_LAYER:
case SCULPT_TOOL_CLAY:
case SCULPT_TOOL_CLAY_STRIPS:
return prop_direction_items;
case SCULPT_TOOL_MASK:
switch ((BrushMaskTool)me->mask_tool) {
case BRUSH_MASK_DRAW:
switch (mode) {
case PAINT_SCULPT:
switch (me->sculpt_tool) {
case SCULPT_TOOL_DRAW:
case SCULPT_TOOL_CREASE:
case SCULPT_TOOL_BLOB:
case SCULPT_TOOL_LAYER:
case SCULPT_TOOL_CLAY:
case SCULPT_TOOL_CLAY_STRIPS:
return prop_direction_items;
break;
case BRUSH_MASK_SMOOTH:
case SCULPT_TOOL_MASK:
switch ((BrushMaskTool)me->mask_tool) {
case BRUSH_MASK_DRAW:
return prop_direction_items;
break;
case BRUSH_MASK_SMOOTH:
return prop_default_items;
break;
}
case SCULPT_TOOL_FLATTEN:
return prop_flatten_contrast_items;
case SCULPT_TOOL_FILL:
return prop_fill_deepen_items;
case SCULPT_TOOL_SCRAPE:
return prop_scrape_peaks_items;
case SCULPT_TOOL_PINCH:
return prop_pinch_magnify_items;
case SCULPT_TOOL_INFLATE:
return prop_inflate_deflate_items;
default:
return prop_default_items;
break;
}
break;
case SCULPT_TOOL_FLATTEN:
return prop_flatten_contrast_items;
case PAINT_TEXTURE_2D:
case PAINT_TEXTURE_PROJECTIVE:
switch (me->imagepaint_tool) {
case PAINT_TOOL_SOFTEN:
return prop_soften_sharpen_items;
case SCULPT_TOOL_FILL:
return prop_fill_deepen_items;
case SCULPT_TOOL_SCRAPE:
return prop_scrape_peaks_items;
case SCULPT_TOOL_PINCH:
return prop_pinch_magnify_items;
case SCULPT_TOOL_INFLATE:
return prop_inflate_deflate_items;
default:
return prop_default_items;
}
break;
default:
return prop_default_items;
@@ -484,11 +577,15 @@ static EnumPropertyItem *rna_Brush_stroke_itemf(bContext *C, PointerRNA *UNUSED(
{0, "DOTS", 0, "Dots", "Apply paint on each mouse move step"},
{BRUSH_SPACE, "SPACE", 0, "Space", "Limit brush application to the distance specified by spacing"},
{BRUSH_AIRBRUSH, "AIRBRUSH", 0, "Airbrush", "Keep applying paint effect while holding mouse (spray)"},
{BRUSH_LINE, "LINE", 0, "Line", "Drag a line with dabs separated according to spacing"},
{BRUSH_CURVE, "CURVE", 0, "Curve", "Define the stroke curve with a bezier curve. Dabs are separated according to spacing"},
{0, NULL, 0, NULL, NULL}
};
switch (mode) {
case PAINT_SCULPT:
case PAINT_TEXTURE_2D:
case PAINT_TEXTURE_PROJECTIVE:
return sculpt_stroke_method_items;
default:
@@ -622,10 +719,39 @@ static void rna_def_brush_capabilities(BlenderRNA *brna)
BRUSH_CAPABILITY(has_texture_angle, "Has Texture Angle");
BRUSH_CAPABILITY(has_texture_angle_source, "Has Texture Angle Source");
BRUSH_CAPABILITY(has_spacing, "Has Spacing");
BRUSH_CAPABILITY(has_smooth_stroke, "Has Smooth Stroke");
#undef BRUSH_CAPABILITY
}
static void rna_def_image_paint_capabilities(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "ImapaintToolCapabilities", NULL);
RNA_def_struct_sdna(srna, "Brush");
RNA_def_struct_nested(brna, srna, "Brush");
RNA_def_struct_ui_text(srna, "Image Paint Capabilities",
"Read-only indications of which brush operations "
"are supported by the current image paint brush");
#define IMAPAINT_TOOL_CAPABILITY(prop_name_, ui_name_) \
prop = RNA_def_property(srna, #prop_name_, \
PROP_BOOLEAN, PROP_NONE); \
RNA_def_property_clear_flag(prop, PROP_EDITABLE); \
RNA_def_property_boolean_funcs(prop, "rna_ImapaintToolCapabilities_" \
#prop_name_ "_get", NULL); \
RNA_def_property_ui_text(prop, ui_name_, NULL)
IMAPAINT_TOOL_CAPABILITY(has_accumulate, "Has Accumulate");
IMAPAINT_TOOL_CAPABILITY(has_space_attenuation, "Has Space Attenuation");
IMAPAINT_TOOL_CAPABILITY(has_radius, "Has Radius");
#undef IMAPAINT_TOOL_CAPABILITY
}
static void rna_def_brush(BlenderRNA *brna)
{
StructRNA *srna;
@@ -640,6 +766,22 @@ static void rna_def_brush(BlenderRNA *brna)
{IMB_BLEND_DARKEN, "DARKEN", 0, "Darken", "Use darken blending mode while painting"},
{IMB_BLEND_ERASE_ALPHA, "ERASE_ALPHA", 0, "Erase Alpha", "Erase alpha while painting"},
{IMB_BLEND_ADD_ALPHA, "ADD_ALPHA", 0, "Add Alpha", "Add alpha while painting"},
{IMB_BLEND_OVERLAY, "OVERLAY", 0, "Overlay", "Use overlay blending mode while painting"},
{IMB_BLEND_HARDLIGHT, "HARDLIGHT", 0, "Hard light", "Use hard light blending mode while painting"},
{IMB_BLEND_COLORBURN, "COLORBURN", 0, "Color burn", "Use color burn blending mode while painting"},
{IMB_BLEND_LINEARBURN, "LINEARBURN", 0, "Linear burn", "Use linear burn blending mode while painting"},
{IMB_BLEND_COLORDODGE, "COLORDODGE", 0, "Color dodge", "Use color dodge blending mode while painting"},
{IMB_BLEND_SCREEN, "SCREEN", 0, "Screen", "Use screen blending mode while painting"},
{IMB_BLEND_SOFTLIGHT, "SOFTLIGHT", 0, "Soft light", "Use softlight blending mode while painting"},
{IMB_BLEND_PINLIGHT, "PINLIGHT", 0, "Pin light", "Use pinlight blending mode while painting"},
{IMB_BLEND_VIVIDLIGHT, "VIVIDLIGHT", 0, "Vivid light", "Use vividlight blending mode while painting"},
{IMB_BLEND_LINEARLIGHT, "LINEARLIGHT", 0, "Linear light", "Use linearlight blending mode while painting"},
{IMB_BLEND_DIFFERENCE, "DIFFERENCE", 0, "Difference", "Use difference blending mode while painting"},
{IMB_BLEND_EXCLUSION, "EXCLUSION", 0, "Exclusion", "Use exclusion blending mode while painting"},
{IMB_BLEND_HUE, "HUE", 0, "Hue", "Use hue blending mode while painting"},
{IMB_BLEND_SATURATION, "SATURATION", 0, "Saturation", "Use saturation blending mode while painting"},
{IMB_BLEND_LUMINOSITY, "LUMINOSITY", 0, "Luminosity", "Use luminosity blending mode while painting"},
{IMB_BLEND_COLOR, "COLOR", 0, "Color", "Use color blending mode while painting"},
{0, NULL, 0, NULL, NULL}
};
@@ -671,6 +813,32 @@ static void rna_def_brush(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem brush_blur_mode_items[] = {
{KERNEL_BOX, "BOX", 0, "Box", ""},
{KERNEL_GAUSSIAN, "GAUSSIAN", 0, "Gaussian", ""},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem brush_gradient_items[] = {
{BRUSH_GRADIENT_PRESSURE, "PRESSURE", 0, "Pressure", ""},
{BRUSH_GRADIENT_SPACING_REPEAT, "SPACING_REPEAT", 0, "Repeat", ""},
{BRUSH_GRADIENT_SPACING_CLAMP, "SPACING_CLAMP", 0, "Clamp", ""},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem brush_gradient_fill_items[] = {
{BRUSH_GRADIENT_LINEAR, "LINEAR", 0, "Linear", ""},
{BRUSH_GRADIENT_RADIAL, "RADIAL", 0, "Radial", ""},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem brush_mask_pressure_items[] = {
{0, "NONE", 0, "Off", ""},
{BRUSH_MASK_PRESSURE_RAMP, "RAMP", ICON_STYLUS_PRESSURE, "Ramp", ""},
{BRUSH_MASK_PRESSURE_CUTOFF, "CUTOFF", ICON_STYLUS_PRESSURE, "Cutoff", ""},
{0, NULL, 0, NULL, NULL}
};
srna = RNA_def_struct(brna, "Brush", "ID");
RNA_def_struct_ui_text(srna, "Brush", "Brush datablock for storing brush settings for painting and sculpting");
RNA_def_struct_ui_icon(srna, ICON_BRUSH_DATA);
@@ -710,7 +878,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_enum_items(prop, sculpt_stroke_method_items);
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Brush_stroke_itemf");
RNA_def_property_ui_text(prop, "Stroke Method", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
RNA_def_property_update(prop, 0, "rna_Brush_stroke_update");
prop = RNA_def_property(srna, "texture_angle_source_random", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
@@ -769,6 +937,13 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Spacing", "Spacing between brush daubs as a percentage of brush diameter");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "grad_spacing", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "gradient_spacing");
RNA_def_property_range(prop, 1, 10000);
RNA_def_property_ui_range(prop, 1, 10000, 5, -1);
RNA_def_property_ui_text(prop, "Gradient Spacing", "Spacing before brush gradient goes full circle");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "smooth_stroke_radius", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 10, 200);
RNA_def_property_ui_text(prop, "Smooth Stroke Radius", "Minimum distance from last point before stroke continues");
@@ -791,7 +966,13 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "rgb");
RNA_def_property_ui_text(prop, "Color", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "secondary_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "secondary_rgb");
RNA_def_property_ui_text(prop, "Secondary Color", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -884,6 +1065,32 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Mask Stencil Dimensions", "Dimensions of mask stencil in viewport");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "sharp_threshold", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 100.0);
RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 3);
RNA_def_property_float_sdna(prop, NULL, "sharp_threshold");
RNA_def_property_ui_text(prop, "Sharp Threshold", "Threshold below which, no sharpening is done");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "fill_threshold", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 100.0);
RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 3);
RNA_def_property_float_sdna(prop, NULL, "fill_threshold");
RNA_def_property_ui_text(prop, "Fill Threshold", "Threshold above which filling is not propagated");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "blur_kernel_radius", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "blur_kernel_radius");
RNA_def_property_range(prop, 1, 10000);
RNA_def_property_ui_range(prop, 1, 50, 1, -1);
RNA_def_property_ui_text(prop, "Kernel Radius", "Radius of kernel used for soften and sharpen in pixels");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "blur_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, brush_blur_mode_items);
RNA_def_property_ui_text(prop, "Blur Mode", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
/* flag */
prop = RNA_def_property(srna, "use_airbrush", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_AIRBRUSH);
@@ -919,7 +1126,13 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
RNA_def_property_ui_text(prop, "Size Pressure", "Enable tablet pressure sensitivity for size");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "use_gradient", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_USE_GRADIENT);
RNA_def_property_boolean_funcs(prop, NULL, "rna_Brush_use_gradient_set");
RNA_def_property_ui_text(prop, "Use Gradient", "Use Gradient by utilizing a sampling method");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "use_pressure_jitter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_JITTER_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
@@ -932,6 +1145,12 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Spacing Pressure", "Enable tablet pressure sensitivity for spacing");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "use_pressure_masking", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mask_pressure");
RNA_def_property_enum_items(prop, brush_mask_pressure_items);
RNA_def_property_ui_text(prop, "Mask Pressure Mode", "Pen pressure makes texture influence smaller");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "use_inverse_smooth_pressure", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_INVERSE_SMOOTH_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
@@ -974,6 +1193,16 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Space", "Limit brush application to the distance specified by spacing");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "use_line", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_LINE);
RNA_def_property_ui_text(prop, "Line", "Draw a line with dabs separated according to spacing");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "use_curve", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_CURVE);
RNA_def_property_ui_text(prop, "Curve", "Define the stroke curve with a bezier curve. Dabs are separated according to spacing");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "use_smooth_stroke", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SMOOTH_STROKE);
RNA_def_property_ui_text(prop, "Smooth Stroke", "Brush lags behind mouse and follows a smoother path");
@@ -1015,7 +1244,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Edge-to-edge", "Drag anchor brush from edge-to-edge");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "use_drag_dot", PROP_BOOLEAN, PROP_NONE);
prop = RNA_def_property(srna, "use_restore_mesh", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_DRAG_DOT);
RNA_def_property_ui_text(prop, "Restore Mesh", "Allow a single dot to be carefully positioned");
RNA_def_property_update(prop, 0, "rna_Brush_update");
@@ -1031,6 +1260,28 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Curve", "Editable falloff curve");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "paint_curve", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Paint Curve", "Active Paint Curve");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "gradient", PROP_POINTER, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "gradient");
RNA_def_property_struct_type(prop, "ColorRamp");
RNA_def_property_ui_text(prop, "Gradient", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
/* gradient source */
prop = RNA_def_property(srna, "gradient_stroke_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, brush_gradient_items);
RNA_def_property_ui_text(prop, "Gradient Stroke Mode", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "gradient_fill_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, brush_gradient_fill_items);
RNA_def_property_ui_text(prop, "Gradient Fill Mode", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
/* overlay flags */
prop = RNA_def_property(srna, "use_primary_overlay", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay_flags", BRUSH_OVERLAY_PRIMARY);
@@ -1173,8 +1424,14 @@ static void rna_def_brush(BlenderRNA *brna)
prop = RNA_def_property(srna, "sculpt_capabilities", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "SculptToolCapabilities");
RNA_def_property_pointer_funcs(prop, "rna_Sculpt_sculpt_tool_capabilities_get", NULL, NULL, NULL);
RNA_def_property_pointer_funcs(prop, "rna_Sculpt_tool_capabilities_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Sculpt Capabilities", "Brush's capabilities in sculpt mode");
prop = RNA_def_property(srna, "image_paint_capabilities", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "ImapaintToolCapabilities");
RNA_def_property_pointer_funcs(prop, "rna_Imapaint_tool_capabilities_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Image Painting Capabilities", "Brush's capabilities in image paint mode");
}
@@ -1211,6 +1468,11 @@ static void rna_def_operator_stroke_element(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Pressure", "Tablet pressure");
prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE);
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_text(prop, "Brush Size", "Brush Size in screen space");
prop = RNA_def_property(srna, "pen_flip", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_ui_text(prop, "Flip", "");
@@ -1237,6 +1499,7 @@ void RNA_def_brush(BlenderRNA *brna)
rna_def_brush(brna);
rna_def_brush_capabilities(brna);
rna_def_sculpt_capabilities(brna);
rna_def_image_paint_capabilities(brna);
rna_def_brush_texture_slot(brna);
rna_def_operator_stroke_element(brna);
}
@@ -202,6 +202,7 @@ void rna_def_texmat_common(struct StructRNA *srna, const char *texspace_editable
void rna_def_mtex_common(struct BlenderRNA *brna, struct StructRNA *srna, const char *begin, const char *activeget,
const char *activeset, const char *activeeditable, const char *structname,
const char *structname_slots, const char *update, const char *update_index);
void rna_def_mtex_texpaint(struct StructRNA *srna);
void rna_def_render_layer_common(struct StructRNA *srna, int scene);
void rna_def_actionbone_group_common(struct StructRNA *srna, int update_flag, const char *update_cb);
@@ -82,6 +82,8 @@ EnumPropertyItem ramp_blend_items[] = {
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
@@ -92,6 +94,8 @@ EnumPropertyItem ramp_blend_items[] = {
#include "BKE_paint.h"
#include "ED_node.h"
#include "ED_image.h"
#include "BKE_scene.h"
static void rna_Material_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
@@ -165,6 +169,50 @@ static void rna_Material_mtex_begin(CollectionPropertyIterator *iter, PointerRNA
rna_iterator_array_begin(iter, (void *)ma->mtex, sizeof(MTex *), MAX_MTEX, 0, NULL);
}
static void rna_Material_texpaint_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Material *ma = (Material *)ptr->data;
rna_iterator_array_begin(iter, (void *)ma->texpaintslot, sizeof(TexPaintSlot), ma->tot_slots, 0, NULL);
}
static void rna_Material_active_paint_texture_index_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
bScreen *sc;
Material *ma = ptr->id.data;
if (ma->use_nodes && ma->nodetree && BKE_scene_use_new_shading_nodes(scene)) {
struct bNode *node;
int index = 0;
for (node = ma->nodetree->nodes.first; node; node = node->next) {
if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
if (index++ == ma->paint_active_slot) {
break;
}
}
}
if (node)
nodeSetActive(ma->nodetree, node);
}
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
SpaceLink *sl;
for (sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
ED_space_image_set(sima, scene, scene->obedit, ma->texpaintslot[ma->paint_active_slot].ima);
}
}
}
}
DAG_id_tag_update(&ma->id, 0);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING, ma);
}
static PointerRNA rna_Material_active_texture_get(PointerRNA *ptr)
{
Material *ma = (Material *)ptr->data;
@@ -2059,6 +2107,8 @@ void RNA_def_material(BlenderRNA *brna)
"rna_Material_active_texture_set", "rna_Material_active_texture_editable",
"MaterialTextureSlot", "MaterialTextureSlots", "rna_Material_update", "rna_Material_update");
rna_def_mtex_texpaint(srna);
/* only material has this one */
prop = RNA_def_property(srna, "use_textures", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "septex", 1);
@@ -2147,4 +2197,27 @@ void rna_def_mtex_common(BlenderRNA *brna, StructRNA *srna, const char *begin,
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, update_index);
}
void rna_def_mtex_texpaint(StructRNA *srna)
{
PropertyRNA *prop;
/* mtex */
prop = RNA_def_property(srna, "texture_paint_slots", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_funcs(prop, "rna_Material_texpaint_begin", "rna_iterator_array_next", "rna_iterator_array_end",
"rna_iterator_array_dereference_get", NULL, NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "Image");
RNA_def_property_ui_text(prop, "Textures", "Texture slots defining the mapping and influence of textures");
prop = RNA_def_property(srna, "paint_active_slot", PROP_INT, PROP_UNSIGNED);
RNA_def_property_range(prop, 0, INT_MAX);
RNA_def_property_ui_text(prop, "Active Paint Texture Index", "Index of active texture paint slot");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_Material_active_paint_texture_index_update");
prop = RNA_def_property(srna, "paint_clone_slot", PROP_INT, PROP_UNSIGNED);
RNA_def_property_range(prop, 0, INT_MAX);
RNA_def_property_ui_text(prop, "Clone Paint Texture Index", "Index of clone texture paint slot");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, NULL);
}
#endif
@@ -3121,11 +3121,13 @@ static void rna_def_mesh(BlenderRNA *brna)
"rna_Mesh_uv_texture_stencil_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Mask UV Map", "UV map to mask the painted area");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
prop = RNA_def_property(srna, "uv_texture_stencil_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_funcs(prop, "rna_Mesh_uv_texture_stencil_index_get",
"rna_Mesh_uv_texture_stencil_index_set", "rna_Mesh_uv_texture_index_range");
RNA_def_property_ui_text(prop, "Mask UV Map Index", "Mask UV map index");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
/* Tessellated face colors - used by renderers */
@@ -2120,6 +2120,11 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Unified Weight",
"Instead of per-brush weight, the weight is shared across brushes");
prop = RNA_def_property(srna, "use_unified_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", UNIFIED_PAINT_COLOR);
RNA_def_property_ui_text(prop, "Use Unified Color",
"Instead of per-brush color, the color is shared across brushes");
/* unified paint settings that override the equivalent settings
* from the active brush */
prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
@@ -2152,6 +2157,18 @@ 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);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "rgb");
RNA_def_property_ui_text(prop, "Color", "");
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
prop = RNA_def_property(srna, "secondary_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "secondary_rgb");
RNA_def_property_ui_text(prop, "Secondary Color", "");
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
prop = RNA_def_property(srna, "use_pressure_size", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", UNIFIED_PAINT_BRUSH_SIZE_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
@@ -285,8 +285,67 @@ static void rna_Paint_brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
BKE_paint_invalidate_overlay_all();
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
}
static void rna_ImaPaint_stencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
/* not the best solution maybe, but will refresh the 3D viewport */
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
#else
static void rna_def_palettecolor(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "PaletteColor", NULL);
RNA_def_struct_ui_text(srna, "Palette Color", "");
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "rgb");
RNA_def_property_ui_text(prop, "Color", "");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "value");
RNA_def_property_ui_text(prop, "Value", "");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "value");
RNA_def_property_ui_text(prop, "Weight", "");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
}
static void rna_def_palette(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "Palette", "ID");
RNA_def_struct_ui_text(srna, "Palette", "");
RNA_def_struct_ui_icon(srna, ICON_COLOR);
prop = RNA_def_property(srna, "colors", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "PaletteColor");
RNA_def_property_ui_text(prop, "Palette Color", "Colors that are part of this palette");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
}
static void rna_def_paint_curve(BlenderRNA *brna)
{
StructRNA *srna;
srna = RNA_def_struct(brna, "PaintCurve", "ID");
RNA_def_struct_ui_text(srna, "Paint Curve", "");
RNA_def_struct_ui_icon(srna, ICON_CURVE_BEZCURVE);
}
static void rna_def_paint(BlenderRNA *brna)
{
StructRNA *srna;
@@ -302,6 +361,11 @@ static void rna_def_paint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Brush", "Active Brush");
RNA_def_property_update(prop, 0, "rna_Paint_brush_update");
prop = RNA_def_property(srna, "palette", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Palette", "Active Palette");
prop = RNA_def_property(srna, "show_brush", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", PAINT_SHOW_BRUSH);
RNA_def_property_ui_text(prop, "Show Brush", "");
@@ -532,11 +596,28 @@ static void rna_def_image_paint(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_stencil_layer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_STENCIL);
RNA_def_property_ui_text(prop, "Stencil Layer", "Set the mask layer from the UV map buttons");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
prop = RNA_def_property(srna, "invert_stencil", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_LAYER_STENCIL_INV);
RNA_def_property_ui_text(prop, "Invert", "Invert the stencil layer");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
prop = RNA_def_property(srna, "stencil_image", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "stencil");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Stencil Image", "Image used as stencil");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
prop = RNA_def_property(srna, "stencil_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "stencil_col");
RNA_def_property_ui_text(prop, "Stencil Color", "Stencil color in the viewport");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
prop = RNA_def_property(srna, "slot_color_default", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "New Layer Color", "Color/Alpha used for new");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "use_clone_layer", PROP_BOOLEAN, PROP_NONE);
@@ -558,6 +639,16 @@ static void rna_def_image_paint(BlenderRNA *brna)
prop = RNA_def_int_array(srna, "screen_grab_size", 2, NULL, 0, 0, "screen_grab_size",
"Size to capture the image for re-projecting", 0, 0);
RNA_def_property_range(prop, 512, 16384);
prop = RNA_def_property(srna, "slot_xresolution_default", PROP_INT, PROP_UNSIGNED);
RNA_def_property_range(prop, 1, SHRT_MAX);
RNA_def_property_ui_range(prop, 64, 4096, 0, -1);
RNA_def_property_ui_text(prop, "X resolution", "X Resolution of new image");
prop = RNA_def_property(srna, "slot_yresolution_default", PROP_INT, PROP_UNSIGNED);
RNA_def_property_range(prop, 1, SHRT_MAX);
RNA_def_property_ui_range(prop, 64, 4096, 0, -1);
RNA_def_property_ui_text(prop, "Y resolution", "Y Resolution of new image");
}
static void rna_def_particle_edit(BlenderRNA *brna)
@@ -741,6 +832,9 @@ void RNA_def_sculpt_paint(BlenderRNA *brna)
{
/* *** Non-Animated *** */
RNA_define_animate_sdna(false);
rna_def_palettecolor(brna);
rna_def_palette(brna);
rna_def_paint_curve(brna);
rna_def_paint(brna);
rna_def_sculpt(brna);
rna_def_uv_sculpt(brna);

Some files were not shown because too many files have changed in this diff Show More