Merge GSOC Sculpt Branch: 28499-30319

https://svn.blender.org/svnroot/bf-blender/branches/soc-2010-jwilkins
See log of that branch for details.
This commit is contained in:
2010-07-14 14:11:03 +00:00
parent ae1748b984
commit 5505697ac5
55 changed files with 5239 additions and 1374 deletions

View File

@@ -56,9 +56,8 @@ else:
if env['BF_GHOST_DEBUG']:
defs.append('BF_GHOST_DEBUG')
incs = '. ../string #extern/glew/include #source/blender/imbuf #source/blender/makesdna ' + env['BF_OPENGL_INC']
if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
incs = env['BF_WINTAB_INC'] + ' ' + incs
env.BlenderLib ('bf_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15] )

View File

@@ -42,7 +42,7 @@ AGLContext GHOST_WindowCarbon::s_firstaglCtx = NULL;
const GHOST_TInt32 GHOST_WindowCarbon::s_sizeRectSize = 16;
#endif //GHOST_DRAW_CARBON_GUTTER
static const GLint sPreferredFormatWindow[8] = {
static const GLint sPreferredFormatWindow[10] = {
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_ACCELERATED,
@@ -50,7 +50,7 @@ AGL_DEPTH_SIZE, 32,
AGL_NONE,
};
static const GLint sPreferredFormatFullScreen[9] = {
static const GLint sPreferredFormatFullScreen[11] = {
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_ACCELERATED,

View File

@@ -348,10 +348,11 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated;
//pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway
pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize;
pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo;
if (numOfAASamples>0) {

View File

@@ -1093,7 +1093,7 @@ static int WeightPixelFormat(PIXELFORMATDESCRIPTOR& pfd) {
!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
!(pfd.dwFlags & PFD_DOUBLEBUFFER) || /* Blender _needs_ this */
( pfd.cDepthBits <= 8 ) ||
!(pfd.iPixelType == PFD_TYPE_RGBA) )
!(pfd.iPixelType == PFD_TYPE_RGBA))
return 0;
weight = 1; /* it's usable */

View File

@@ -437,6 +437,7 @@ class DATA_PT_modifiers(DataButtonsPanel):
col.prop(md, "levels", text="Preview")
col.prop(md, "sculpt_levels", text="Sculpt")
col.prop(md, "render_levels", text="Render")
col.prop(bpy.context.tool_settings.sculpt, "fast_navigate")
if wide_ui:
col = split.column()

View File

@@ -275,15 +275,12 @@ class TEXTURE_PT_mapping(TextureSlotPanel):
if type(idblock) == bpy.types.Brush:
if context.sculpt_object:
layout.label(text="Brush Mapping:")
layout.prop(tex, "map_mode", expand=True)
row = layout.row()
row.active = tex.map_mode in ('FIXED', 'TILED')
row.prop(tex, "angle")
row = layout.row()
row.active = tex.map_mode in ('TILED', '3D')
row.column().prop(tex, "size")
else:
if type(idblock) == bpy.types.Material:
split = layout.split(percentage=0.3)
@@ -307,15 +304,17 @@ class TEXTURE_PT_mapping(TextureSlotPanel):
row.prop(tex, "y_mapping", text="")
row.prop(tex, "z_mapping", text="")
# any non brush
split = layout.split()
split = layout.split()
col = split.column()
col.prop(tex, "offset")
if wide_ui:
col = split.column()
col.prop(tex, "offset")
else:
col.separator()
if wide_ui:
col = split.column()
col.prop(tex, "size")
col.prop(tex, "size")
class TEXTURE_PT_influence(TextureSlotPanel):

View File

@@ -327,7 +327,21 @@ class USERPREF_PT_edit(bpy.types.Panel):
row.separator()
row.separator()
sculpt = context.tool_settings.sculpt
col = row.column()
col.label(text="Paint and Sculpt:")
col.prop(edit, "sculpt_paint_use_unified_size", text="Unify Size")
col.prop(edit, "sculpt_paint_use_unified_strength", text="Unify Strength")
row = col.row(align=True)
row.label("Overlay Color:")
row.prop(edit, "sculpt_paint_overlay_col", text="")
col.prop(sculpt, "use_openmp", text="Threaded Sculpt")
col.prop(sculpt, "show_brush")
col.separator()
col.separator()
col.separator()
col.label(text="Duplicate Data:")
col.prop(edit, "duplicate_mesh", text="Mesh")
col.prop(edit, "duplicate_surface", text="Surface")

View File

@@ -19,6 +19,7 @@
# <pep8 compliant>
import bpy
narrowui = bpy.context.user_preferences.view.properties_width_check
class View3DPanel(bpy.types.Panel):
bl_space_type = 'VIEW_3D'
@@ -503,18 +504,26 @@ class VIEW3D_PT_tools_brush(PaintPanel):
if not context.particle_edit_object:
col = layout.split().column()
row = col.row()
if context.sculpt_object and brush:
defaultbrushes = 8
elif context.texture_paint_object and brush:
defaultbrushes = 4
if context.sculpt_object and context.tool_settings.sculpt:
col.template_ID_preview(settings, "brush", new="brush.add", filter="is_sculpt_brush", rows=3, cols=8)
elif context.texture_paint_object and context.tool_settings.image_paint:
col.template_ID_preview(settings, "brush", new="brush.add", filter="is_imapaint_brush", rows=3, cols=8)
elif context.vertex_paint_object and context.tool_settings.vertex_paint:
col.template_ID_preview(settings, "brush", new="brush.add", filter="is_vpaint_brush", rows=3, cols=8)
elif context.weight_paint_object and context.tool_settings.weight_paint:
col.template_ID_preview(settings, "brush", new="brush.add", filter="is_wpaint_brush", rows=3, cols=8)
else:
defaultbrushes = 7
row = col.row()
row.template_list(settings, "brushes", settings, "active_brush_index", rows=2, maxrows=defaultbrushes)
if context.sculpt_object and brush:
defaultbrushes = 8
elif context.texture_paint_object and brush:
defaultbrushes = 4
else:
defaultbrushes = 7
col.template_ID(settings, "brush", new="brush.add")
row.template_list(settings, "brushes", settings, "active_brush_index", rows=2, maxrows=defaultbrushes)
# Particle Mode #
@@ -546,44 +555,152 @@ class VIEW3D_PT_tools_brush(PaintPanel):
# Sculpt Mode #
elif context.sculpt_object and brush:
edit = context.user_preferences.edit
col = layout.column()
col.separator()
row = col.row(align=True)
row.prop(brush, "size", slider=True)
if brush.sculpt_tool != 'GRAB':
row.prop(brush, "use_size_pressure", toggle=True, text="")
if edit.sculpt_paint_use_unified_size:
if edit.sculpt_paint_unified_lock_brush_size:
row.prop(edit, "sculpt_paint_unified_lock_brush_size", toggle=True, text="", icon='LOCKED')
row.prop(edit, "sculpt_paint_unified_unprojected_radius", text="Unified Radius", slider=True)
else:
row.prop(edit, "sculpt_paint_unified_lock_brush_size", toggle=True, text="", icon='UNLOCKED')
row.prop(edit, "sculpt_paint_unified_size", text="Unified Radius", slider=True)
else:
if brush.lock_brush_size:
row.prop(brush, "lock_brush_size", toggle=True, text="", icon='LOCKED')
row.prop(brush, "unprojected_radius", text="Radius", slider=True)
else:
row.prop(brush, "lock_brush_size", toggle=True, text="", icon='UNLOCKED')
row.prop(brush, "size", text="Radius", slider=True)
row.prop(brush, "use_size_pressure", toggle=True, text="")
if brush.sculpt_tool not in ('SNAKE_HOOK', 'GRAB', 'ROTATE'):
col.separator()
row = col.row(align=True)
row.prop(brush, "strength", slider=True)
if brush.use_space and brush.sculpt_tool not in ('SMOOTH'):
if brush.use_space_atten:
row.prop(brush, "use_space_atten", toggle=True, text="", icon='LOCKED')
else:
row.prop(brush, "use_space_atten", toggle=True, text="", icon='UNLOCKED')
if edit.sculpt_paint_use_unified_strength:
row.prop(edit, "sculpt_paint_unified_strength", text="Unified Strength", slider=True)
else:
row.prop(brush, "strength", text="Strength", slider=True)
row.prop(brush, "use_strength_pressure", text="")
# XXX - TODO
#row = col.row(align=True)
#row.prop(brush, "jitter", slider=True)
#row.prop(brush, "use_jitter_pressure", toggle=True, text="")
col = layout.column()
if brush.sculpt_tool in ('DRAW', 'PINCH', 'INFLATE', 'LAYER', 'CLAY'):
col.row().prop(brush, "direction", expand=True)
if brush.sculpt_tool not in ('SMOOTH'):
col.separator()
if brush.sculpt_tool in ('DRAW', 'INFLATE', 'LAYER'):
col.prop(brush, "use_accumulate")
row = col.row(align=True)
row.prop(brush, "autosmooth_factor", slider=True)
row.prop(brush, "use_inverse_smooth_pressure", toggle=True, text="")
if brush.sculpt_tool == 'LAYER':
ob = context.sculpt_object
do_persistent = True
# not supported yet for this case
for md in ob.modifiers:
if md.type == 'MULTIRES':
do_persistent = False
if do_persistent:
col.prop(brush, "use_persistent")
col.operator("sculpt.set_persistent_base")
if brush.sculpt_tool in ('GRAB', 'SNAKE_HOOK'):
col.separator()
row = col.row(align=True)
row.prop(brush, "normal_weight", slider=True)
if brush.sculpt_tool in ('CREASE', 'BLOB'):
col.separator()
row = col.row(align=True)
row.prop(brush, "crease_pinch_factor", slider=True, text="Pinch")
if brush.sculpt_tool not in ('PINCH', 'INFLATE', 'SMOOTH'):
row = col.row(align=True)
col.separator()
if brush.use_original_normal:
row.prop(brush, "use_original_normal", toggle=True, text="", icon='LOCKED')
else:
row.prop(brush, "use_original_normal", toggle=True, text="", icon='UNLOCKED')
row.prop(brush, "sculpt_plane", text="")
#if brush.sculpt_tool in ('CLAY', 'CLAY_TUBES', 'FLATTEN', 'FILL', 'SCRAPE'):
if brush.sculpt_tool in ('CLAY', 'FLATTEN', 'FILL', 'SCRAPE'):
row = col.row(align=True)
row.prop(brush, "plane_offset", slider=True)
row.prop(brush, "use_offset_pressure", text="")
col.separator()
row= col.row()
row.prop(brush, "use_plane_trim", text="Trim")
row= col.row()
row.active=brush.use_plane_trim
row.prop(brush, "plane_trim", slider=True, text="Distance")
col.separator()
row= col.row()
row.prop(brush, "use_frontface", text="Front Faces Only")
#if brush.sculpt_tool in ('DRAW', 'CREASE', 'BLOB', 'LAYER', 'CLAY', 'CLAY_TUBES'):
if brush.sculpt_tool in ('DRAW', 'CREASE', 'BLOB', 'LAYER', 'CLAY'):
col.separator()
col.row().prop(brush, "direction", expand=True)
elif brush.sculpt_tool in ('FLATTEN'):
col.separator()
col.row().prop(brush, "flatten_contrast", expand=True)
elif brush.sculpt_tool in ('FILL'):
col.separator()
col.row().prop(brush, "fill_deepen", expand=True)
elif brush.sculpt_tool in ('SCRAPE'):
col.separator()
col.row().prop(brush, "scrape_peaks", expand=True)
elif brush.sculpt_tool in ('INFLATE'):
col.separator()
col.row().prop(brush, "inflate_deflate", expand=True)
elif brush.sculpt_tool in ('PINCH'):
col.separator()
col.row().prop(brush, "pinch_magnify", expand=True)
#if brush.sculpt_tool in ('DRAW', 'CREASE', 'BLOB', 'INFLATE', 'LAYER', 'CLAY', 'CLAY_TUBES'):
if brush.sculpt_tool in ('DRAW', 'CREASE', 'BLOB', 'INFLATE', 'LAYER', 'CLAY'):
col.separator()
col.prop(brush, "use_accumulate")
if brush.sculpt_tool == 'LAYER':
col.separator()
ob = context.sculpt_object
do_persistent = True
# not supported yet for this case
for md in ob.modifiers:
if md.type == 'MULTIRES':
do_persistent = False
if do_persistent:
col.prop(brush, "use_persistent")
col.operator("sculpt.set_persistent_base")
# Texture Paint Mode #
@@ -669,10 +786,88 @@ class VIEW3D_PT_tools_brush_texture(PaintPanel):
col = layout.column()
col.template_ID_preview(brush, "texture", new="texture.new", rows=2, cols=4)
col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
if context.sculpt_object:
col.row().prop(tex_slot, "map_mode", expand=True)
#XXX duplicated from properties_texture.py
wide_ui = context.region.width > narrowui
col.separator()
col.label(text="Brush Mapping:")
row = col.row(align=True)
row.prop(tex_slot, "map_mode", expand=True)
col.separator()
col = layout.column()
col.active = tex_slot.map_mode in ('FIXED')
col.label(text="Angle:")
col = layout.column()
if not brush.use_anchor and brush.sculpt_tool not in ('GRAB', 'SNAKE_HOOK', 'THUMB', 'ROTATE') and tex_slot.map_mode in ('FIXED'):
col.prop(brush, "texture_angle_source", text="")
else:
col.prop(brush, "texture_angle_source_no_random", text="")
#row = col.row(align=True)
#row.label(text="Angle:")
#row.active = tex_slot.map_mode in ('FIXED', 'TILED')
#row = col.row(align=True)
#col = row.column()
#col.active = tex_slot.map_mode in ('FIXED')
#col.prop(brush, "use_rake", toggle=True, icon='PARTICLEMODE', text="")
col = layout.column()
col.prop(tex_slot, "angle", text="")
col.active = tex_slot.map_mode in ('FIXED', 'TILED')
#col = layout.column()
#col.prop(brush, "use_random_rotation")
#col.active = (not brush.use_rake) and (not brush.use_anchor) and brush.sculpt_tool not in ('GRAB', 'SNAKE_HOOK', 'THUMB', 'ROTATE') and tex_slot.map_mode in ('FIXED')
split = layout.split()
col = split.column()
col.prop(tex_slot, "offset")
if wide_ui:
col = split.column()
else:
col.separator()
col.prop(tex_slot, "size")
col = layout.column()
row = col.row(align=True)
row.label(text="Sample Bias:")
row = col.row(align=True)
row.prop(brush, "texture_sample_bias", slider=True, text="")
row = col.row(align=True)
row.label(text="Overlay:")
row.active = tex_slot.map_mode in ('FIXED', 'TILED')
row = col.row(align=True)
col = row.column()
if brush.use_texture_overlay:
col.prop(brush, "use_texture_overlay", toggle=True, text="", icon='MUTE_IPO_OFF')
else:
col.prop(brush, "use_texture_overlay", toggle=True, text="", icon='MUTE_IPO_ON')
col.active = tex_slot.map_mode in ('FIXED', 'TILED')
col = row.column()
col.prop(brush, "texture_overlay_alpha", text="Alpha")
col.active = tex_slot.map_mode in ('FIXED', 'TILED') and brush.use_texture_overlay
class VIEW3D_PT_tools_brush_tool(PaintPanel):
@@ -696,15 +891,11 @@ class VIEW3D_PT_tools_brush_tool(PaintPanel):
col = layout.column(align=True)
if context.sculpt_object:
col.prop(brush, "sculpt_tool", expand=True)
col.prop(brush, "sculpt_tool", expand=False, text="")
elif context.texture_paint_object:
col.prop(brush, "imagepaint_tool", expand=True)
#col.prop_enum(settings, "tool", 'DRAW')
#col.prop_enum(settings, "tool", 'SOFTEN')
#col.prop_enum(settings, "tool", 'CLONE')
#col.prop_enum(settings, "tool", 'SMEAR')
col.prop(brush, "imagepaint_tool", expand=False, text="")
elif context.vertex_paint_object or context.weight_paint_object:
col.prop(brush, "vertexpaint_tool", expand=True)
col.prop(brush, "vertexpaint_tool", expand=False, text="")
class VIEW3D_PT_tools_brush_stroke(PaintPanel):
@@ -725,29 +916,83 @@ class VIEW3D_PT_tools_brush_stroke(PaintPanel):
brush = settings.brush
texture_paint = context.texture_paint_object
if context.sculpt_object:
if brush.sculpt_tool != 'LAYER':
layout.prop(brush, "use_anchor")
layout.prop(brush, "use_rake")
layout.prop(brush, "use_airbrush")
col = layout.column()
col.active = brush.use_airbrush
col.prop(brush, "rate", slider=True)
if not texture_paint:
layout.prop(brush, "use_smooth_stroke")
if context.sculpt_object:
col.label(text="Stroke Method:")
col.prop(brush, "stroke_method", text="")
if brush.use_anchor:
col.separator()
row = col.row()
row.prop(brush, "edge_to_edge", "Edge To Edge")
if brush.use_airbrush:
col.separator()
row = col.row()
row.prop(brush, "rate", text="Rate", slider=True)
if brush.use_space:
col.separator()
row = col.row()
row.active = brush.use_space
row.prop(brush, "spacing", text="Spacing")
if brush.sculpt_tool not in ('GRAB', 'THUMB', 'SNAKE_HOOK', 'ROTATE') and (not brush.use_anchor) and (not brush.restore_mesh):
col = layout.column()
col.separator()
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)
col.separator()
row = col.row(align=True)
row.prop(brush, "jitter", slider=True)
row.prop(brush, "use_jitter_pressure", toggle=True, text="")
else:
row = col.row()
row.prop(brush, "use_airbrush")
row = col.row()
row.active = brush.use_airbrush and (not brush.use_space) and (not brush.use_anchor)
row.prop(brush, "rate", slider=True)
col.separator()
if not texture_paint:
row = col.row()
row.prop(brush, "use_smooth_stroke")
col = layout.column()
col.active = brush.use_smooth_stroke
col.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
col.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
col.separator()
col = layout.column()
col.active = brush.use_smooth_stroke
col.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
col.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
col.active = (not brush.use_anchor) and (brush.sculpt_tool not in ('GRAB', 'THUMB', 'ROTATE', 'SNAKE_HOOK'))
layout.prop(brush, "use_space")
row = layout.row(align=True)
row.active = brush.use_space
row.prop(brush, "spacing", text="Distance", slider=True)
if texture_paint:
row.prop(brush, "use_spacing_pressure", toggle=True, text="")
row = col.row()
row.prop(brush, "use_space")
row = col.row()
row.active = brush.use_space
row.prop(brush, "spacing", text="Spacing")
#col.prop(brush, "use_space_atten", text="Adaptive Strength")
#col.prop(brush, "use_adaptive_space", text="Adaptive Spacing")
#col.separator()
#if texture_paint:
# row.prop(brush, "use_spacing_pressure", toggle=True, text="")
class VIEW3D_PT_tools_brush_curve(PaintPanel):
@@ -767,13 +1012,17 @@ class VIEW3D_PT_tools_brush_curve(PaintPanel):
layout.template_curve_mapping(brush, "curve", brush=True)
row = layout.row(align=True)
row.operator("brush.curve_preset", text="Sharp").shape = 'SHARP'
row.operator("brush.curve_preset", text="Smooth").shape = 'SMOOTH'
row.operator("brush.curve_preset", text="Max").shape = 'MAX'
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'
row.operator("brush.curve_preset", icon="SHARPCURVE", text="").shape = 'SHARP'
row.operator("brush.curve_preset", icon="LINCURVE", text="").shape = 'LINE'
row.operator("brush.curve_preset", icon="NOCURVE", text="").shape = 'MAX'
row.operator("brush.curve_preset", icon="RNDCURVE", text="").shape = 'MID9'
class VIEW3D_PT_sculpt_options(PaintPanel):
bl_label = "Options"
bl_default_closed = True
def poll(self, context):
return (context.sculpt_object and context.tool_settings.sculpt)
@@ -781,25 +1030,100 @@ class VIEW3D_PT_sculpt_options(PaintPanel):
def draw(self, context):
layout = self.layout
wide_ui = context.region.width > narrowui
sculpt = context.tool_settings.sculpt
settings = self.paint_settings(context)
brush = settings.brush
col = layout.column()
col.prop(sculpt, "show_brush")
col.prop(sculpt, "fast_navigate")
split = self.layout.split()
split = layout.split()
col = split.column()
col.label(text="Symmetry:")
edit = context.user_preferences.edit
col.label(text="Unified Settings:")
col.prop(edit, "sculpt_paint_use_unified_size", text="Size")
col.prop(edit, "sculpt_paint_use_unified_strength", text="Strength")
if wide_ui:
col = split.column()
else:
col.separator()
col.label(text="Lock:")
row = col.row(align=True)
row.prop(sculpt, "lock_x", text="X", toggle=True)
row.prop(sculpt, "lock_y", text="Y", toggle=True)
row.prop(sculpt, "lock_z", text="Z", toggle=True)
class VIEW3D_PT_sculpt_symmetry(PaintPanel):
bl_label = "Symmetry"
bl_default_closed = True
def poll(self, context):
return (context.sculpt_object and context.tool_settings.sculpt)
def draw(self, context):
wide_ui = context.region.width > narrowui
layout = self.layout
sculpt = context.tool_settings.sculpt
settings = self.paint_settings(context)
brush = settings.brush
split = layout.split()
col = split.column()
col.label(text="Mirror:")
col.prop(sculpt, "symmetry_x", text="X")
col.prop(sculpt, "symmetry_y", text="Y")
col.prop(sculpt, "symmetry_z", text="Z")
col = split.column()
col.label(text="Lock:")
col.prop(sculpt, "lock_x", text="X")
col.prop(sculpt, "lock_y", text="Y")
col.prop(sculpt, "lock_z", text="Z")
if wide_ui:
col = split.column()
else:
col.separator()
col.prop(sculpt, "radial_symm", text="Radial")
col = layout.column()
col.separator()
col.prop(sculpt, "use_symmetry_feather", text="Feather")
class VIEW3D_PT_tools_brush_appearance(PaintPanel):
bl_label = "Appearance"
bl_default_closed = True
def poll(self, context):
return (context.sculpt_object and context.tool_settings.sculpt) or (context.vertex_paint_object and context.tool_settings.vertex_paint) or (context.weight_paint_object and context.tool_settings.weight_paint) or (context.texture_paint_object and context.tool_settings.image_paint)
def draw(self, context):
layout = self.layout
sculpt = context.tool_settings.sculpt
settings = self.paint_settings(context)
brush = settings.brush
col = layout.column();
if context.sculpt_object and context.tool_settings.sculpt:
#if brush.sculpt_tool in ('DRAW', 'INFLATE', 'CLAY', 'CLAY_TUBES', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN'):
if brush.sculpt_tool in ('DRAW', 'INFLATE', 'CLAY', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN'):
col.prop(brush, "add_col", text="Add Color")
col.prop(brush, "sub_col", text="Substract Color")
else:
col.prop(brush, "add_col", text="Color")
col.separator()
col = layout.column()
col.label(text="Icon:")
#col.template_ID_preview(brush, "image_icon", open="image.open", filter="is_image_icon", rows=3, cols=8)
col.template_ID_preview(brush, "image_icon", open="image.open", rows=3, cols=8)
# ********** default tools for weightpaint ****************
@@ -1049,9 +1373,11 @@ classes = [
VIEW3D_PT_tools_posemode_options,
VIEW3D_PT_tools_brush,
VIEW3D_PT_tools_brush_texture,
VIEW3D_PT_tools_brush_tool,
VIEW3D_PT_tools_brush_stroke,
VIEW3D_PT_tools_brush_curve,
VIEW3D_PT_tools_brush_appearance,
VIEW3D_PT_tools_brush_tool,
VIEW3D_PT_sculpt_symmetry,
VIEW3D_PT_sculpt_options,
VIEW3D_PT_tools_vertexpaint,
VIEW3D_PT_tools_weightpaint_options,

View File

@@ -43,9 +43,9 @@ struct bContext;
struct ReportList;
struct Scene;
struct Main;
#define BLENDER_VERSION 252
#define BLENDER_SUBVERSION 5
#define BLENDER_SUBVERSION 6 // XXX: this shouldn't be merged with trunk, this is so Sculpt branch can detect old files
#define BLENDER_MINVERSION 250
#define BLENDER_MINSUBVERSION 0

View File

@@ -84,5 +84,15 @@ unsigned int *brush_gen_texture_cache(struct Brush *br, int half_side);
void brush_radial_control_invoke(struct wmOperator *op, struct Brush *br, float size_weight);
int brush_radial_control_exec(struct wmOperator *op, struct Brush *br, float size_weight);
/* unified strength and size */
int sculpt_get_brush_size(struct Brush *brush);
void sculpt_set_brush_size(struct Brush *brush, int size);
int sculpt_get_lock_brush_size(struct Brush *brush);
float sculpt_get_brush_unprojected_radius(struct Brush *brush);
void sculpt_set_brush_unprojected_radius(struct Brush *brush, float unprojected_radius);
float sculpt_get_brush_alpha(struct Brush *brush);
void sculpt_set_brush_alpha(struct Brush *brush, float alpha);
#endif

View File

@@ -28,6 +28,8 @@
#ifndef BKE_PAINT_H
#define BKE_PAINT_H
#include "DNA_vec_types.h"
struct Brush;
struct MFace;
struct MultireModifierData;
@@ -96,6 +98,8 @@ typedef struct SculptSession {
struct GPUDrawObject *drawobject;
int modifiers_active;
rcti previous_r;
} SculptSession;
void free_sculptsession(struct Object *ob);

View File

@@ -53,8 +53,7 @@
#include "BKE_main.h"
#include "BKE_paint.h"
#include "BKE_texture.h"
#include "BKE_icons.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -70,29 +69,59 @@ Brush *add_brush(const char *name)
brush= alloc_libblock(&G.main->brush, ID_BR, name);
brush->rgb[0]= 1.0f;
/* BRUSH SCULPT TOOL SETTINGS */
brush->sculpt_tool = SCULPT_TOOL_DRAW; /* sculpting defaults to the draw tool for new brushes */
brush->size= 35; /* radius of the brush in pixels */
brush->alpha= 0.5f; /* brush strength/intensity probably variable should be renamed? */
brush->autosmooth_factor= 0.0f;
brush->crease_pinch_factor= 0.5f;
brush->sculpt_plane = SCULPT_DISP_DIR_VIEW;
brush->plane_offset= 0.0f; /* how far above or below the plane that is found by averaging the faces */
brush->plane_trim= 0.5f;
brush->clone.alpha= 0.5f;
brush->normal_weight= 0.0f;
/* BRUSH PAINT TOOL SETTINGS */
brush->rgb[0]= 1.0f; /* default rgb color of the brush when painting - white */
brush->rgb[1]= 1.0f;
brush->rgb[2]= 1.0f;
brush->alpha= 0.2f;
brush->size= 25;
brush->spacing= 3.5f;
brush->smooth_stroke_radius= 75;
brush->smooth_stroke_factor= 0.9;
brush->rate= 0.1f;
brush->jitter= 0.0f;
brush->clone.alpha= 0.5;
brush->sculpt_tool = SCULPT_TOOL_DRAW;
brush->flag |= BRUSH_SPACE;
brush_curve_preset(brush, CURVE_PRESET_SMOOTH);
/* 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 */
brush->smooth_stroke_radius= 75;
brush->smooth_stroke_factor= 0.9f;
brush->rate= 0.1f; /* time delay between dots of paint or sculpting when doing airbrush mode */
brush->jitter= 0.0f;
/* BRUSH TEXTURE SETTINGS */
default_mtex(&brush->mtex);
brush->texture_sample_bias= 0; /* value to added to texture samples */
/* brush appearance */
brush->image_icon= NULL;
brush->add_col[0]= 1.00; /* add mode color is light red */
brush->add_col[1]= 0.39;
brush->add_col[2]= 0.39;
brush->sub_col[0]= 0.39; /* subtract mode color is light blue */
brush->sub_col[1]= 0.39;
brush->sub_col[2]= 1.00;
/* the default alpha falloff curve */
brush_curve_preset(brush, CURVE_PRESET_SMOOTH);
/* enable fake user by default */
brush->id.flag |= LIB_FAKEUSER;
brush_toggled_fake_user(brush);
return brush;
return brush;
}
Brush *copy_brush(Brush *brush)
@@ -118,7 +147,7 @@ Brush *copy_brush(Brush *brush)
void free_brush(Brush *brush)
{
if(brush->mtex.tex) brush->mtex.tex->id.us--;
curvemapping_free(brush->curve);
}
@@ -731,11 +760,19 @@ static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pres
brush->spacing = MAX2(1.0, painter->startspacing*(1.5f-pressure));
}
static void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos)
void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos)
{
if(brush->jitter){
jitterpos[0] = pos[0] + ((BLI_frand()-0.5f) * brush->size * brush->jitter * 2);
jitterpos[1] = pos[1] + ((BLI_frand()-0.5f) * brush->size * brush->jitter * 2);
float rand_pos[2];
// find random position within a circle of diameter 1
do {
rand_pos[0] = BLI_frand()-0.5f;
rand_pos[1] = BLI_frand()-0.5f;
} while (len_v2(rand_pos) > 0.5f);
jitterpos[0] = pos[0] + 2*rand_pos[0]*brush->size*brush->jitter;
jitterpos[1] = pos[1] + 2*rand_pos[1]*brush->size*brush->jitter;
}
else {
VECCOPY2D(jitterpos, pos);
@@ -887,7 +924,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
/* Uses the brush curve control to find a strength value between 0 and 1 */
float brush_curve_strength_clamp(Brush *br, float p, const float len)
{
if(p >= len) p= 1.0f;
if(p >= len) return 0;
else p= p/len;
p= curvemapping_evaluateF(br->curve, 0, p);
@@ -899,9 +936,12 @@ float brush_curve_strength_clamp(Brush *br, float p, const float len)
* used for sculpt only */
float brush_curve_strength(Brush *br, float p, const float len)
{
if(p >= len) p= 1.0f;
else p= p/len;
return curvemapping_evaluateF(br->curve, 0, p);
if(p >= len)
p= 1.0f;
else
p= p/len;
return curvemapping_evaluateF(br->curve, 0, p);
}
/* TODO: should probably be unified with BrushPainter stuff? */
@@ -915,7 +955,7 @@ unsigned int *brush_gen_texture_cache(Brush *br, int half_side)
memset(&texres, 0, sizeof(TexResult));
if(mtex && mtex->tex) {
if(mtex->tex) {
float x, y, step = 2.0 / side, co[3];
texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache");
@@ -993,9 +1033,9 @@ void brush_radial_control_invoke(wmOperator *op, Brush *br, float size_weight)
float original_value= 0;
if(mode == WM_RADIALCONTROL_SIZE)
original_value = br->size * size_weight;
original_value = sculpt_get_brush_size(br) * size_weight;
else if(mode == WM_RADIALCONTROL_STRENGTH)
original_value = br->alpha;
original_value = sculpt_get_brush_alpha(br);
else if(mode == WM_RADIALCONTROL_ANGLE) {
MTex *mtex = brush_active_texture(br);
if(mtex)
@@ -1013,9 +1053,15 @@ int brush_radial_control_exec(wmOperator *op, Brush *br, float size_weight)
const float conv = 0.017453293;
if(mode == WM_RADIALCONTROL_SIZE)
br->size = new_value * size_weight;
if (sculpt_get_lock_brush_size(br)) {
float initial_value = RNA_float_get(op->ptr, "initial_value");
const float unprojected_radius = sculpt_get_brush_unprojected_radius(br);
sculpt_set_brush_unprojected_radius(br, unprojected_radius * new_value/initial_value * size_weight);
}
else
sculpt_set_brush_size(br, new_value * size_weight);
else if(mode == WM_RADIALCONTROL_STRENGTH)
br->alpha = new_value;
sculpt_set_brush_alpha(br, new_value);
else if(mode == WM_RADIALCONTROL_ANGLE) {
MTex *mtex = brush_active_texture(br);
if(mtex)

View File

@@ -126,6 +126,9 @@ CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, floa
cumap->cm[a].curve[1].x= maxx;
cumap->cm[a].curve[1].y= maxy;
}
cumap->changed_timestamp = 0;
return cumap;
}
@@ -240,10 +243,12 @@ void curvemap_reset(CurveMap *cuma, rctf *clipr, int preset)
switch(preset) {
case CURVE_PRESET_LINE: cuma->totpoint= 2; break;
case CURVE_PRESET_SHARP: cuma->totpoint= 3; break;
case CURVE_PRESET_SHARP: cuma->totpoint= 4; break;
case CURVE_PRESET_SMOOTH: cuma->totpoint= 4; break;
case CURVE_PRESET_MAX: cuma->totpoint= 2; break;
case CURVE_PRESET_MID9: cuma->totpoint= 9;
case CURVE_PRESET_MID9: cuma->totpoint= 9; break;
case CURVE_PRESET_ROUND: cuma->totpoint= 4; break;
case CURVE_PRESET_ROOT: cuma->totpoint= 4; break;
}
cuma->curve= MEM_callocN(cuma->totpoint*sizeof(CurveMapPoint), "curve points");
@@ -251,27 +256,29 @@ void curvemap_reset(CurveMap *cuma, rctf *clipr, int preset)
switch(preset) {
case CURVE_PRESET_LINE:
cuma->curve[0].x= clipr->xmin;
cuma->curve[0].y= clipr->ymin;
cuma->curve[0].y= clipr->ymax;
cuma->curve[0].flag= 0;
cuma->curve[1].x= clipr->xmax;
cuma->curve[1].y= clipr->ymax;
cuma->curve[1].y= clipr->ymin;
cuma->curve[1].flag= 0;
break;
case CURVE_PRESET_SHARP:
cuma->curve[0].x= 0;
cuma->curve[0].y= 1;
cuma->curve[1].x= 0.33;
cuma->curve[1].y= 0.33;
cuma->curve[2].x= 1;
cuma->curve[2].y= 0;
cuma->curve[1].x= 0.25;
cuma->curve[1].y= 0.50;
cuma->curve[2].x= 0.75;
cuma->curve[2].y= 0.04;
cuma->curve[3].x= 1;
cuma->curve[3].y= 0;
break;
case CURVE_PRESET_SMOOTH:
cuma->curve[0].x= 0;
cuma->curve[0].y= 1;
cuma->curve[1].x= 0.25;
cuma->curve[1].y= 0.92;
cuma->curve[1].y= 0.94;
cuma->curve[2].x= 0.75;
cuma->curve[2].y= 0.08;
cuma->curve[2].y= 0.06;
cuma->curve[3].x= 1;
cuma->curve[3].y= 0;
break;
@@ -290,8 +297,29 @@ void curvemap_reset(CurveMap *cuma, rctf *clipr, int preset)
cuma->curve[i].y= 0.5;
}
}
break;
case CURVE_PRESET_ROUND:
cuma->curve[0].x= 0;
cuma->curve[0].y= 1;
cuma->curve[1].x= 0.5;
cuma->curve[1].y= 0.90;
cuma->curve[2].x= 0.86;
cuma->curve[2].y= 0.5;
cuma->curve[3].x= 1;
cuma->curve[3].y= 0;
break;
case CURVE_PRESET_ROOT:
cuma->curve[0].x= 0;
cuma->curve[0].y= 1;
cuma->curve[1].x= 0.25;
cuma->curve[1].y= 0.95;
cuma->curve[2].x= 0.75;
cuma->curve[2].y= 0.44;
cuma->curve[3].x= 1;
cuma->curve[3].y= 0;
break;
}
if(cuma->table) {
MEM_freeN(cuma->table);
cuma->table= NULL;
@@ -619,7 +647,9 @@ void curvemapping_changed(CurveMapping *cumap, int rem_doubles)
float thresh= 0.01f*(clipr->xmax - clipr->xmin);
float dx= 0.0f, dy= 0.0f;
int a;
cumap->changed_timestamp++;
/* clamp with clip */
if(cumap->flag & CUMA_DO_CLIP) {
for(a=0; a<cuma->totpoint; a++) {
@@ -701,7 +731,7 @@ float curvemapping_evaluateF(CurveMapping *cumap, int cur, float value)
if(cuma->table==NULL) {
curvemap_make_table(cuma, &cumap->clipr);
if(cuma->table==NULL)
return value;
return 1.0f-value;
}
return curvemap_evaluateF(cuma, value);
}

View File

@@ -38,6 +38,7 @@
#include "DNA_material_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
#include "DNA_brush_types.h"
#include "BLI_ghash.h"
@@ -120,6 +121,7 @@ struct PreviewImage* BKE_previewimg_create()
for (i=0; i<PREVIEW_MIPMAPS; ++i) {
prv_img->changed[i] = 1;
prv_img->changed_timestamp[i] = 0;
}
return prv_img;
}
@@ -202,7 +204,7 @@ PreviewImage* BKE_previewimg_get(ID *id)
Image *img = (Image*)id;
if (!img->preview) img->preview = BKE_previewimg_create();
prv_img = img->preview;
}
}
return prv_img;
}
@@ -224,6 +226,7 @@ void BKE_icon_changed(int id)
int i;
for (i=0; i<PREVIEW_MIPMAPS; ++i) {
prv->changed[i] = 1;
prv->changed_timestamp[i]++;
}
}
}

View File

@@ -200,9 +200,9 @@ void free_image(Image *ima)
}
BKE_icon_delete(&ima->id);
ima->id.icon_id = 0;
if (ima->preview) {
BKE_previewimg_free(&ima->preview);
}
BKE_previewimg_free(&ima->preview);
for(a=0; a<IMA_MAX_RENDER_SLOT; a++) {
if(ima->renders[a]) {
RE_FreeRenderResult(ima->renders[a]);

View File

@@ -36,12 +36,17 @@ struct ListBase;
typedef struct PBVH PBVH;
typedef struct PBVHNode PBVHNode;
typedef struct {
float (*co)[3];
} PBVHProxyNode;
/* Callbacks */
/* returns 1 if the search should continue from this node, 0 otherwise */
typedef int (*BLI_pbvh_SearchCallback)(PBVHNode *node, void *data);
typedef void (*BLI_pbvh_HitCallback)(PBVHNode *node, void *data);
typedef void (*BLI_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float* tmin);
/* Building */
@@ -70,7 +75,7 @@ void BLI_pbvh_search_gather(PBVH *bvh,
it's up to the callback to find the primitive within the leaves that is
hit first */
void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitCallback cb, void *data,
void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data,
float ray_start[3], float ray_normal[3], int original);
int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
float ray_start[3], float ray_normal[3], float *dist);
@@ -106,6 +111,8 @@ void BLI_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node,
void BLI_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3]);
void BLI_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max[3]);
float BLI_pbvh_node_get_tmin(PBVHNode* node);
/* Update Normals/Bounding Box/Draw Buffers/Redraw and clear flags */
void BLI_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]);
@@ -159,13 +166,21 @@ typedef struct PBVHVertexIter {
float *fno;
} PBVHVertexIter;
#ifdef _MSC_VER
#pragma warning (disable:4127) // conditional expression is constant
#endif
#define BLI_pbvh_vertex_iter_begin(bvh, node, vi, mode) \
{ \
struct DMGridData **grids; \
struct MVert *verts; \
int *grid_indices, totgrid, gridsize, *vert_indices, uniq_verts, totvert; \
\
memset(&vi, 0, sizeof(PBVHVertexIter)); \
vi.grid= 0; \
vi.no= 0; \
vi.fno= 0; \
vi.mvert= 0; \
vi.skip= 0; \
\
BLI_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids, NULL); \
BLI_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert); \
@@ -222,6 +237,13 @@ typedef struct PBVHVertexIter {
} \
}
void BLI_pbvh_node_get_proxies(PBVHNode* node, PBVHProxyNode** proxies, int* proxy_count);
void BLI_pbvh_node_free_proxies(PBVHNode* node);
PBVHProxyNode* BLI_pbvh_node_add_proxy(PBVH* bvh, PBVHNode* node);
void BLI_pbvh_gather_proxies(PBVH* pbvh, PBVHNode*** nodes, int* totnode);
//void BLI_pbvh_node_BB_reset(PBVHNode* node);
//void BLI_pbvh_node_BB_expand(PBVHNode* node, float co[3]);
#endif /* BLI_PBVH_H */

View File

@@ -62,6 +62,7 @@ float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const floa
n[0]= n1[1]*n2[2]-n1[2]*n2[1];
n[1]= n1[2]*n2[0]-n1[0]*n2[2];
n[2]= n1[0]*n2[1]-n1[1]*n2[0];
return normalize_v3(n);
}
@@ -401,16 +402,17 @@ int isect_line_tri_v3(float p1[3], float p2[3], float v0[3], float v1[3], float
sub_v3_v3v3(s, p1, v0);
cross_v3_v3v3(q, s, e1);
*lambda = f * dot_v3v3(e2, q);
if ((*lambda < 0.0)||(*lambda > 1.0)) return 0;
u = f * dot_v3v3(s, p);
if ((u < 0.0)||(u > 1.0)) return 0;
v = f * dot_v3v3(d, q);
cross_v3_v3v3(q, s, e1);
v = f * dot_v3v3(d, q);
if ((v < 0.0)||((u + v) > 1.0)) return 0;
*lambda = f * dot_v3v3(e2, q);
if ((*lambda < 0.0)||(*lambda > 1.0)) return 0;
if(uv) {
uv[0]= u;
uv[1]= v;
@@ -440,17 +442,18 @@ int isect_ray_tri_v3(float p1[3], float d[3], float v0[3], float v1[3], float v2
sub_v3_v3v3(s, p1, v0);
cross_v3_v3v3(q, s, e1);
*lambda = f * dot_v3v3(e2, q);
if ((*lambda < 0.0)) return 0;
u = f * dot_v3v3(s, p);
if ((u < 0.0)||(u > 1.0)) return 0;
cross_v3_v3v3(q, s, e1);
v = f * dot_v3v3(d, q);
if ((v < 0.0)||((u + v) > 1.0)) return 0;
if(uv) {
*lambda = f * dot_v3v3(e2, q);
if ((*lambda < 0.0)) return 0;
if(uv) {
uv[0]= u;
uv[1]= v;
}
@@ -460,36 +463,36 @@ int isect_ray_tri_v3(float p1[3], float d[3], float v0[3], float v1[3], float v2
int isect_ray_tri_epsilon_v3(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv, float epsilon)
{
float p[3], s[3], e1[3], e2[3], q[3];
float a, f, u, v;
sub_v3_v3v3(e1, v1, v0);
sub_v3_v3v3(e2, v2, v0);
cross_v3_v3v3(p, d, e2);
a = dot_v3v3(e1, p);
if (a == 0.0f) return 0;
f = 1.0f/a;
sub_v3_v3v3(s, p1, v0);
cross_v3_v3v3(q, s, e1);
float p[3], s[3], e1[3], e2[3], q[3];
float a, f, u, v;
u = f * dot_v3v3(s, p);
if ((u < -epsilon)||(u > 1.0f+epsilon)) return 0;
v = f * dot_v3v3(d, q);
if ((v < -epsilon)||((u + v) > 1.0f+epsilon)) return 0;
sub_v3_v3v3(e1, v1, v0);
sub_v3_v3v3(e2, v2, v0);
*lambda = f * dot_v3v3(e2, q);
if ((*lambda < 0.0f)) return 0;
cross_v3_v3v3(p, d, e2);
a = dot_v3v3(e1, p);
if (a == 0.0f) return 0;
f = 1.0f/a;
if(uv) {
uv[0]= u;
uv[1]= v;
}
return 1;
sub_v3_v3v3(s, p1, v0);
u = f * dot_v3v3(s, p);
if ((u < -epsilon)||(u > 1.0f+epsilon)) return 0;
cross_v3_v3v3(q, s, e1);
v = f * dot_v3v3(d, q);
if ((v < -epsilon)||((u + v) > 1.0f+epsilon)) return 0;
*lambda = f * dot_v3v3(e2, q);
if ((*lambda < 0.0f)) return 0;
if(uv) {
uv[0]= u;
uv[1]= v;
}
return 1;
}
int isect_ray_tri_threshold_v3(float p1[3], float d[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv, float threshold)

View File

@@ -92,6 +92,11 @@ struct PBVHNode {
unsigned int uniq_verts, face_verts;
char flag;
float tmin; // used for raycasting, is how close bb is to the ray point
int proxy_count;
PBVHProxyNode* proxies;
};
struct PBVH {
@@ -227,6 +232,17 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node)
node->vb= vb;
}
//void BLI_pbvh_node_BB_reset(PBVHNode* node)
//{
// BB_reset(&node->vb);
//}
//
//void BLI_pbvh_node_BB_expand(PBVHNode* node, float co[3])
//{
// BB_expand(&node->vb, co);
//}
/* Adapted from BLI_kdopbvh.c */
/* Returns the index of the first element on the right of the partition */
static int partition_indices(int *prim_indices, int lo, int hi, int axis,
@@ -354,10 +370,10 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
if(!G.background) {
node->draw_buffers =
GPU_build_mesh_buffers(map, bvh->verts, bvh->faces,
node->prim_indices,
node->totprim, node->vert_indices,
node->uniq_verts,
node->uniq_verts + node->face_verts);
node->prim_indices,
node->totprim, node->vert_indices,
node->uniq_verts,
node->uniq_verts + node->face_verts);
}
node->flag |= PBVH_UpdateDrawBuffers;
@@ -641,13 +657,12 @@ static PBVHNode *pbvh_iter_next(PBVHIter *iter)
{
PBVHNode *node;
int revisiting;
void *search_data;
/* purpose here is to traverse tree, visiting child nodes before their
parents, this order is necessary for e.g. computing bounding boxes */
while(iter->stacksize) {
/* pop node */
/* pop node */
iter->stacksize--;
node= iter->stack[iter->stacksize].node;
@@ -662,10 +677,7 @@ static PBVHNode *pbvh_iter_next(PBVHIter *iter)
if(revisiting)
return node;
/* check search callback */
search_data= iter->search_data;
if(iter->scb && !iter->scb(node, search_data))
if(iter->scb && !iter->scb(node, iter->search_data))
continue; /* don't traverse, outside of search zone */
if(node->flag & PBVH_Leaf) {
@@ -685,6 +697,34 @@ static PBVHNode *pbvh_iter_next(PBVHIter *iter)
return NULL;
}
static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
{
PBVHNode *node;
while(iter->stacksize) {
/* pop node */
iter->stacksize--;
node= iter->stack[iter->stacksize].node;
/* on a mesh with no faces this can happen
* can remove this check if we know meshes have at least 1 face */
if(node==NULL) return NULL;
if(iter->scb && !iter->scb(node, iter->search_data)) continue; /* don't traverse, outside of search zone */
if(node->flag & PBVH_Leaf) {
/* immediately hit leaf node */
return node;
}
else {
pbvh_stack_push(iter, iter->bvh->nodes+node->children_offset+1, 0);
pbvh_stack_push(iter, iter->bvh->nodes+node->children_offset, 0);
}
}
return NULL;
}
void BLI_pbvh_search_gather(PBVH *bvh,
BLI_pbvh_SearchCallback scb, void *search_data,
PBVHNode ***r_array, int *r_tot)
@@ -736,12 +776,105 @@ void BLI_pbvh_search_callback(PBVH *bvh,
pbvh_iter_begin(&iter, bvh, scb, search_data);
while((node=pbvh_iter_next(&iter)))
if(node->flag & PBVH_Leaf)
if (node->flag & PBVH_Leaf)
hcb(node, hit_data);
pbvh_iter_end(&iter);
}
typedef struct node_tree {
PBVHNode* data;
struct node_tree* left;
struct node_tree* right;
} node_tree;
static void node_tree_insert(node_tree* tree, node_tree* new_node)
{
if (new_node->data->tmin < tree->data->tmin) {
if (tree->left) {
node_tree_insert(tree->left, new_node);
}
else {
tree->left = new_node;
}
}
else {
if (tree->right) {
node_tree_insert(tree->right, new_node);
}
else {
tree->right = new_node;
}
}
}
static void traverse_tree(node_tree* tree, BLI_pbvh_HitOccludedCallback hcb, void* hit_data, float* tmin)
{
if (tree->left) traverse_tree(tree->left, hcb, hit_data, tmin);
hcb(tree->data, hit_data, tmin);
if (tree->right) traverse_tree(tree->right, hcb, hit_data, tmin);
}
static void free_tree(node_tree* tree)
{
if (tree->left) {
free_tree(tree->left);
tree->left = 0;
}
if (tree->right) {
free_tree(tree->right);
tree->right = 0;
}
free(tree);
}
float BLI_pbvh_node_get_tmin(PBVHNode* node)
{
return node->tmin;
}
void BLI_pbvh_search_callback_occluded(PBVH *bvh,
BLI_pbvh_SearchCallback scb, void *search_data,
BLI_pbvh_HitOccludedCallback hcb, void *hit_data)
{
PBVHIter iter;
PBVHNode *node;
node_tree *tree = 0;
pbvh_iter_begin(&iter, bvh, scb, search_data);
while((node=pbvh_iter_next_occluded(&iter))) {
if(node->flag & PBVH_Leaf) {
node_tree* new_node = malloc(sizeof(node_tree));
new_node->data = node;
new_node->left = NULL;
new_node->right = NULL;
if (tree) {
node_tree_insert(tree, new_node);
}
else {
tree = new_node;
}
}
}
pbvh_iter_end(&iter);
if (tree) {
float tmin = FLT_MAX;
traverse_tree(tree, hcb, hit_data, &tmin);
free_tree(tree);
}
}
static int update_search_cb(PBVHNode *node, void *data_v)
{
int flag= GET_INT_FROM_POINTER(data_v);
@@ -985,7 +1118,8 @@ void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *tot
GHashIterator *hiter;
GHash *map;
void *face, **faces;
int i, tot;
unsigned i;
int tot;
map = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "pbvh_get_grid_updates gh");
@@ -1086,6 +1220,18 @@ void BLI_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max
copy_v3_v3(bb_max, node->orig_vb.bmax);
}
void BLI_pbvh_node_get_proxies(PBVHNode* node, PBVHProxyNode** proxies, int* proxy_count)
{
if (node->proxy_count > 0) {
if (proxies) *proxies = node->proxies;
if (proxy_count) *proxy_count = node->proxy_count;
}
else {
if (proxies) *proxies = 0;
if (proxy_count) *proxy_count = 0;
}
}
/********************************* Raycast ***********************************/
typedef struct {
@@ -1100,16 +1246,13 @@ typedef struct {
static int ray_aabb_intersect(PBVHNode *node, void *data_v)
{
RaycastData *ray = data_v;
float bb_min[3], bb_max[3], bbox[2][3];
float bbox[2][3];
float tmin, tmax, tymin, tymax, tzmin, tzmax;
if(ray->original)
BLI_pbvh_node_get_original_BB(node, bb_min, bb_max);
BLI_pbvh_node_get_original_BB(node, bbox[0], bbox[1]);
else
BLI_pbvh_node_get_BB(node, bb_min, bb_max);
copy_v3_v3(bbox[0], bb_min);
copy_v3_v3(bbox[1], bb_max);
BLI_pbvh_node_get_BB(node, bbox[0], bbox[1]);
tmin = (bbox[ray->sign[0]][0] - ray->start[0]) * ray->inv_dir[0];
tmax = (bbox[1-ray->sign[0]][0] - ray->start[0]) * ray->inv_dir[0];
@@ -1119,8 +1262,10 @@ static int ray_aabb_intersect(PBVHNode *node, void *data_v)
if((tmin > tymax) || (tymin > tmax))
return 0;
if(tymin > tmin)
tmin = tymin;
if(tymax < tmax)
tmax = tymax;
@@ -1129,20 +1274,20 @@ static int ray_aabb_intersect(PBVHNode *node, void *data_v)
if((tmin > tzmax) || (tzmin > tmax))
return 0;
if(tzmin > tmin)
tmin = tzmin;
// XXX jwilkins: tmax does not need to be updated since we don't use it
// keeping this here for future reference
//if(tzmax < tmax) tmax = tzmax;
node->tmin = tmin;
return 1;
/* XXX: Not sure about this?
if(tzmin > tmin)
tmin = tzmin;
if(tzmax < tmax)
tmax = tzmax;
return ((tmin < t1) && (tmax > t0));
*/
}
void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitCallback cb, void *data,
void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data,
float ray_start[3], float ray_normal[3], int original)
{
RaycastData rcd;
@@ -1156,37 +1301,24 @@ void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitCallback cb, void *data,
rcd.sign[2] = rcd.inv_dir[2] < 0;
rcd.original = original;
BLI_pbvh_search_callback(bvh, ray_aabb_intersect, &rcd, cb, data);
BLI_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data);
}
/* XXX: Code largely copied from bvhutils.c, could be unified */
/* Returns 1 if a better intersection has been found */
static int ray_face_intersection(float ray_start[3], float ray_normal[3],
float *t0, float *t1, float *t2, float *t3,
float *fdist)
{
int hit = 0;
float dist;
do
{
float dist = FLT_MAX;
if(!isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2,
&dist, NULL, 0.1f))
dist = FLT_MAX;
if(dist >= 0 && dist < *fdist) {
hit = 1;
*fdist = dist;
}
t1 = t2;
t2 = t3;
t3 = NULL;
} while(t2);
return hit;
if ((isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2, &dist, NULL, 0.1f) && dist < *fdist) ||
(t3 && isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t2, t3, &dist, NULL, 0.1f) && dist < *fdist))
{
*fdist = dist;
return 1;
}
else {
return 0;
}
}
int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
@@ -1399,3 +1531,86 @@ int BLI_pbvh_isDeformed(PBVH *pbvh)
{
return pbvh->deformed;
}
/* Proxies */
PBVHProxyNode* BLI_pbvh_node_add_proxy(PBVH* bvh, PBVHNode* node)
{
int index, totverts;
#pragma omp critical
{
index = node->proxy_count;
node->proxy_count++;
if (node->proxies)
node->proxies= MEM_reallocN(node->proxies, node->proxy_count*sizeof(PBVHProxyNode));
else
node->proxies= MEM_mallocN(sizeof(PBVHProxyNode), "PBVHNodeProxy");
if (bvh->grids)
totverts = node->totprim*bvh->gridsize*bvh->gridsize;
else
totverts = node->uniq_verts;
node->proxies[index].co= MEM_callocN(sizeof(float[3])*totverts, "PBVHNodeProxy.co");
}
return node->proxies + index;
}
void BLI_pbvh_node_free_proxies(PBVHNode* node)
{
#pragma omp critical
{
int p;
for (p= 0; p < node->proxy_count; p++) {
MEM_freeN(node->proxies[p].co);
node->proxies[p].co= 0;
}
MEM_freeN(node->proxies);
node->proxies = 0;
node->proxy_count= 0;
}
}
void BLI_pbvh_gather_proxies(PBVH* pbvh, PBVHNode*** r_array, int* r_tot)
{
PBVHNode **array= NULL, **newarray, *node;
int tot= 0, space= 0;
int n;
for (n= 0; n < pbvh->totnode; n++) {
node = pbvh->nodes + n;
if(node->proxy_count > 0) {
if(tot == space) {
/* resize array if needed */
space= (tot == 0)? 32: space*2;
newarray= MEM_callocN(sizeof(PBVHNode)*space, "BLI_pbvh_gather_proxies");
if (array) {
memcpy(newarray, array, sizeof(PBVHNode)*tot);
MEM_freeN(array);
}
array= newarray;
}
array[tot]= node;
tot++;
}
}
if(tot == 0 && array) {
MEM_freeN(array);
array= NULL;
}
*r_array= array;
*r_tot= tot;
}

View File

@@ -1539,6 +1539,7 @@ static void lib_link_brush(FileData *fd, Main *main)
brush->id.flag -= LIB_NEEDLINK;
brush->mtex.tex= newlibadr_us(fd, brush->id.lib, brush->mtex.tex);
brush->image_icon= newlibadr_us(fd, brush->id.lib, brush->image_icon);
brush->clone.image= newlibadr_us(fd, brush->id.lib, brush->clone.image);
}
}
@@ -10971,6 +10972,82 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
{
/* GSOC 2010 Sculpt - New settings for Brush */
Brush *brush;
for (brush= main->brush.first; brush; brush= brush->id.next) {
/* Sanity Check */
// infinite number of dabs
if (brush->spacing == 0)
brush->spacing = 10;
// will have no effect
if (brush->alpha == 0)
brush->alpha = 0.5f;
// bad radius
if (brush->unprojected_radius == 0)
brush->unprojected_radius = 0.125;
// unusable size
if (brush->size == 0)
brush->size = 35;
// can't see overlay
if (brush->texture_overlay_alpha == 0)
brush->texture_overlay_alpha = 33;
// same as draw brush
if (brush->crease_pinch_factor == 0)
brush->crease_pinch_factor = 0.5f;
// will sculpt no vertexes
if (brush->plane_trim == 0)
brush->plane_trim = 0.5f;
// same as smooth stroke off
if (brush->smooth_stroke_radius == 0)
brush->smooth_stroke_radius= 75;
// will keep cursor in one spot
if (brush->smooth_stroke_radius == 1)
brush->smooth_stroke_factor= 0.9f;
// same as dots
if (brush->rate == 0)
brush->rate = 0.1f;
/* New Settings */
if (main->versionfile < 252 || (main->versionfile == 252 && main->subversionfile < 6)) {
brush->flag |= BRUSH_SPACE_ATTEN; // explicitly enable adaptive space
// spacing was originally in pixels, convert it to percentage for new version
// size should not be zero due to sanity check above
brush->spacing = (int)(100*((float)brush->spacing) / ((float)brush->size));
if (brush->add_col[0] == 0 &&
brush->add_col[1] == 0 &&
brush->add_col[2] == 0)
{
brush->add_col[0] = 1.00;
brush->add_col[1] = 0.39;
brush->add_col[2] = 0.39;
}
if (brush->sub_col[0] == 0 &&
brush->sub_col[1] == 0 &&
brush->sub_col[2] == 0)
{
brush->sub_col[0] = 0.39;
brush->sub_col[1] = 0.39;
brush->sub_col[2] = 1.00;
}
}
}
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */

View File

@@ -243,7 +243,7 @@ static void draw_gpencil_panel (bContext *C, uiLayout *layout, bGPdata *gpd, Poi
col= uiLayoutColumn(layout, 0);
/* current Grease Pencil block */
// TODO: show some info about who owns this?
uiTemplateID(col, C, ctx_ptr, "grease_pencil", "GPENCIL_OT_data_add", NULL, "GPENCIL_OT_data_unlink");
uiTemplateID(col, C, ctx_ptr, "grease_pencil", "GPENCIL_OT_data_add", NULL, "GPENCIL_OT_data_unlink", NULL);
/* add new layer button - can be used even when no data, since it can add a new block too */
uiItemO(col, NULL, 0, "GPENCIL_OT_layer_add");

View File

@@ -669,11 +669,11 @@ uiBlock *uiLayoutAbsoluteBlock(uiLayout *layout);
void uiTemplateHeader(uiLayout *layout, struct bContext *C, int menus);
void uiTemplateDopeSheetFilter(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr);
void uiTemplateID(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname,
char *newop, char *openop, char *unlinkop);
char *newop, char *openop, char *unlinkop, char *filterop);
void uiTemplateIDBrowse(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname,
char *newop, char *openop, char *unlinkop);
char *newop, char *openop, char *unlinkop, char *filterop);
void uiTemplateIDPreview(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname,
char *newop, char *openop, char *unlinkop, int rows, int cols);
char *newop, char *openop, char *unlinkop, char *filterop, int rows, int cols);
void uiTemplateAnyID(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname,
char *proptypename, char *text);
void uiTemplatePathBuilder(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname,

View File

@@ -46,6 +46,7 @@
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
#include "DNA_brush_types.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -762,6 +763,7 @@ static void icon_create_mipmap(struct PreviewImage* prv_img, int miplevel)
prv_img->w[miplevel] = size;
prv_img->h[miplevel] = size;
prv_img->changed[miplevel] = 1;
prv_img->changed_timestamp[miplevel] = 0;
prv_img->rect[miplevel] = MEM_callocN(size*size*sizeof(unsigned int), "prv_rect");
}
}
@@ -976,6 +978,16 @@ int ui_id_icon_get(bContext *C, ID *id, int preview)
/* checks if not exists, or changed */
ui_id_icon_render(C, id, preview);
break;
case ID_BR:
{ /* use the image in the brush as the icon */
/* XXX redundancy here can be reduced be rewriting this switch as an if */
ID* ima_id = (ID*)((Brush*)id)->image_icon;
id = ima_id ? ima_id : id;
iconid= BKE_icon_getid(id);
/* checks if not exists, or changed */
ui_id_icon_render(C, id, preview);
}
break;
default:
break;
}

View File

@@ -42,6 +42,7 @@
#include "BKE_main.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "BKE_report.h"
#include "ED_screen.h"
#include "ED_render.h"
@@ -141,6 +142,8 @@ typedef struct TemplateID {
ListBase *idlb;
int prv_rows, prv_cols;
char filterop[64];
} TemplateID;
/* Search browse menu, assign */
@@ -170,15 +173,53 @@ static void id_search_cb(const bContext *C, void *arg_template, char *str, uiSea
/* ID listbase */
for(id= lb->first; id; id= id->next) {
if(!((flag & PROP_ID_SELF_CHECK) && id == id_from)) {
int filter_yes;
/* hide dot-datablocks */
if(U.uiflag & USER_HIDE_DOT)
filter_yes= 0;
/* use filter */
if (template->filterop[0] != 0) {
PointerRNA ptr;
ReportList reports;
FunctionRNA *func;
ParameterList parms;
RNA_id_pointer_create(id, &ptr);
BKE_reports_init(&reports, RPT_PRINT);
func= RNA_struct_find_function(&ptr, template->filterop);
if (func) {
RNA_parameter_list_create(&parms, &ptr, func);
RNA_parameter_set_lookup(&parms, "context", &C);
if (RNA_function_call(C, &reports, &ptr, func, &parms) == 0) {
int* ret;
RNA_parameter_get_lookup(&parms, "ret", &ret);
if (!(*ret)) {
RNA_parameter_list_free(&parms);
continue;
}
else {
filter_yes= 1;
}
}
RNA_parameter_list_free(&parms);
}
}
/* hide dot-datablocks, but only if filter does not force it visible */
if(!filter_yes && U.uiflag & USER_HIDE_DOT)
if ((id->name[2]=='.') && (str[0] != '.'))
continue;
if(BLI_strcasestr(id->name+2, str)) {
iconid= ui_id_icon_get((bContext*)C, id, 1);
if(!uiSearchItemAdd(items, id->name+2, id, iconid))
break;
}
@@ -340,7 +381,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
}
}
static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, int flag, char *newop, char *openop, char *unlinkop)
static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, int flag, char *newop, char *openop, char *unlinkop, char *filterop)
{
uiBut *but;
uiBlock *block;
@@ -480,7 +521,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str
uiBlockEndAlign(block);
}
static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop, int flag, int prv_rows, int prv_cols)
static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop, char* filterop, int flag, int prv_rows, int prv_cols)
{
TemplateID *template;
PropertyRNA *prop;
@@ -498,7 +539,12 @@ static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, char
template->prop= prop;
template->prv_rows = prv_rows;
template->prv_cols = prv_cols;
if (filterop)
BLI_strncpy(template->filterop, filterop, sizeof(template->filterop));
else
template->filterop[0] = 0;
if(newop)
flag |= UI_ID_ADD_NEW;
if(openop)
@@ -512,26 +558,25 @@ static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, char
*/
if(template->idlb) {
uiLayoutRow(layout, 1);
template_ID(C, layout, template, type, flag, newop, openop, unlinkop);
template_ID(C, layout, template, type, flag, newop, openop, unlinkop, filterop);
}
MEM_freeN(template);
}
void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop)
void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop, char *filterop)
{
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE, 0, 0);
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, filterop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE, 0, 0);
}
void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop)
void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop, char *filterop)
{
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME, 0, 0);
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, filterop, UI_ID_BROWSE|UI_ID_RENAME, 0, 0);
}
void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop, int rows, int cols)
void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop, char *filterop, int rows, int cols)
{
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE|UI_ID_PREVIEWS, rows, cols);
ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, filterop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE|UI_ID_PREVIEWS, rows, cols);
}
/************************ ID Chooser Template ***************************/

View File

@@ -1463,7 +1463,7 @@ void init_userdef_do_versions(void)
SETCOL(btheme->tv3d.lastsel_point, 0xff, 0xff, 0xff, 255);
}
}
if (G.main->versionfile <= 252 || (G.main->versionfile == 252 && G.main->subversionfile < 5)) {
if (G.main->versionfile < 252 || (G.main->versionfile == 252 && G.main->subversionfile < 5)) {
bTheme *btheme;
/* interface_widgets.c */
@@ -1521,7 +1521,14 @@ void init_userdef_do_versions(void)
/* this timer uses U */
// XXX reset_autosave();
/* GSOC Sculpt 2010 - Sanity check on Sculpt/Paint settings */
if (U.sculpt_paint_unified_alpha == 0)
U.sculpt_paint_unified_alpha = 0.5f;
if (U.sculpt_paint_unified_unprojected_radius == 0)
U.sculpt_paint_unified_unprojected_radius = 0.125f;
if (U.sculpt_paint_unified_size == 0)
U.sculpt_paint_unified_size = 35;
}

View File

@@ -3,6 +3,8 @@ Import ('env')
sources = env.Glob('*.c')
defs = []
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../render/extern/include'
@@ -12,7 +14,11 @@ if env['OURPLATFORM'] == 'linux2':
cflags='-pthread'
incs += ' ../../../extern/binreloc/include'
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
incs += ' ' + env['BF_PTHREADS_INC']
if env['OURPLATFORM'] == 'linuxcross':
if env['WITH_BF_OPENMP']:
incs += ' ' + env['BF_OPENMP_INC']
env.BlenderLib ( 'bf_editors_sculpt_paint', sources, Split(incs), [], libtype=['core'], priority=[40] )
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
incs += ' ' + env['BF_PTHREADS_INC']
env.BlenderLib ( 'bf_editors_sculpt_paint', sources, Split(incs), defines=defs, libtype=['core'], priority=[40] )

View File

@@ -641,8 +641,8 @@ static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float
}
}
else {
xi = (uv[0]*ibuf->x) + 0.5f;
yi = (uv[1]*ibuf->y) + 0.5f;
xi = (int)((uv[0]*ibuf->x) + 0.5f);
yi = (int)((uv[1]*ibuf->y) + 0.5f);
//if (xi<0 || xi>=ibuf->x || yi<0 || yi>=ibuf->y) return 0;
@@ -1053,15 +1053,15 @@ static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const fl
* This is incorrect. Its already given radians but without it wont work.
* need to look into a fix - campbell */
if (is_quad) {
a1 = shell_angle_to_dist(angle_normalized_v2v2(dir4, dir1) * (M_PI/180.0f));
a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * (M_PI/180.0f));
a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * (M_PI/180.0f));
a4 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir4) * (M_PI/180.0f));
a1 = shell_angle_to_dist(angle_normalized_v2v2(dir4, dir1) * ((float)M_PI/180.0f));
a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * ((float)M_PI/180.0f));
a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * ((float)M_PI/180.0f));
a4 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir4) * ((float)M_PI/180.0f));
}
else {
a1 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir1) * (M_PI/180.0f));
a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * (M_PI/180.0f));
a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * (M_PI/180.0f));
a1 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir1) * ((float)M_PI/180.0f));
a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * ((float)M_PI/180.0f));
a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * ((float)M_PI/180.0f));
}
if (is_quad) {
@@ -1197,7 +1197,7 @@ static void screen_px_from_persp(
w[2] *= wtot_inv;
}
else {
w[0] = w[1] = w[2] = 1.0/3.0; /* dummy values for zero area face */
w[0] = w[1] = w[2] = 1.0f/3.0f; /* dummy values for zero area face */
}
/* done re-weighting */
@@ -2513,11 +2513,11 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
w[0]=w[1]=w[2]= 0.0;
if (side) {
w[fidx1?fidx1-1:0] = fac;
w[fidx2?fidx2-1:0] = 1.0-fac;
w[fidx2?fidx2-1:0] = 1.0f-fac;
}
else {
w[fidx1] = fac;
w[fidx2] = 1.0-fac;
w[fidx2] = 1.0f-fac;
}
#endif
}
@@ -2571,11 +2571,12 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i
static void project_paint_bucket_bounds(const ProjPaintState *ps, const float min[2], const float max[2], int bucketMin[2], int bucketMax[2])
{
/* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */
bucketMin[0] = (int)(((float)(min[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 0.5f; /* these offsets of 0.5 and 1.5 seem odd but they are correct */
bucketMin[1] = (int)(((float)(min[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 0.5f;
/* XXX: the offset of 0.5 is always truncated to zero and the offset of 1.5f is always truncated to 1, is this really correct?? - jwilkins */
bucketMin[0] = (int)((int)(((float)(min[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 0.5f); /* these offsets of 0.5 and 1.5 seem odd but they are correct */
bucketMin[1] = (int)((int)(((float)(min[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 0.5f);
bucketMax[0] = (int)(((float)(max[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 1.5f;
bucketMax[1] = (int)(((float)(max[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 1.5f;
bucketMax[0] = (int)((int)(((float)(max[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 1.5f);
bucketMax[1] = (int)((int)(((float)(max[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 1.5f);
/* incase the rect is outside the mesh 2d bounds */
CLAMP(bucketMin[0], 0, ps->buckets_x);
@@ -3029,19 +3030,19 @@ static void project_paint_begin(ProjPaintState *ps)
if(ps->source==PROJ_SRC_VIEW) {
#ifdef PROJ_DEBUG_WINCLIP
CLAMP(ps->screenMin[0], -ps->brush->size, ps->winx + ps->brush->size);
CLAMP(ps->screenMax[0], -ps->brush->size, ps->winx + ps->brush->size);
CLAMP(ps->screenMin[0], (float)(-ps->brush->size), (float)(ps->winx + ps->brush->size));
CLAMP(ps->screenMax[0], (float)(-ps->brush->size), (float)(ps->winx + ps->brush->size));
CLAMP(ps->screenMin[1], -ps->brush->size, ps->winy + ps->brush->size);
CLAMP(ps->screenMax[1], -ps->brush->size, ps->winy + ps->brush->size);
CLAMP(ps->screenMin[1], (float)(-ps->brush->size), (float)(ps->winy + ps->brush->size));
CLAMP(ps->screenMax[1], (float)(-ps->brush->size), (float)(ps->winy + ps->brush->size));
#endif
}
else { /* reprojection, use bounds */
ps->screenMin[0]= 0;
ps->screenMax[0]= ps->winx;
ps->screenMax[0]= (float)(ps->winx);
ps->screenMin[1]= 0;
ps->screenMax[1]= ps->winy;
ps->screenMax[1]= (float)(ps->winy);
}
/* only for convenience */
@@ -3497,7 +3498,7 @@ static int project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf
project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds);
if ( (ps->source != PROJ_SRC_VIEW) ||
project_bucket_isect_circle(ps->context_bucket_x, ps->context_bucket_y, mval, ps->brush->size * ps->brush->size, bucket_bounds)
project_bucket_isect_circle(ps->context_bucket_x, ps->context_bucket_y, mval, (float)(ps->brush->size * ps->brush->size), bucket_bounds)
) {
*bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x);
ps->context_bucket_x++;
@@ -3545,7 +3546,7 @@ static void blend_color_mix(unsigned char *cp, const unsigned char *cp1, const u
static void blend_color_mix_float(float *cp, const float *cp1, const float *cp2, const float fac)
{
const float mfac= 1.0-fac;
const float mfac= 1.0f-fac;
cp[0]= mfac*cp1[0] + fac*cp2[0];
cp[1]= mfac*cp1[1] + fac*cp2[1];
cp[2]= mfac*cp1[2] + fac*cp2[2];
@@ -3712,7 +3713,7 @@ static void *do_projectpaint_thread(void *ph_v)
}
/* avoid a square root with every dist comparison */
brush_size_sqared = ps->brush->size * ps->brush->size;
brush_size_sqared = (float)(ps->brush->size * ps->brush->size);
/* printf("brush bounds %d %d %d %d\n", bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */
@@ -3771,7 +3772,7 @@ static void *do_projectpaint_thread(void *ph_v)
falloff = 1.0f - falloff;
falloff = 1.0f - (falloff * falloff);
mask_short = projPixel->mask * (ps->brush->alpha * falloff);
mask_short = (unsigned short)(projPixel->mask * (ps->brush->alpha * falloff));
if (mask_short > projPixel->mask_max) {
mask = ((float)mask_short)/65535.0f;
projPixel->mask_max = mask_short;
@@ -3932,8 +3933,8 @@ static int project_paint_sub_stroke(ProjPaintState *ps, BrushPainter *painter, i
/* Use mouse coords as floats for projection painting */
float pos[2];
pos[0] = mval_i[0];
pos[1] = mval_i[1];
pos[0] = (float)(mval_i[0]);
pos[1] = (float)(mval_i[1]);
// we may want to use this later
// brush_painter_require_imbuf(painter, ((ibuf->rect_float)? 1: 0), 0, 0);
@@ -4057,7 +4058,8 @@ static int imapaint_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, flo
{
float inrgb[3];
if ((x >= ibuf->x) || (y >= ibuf->y)) {
// XXX: signed unsigned mismatch
if ((x >= (unsigned int)(ibuf->x)) || (y >= (unsigned int)(ibuf->y))) {
if (torus) imapaint_ibuf_get_set_rgb(ibuf, x, y, 1, 0, inrgb);
else return 0;
}
@@ -4611,8 +4613,8 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps)
ps->normal_angle_inner= ps->normal_angle= settings->imapaint.normal_angle;
}
ps->normal_angle_inner *= M_PI_2 / 90;
ps->normal_angle *= M_PI_2 / 90;
ps->normal_angle_inner *= (float)(M_PI_2 / 90);
ps->normal_angle *= (float)(M_PI_2 / 90);
ps->normal_angle_range = ps->normal_angle - ps->normal_angle_inner;
if(ps->normal_angle_range <= 0.0f)
@@ -4711,8 +4713,8 @@ static void paint_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
int mouse[2], redraw;
RNA_float_get_array(itemptr, "mouse", mousef);
mouse[0] = mousef[0];
mouse[1] = mousef[1];
mouse[0] = (int)(mousef[0]);
mouse[1] = (int)(mousef[1]);
time= RNA_float_get(itemptr, "time");
pressure= RNA_float_get(itemptr, "pressure");
@@ -4832,8 +4834,8 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event)
/* fill in stroke */
RNA_collection_add(op->ptr, "stroke", &itemptr);
mousef[0] = mouse[0];
mousef[1] = mouse[1];
mousef[0] = (float)(mouse[0]);
mousef[1] = (float)(mouse[1]);
RNA_float_set_array(&itemptr, "mouse", mousef);
RNA_float_set(&itemptr, "time", (float)(time - pop->starttime));
RNA_float_set(&itemptr, "pressure", pressure);
@@ -4950,7 +4952,7 @@ static void brush_drawcursor(bContext *C, int x, int y, void *customdata)
glColor4ub(255, 255, 255, 128);
glEnable( GL_LINE_SMOOTH );
glEnable(GL_BLEND);
glutil_draw_lined_arc(0.0, M_PI*2.0, brush->size*0.5f, 40);
glutil_draw_lined_arc(0, (float)(M_PI*2.0), brush->size*0.5f, 40);
glDisable(GL_BLEND);
glDisable( GL_LINE_SMOOTH );
@@ -4977,7 +4979,7 @@ static int paint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *eve
ToolSettings *ts = CTX_data_scene(C)->toolsettings;
get_imapaint_zoom(C, &zoom, &zoom);
toggle_paint_cursor(C, !ts->imapaint.paintcursor);
brush_radial_control_invoke(op, paint_brush(&ts->imapaint.paint), 0.5 * zoom);
brush_radial_control_invoke(op, paint_brush(&ts->imapaint.paint), 0.5f * zoom);
return WM_radial_control_invoke(C, op, event);
}
@@ -4997,7 +4999,7 @@ static int paint_radial_control_exec(bContext *C, wmOperator *op)
int ret;
char str[256];
get_imapaint_zoom(C, &zoom, &zoom);
ret = brush_radial_control_exec(op, brush, 2.0 / zoom);
ret = brush_radial_control_exec(op, brush, 2.0f / zoom);
WM_radial_control_string(op, str, 256);
WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush);

View File

@@ -110,6 +110,13 @@ void PAINT_OT_face_select_all(struct wmOperatorType *ot);
int facemask_paint_poll(struct bContext *C);
/* stroke operator */
typedef enum wmBrushStrokeMode {
WM_BRUSHSTROKE_NORMAL,
WM_BRUSHSTROKE_INVERT,
WM_BRUSHSTROKE_SMOOTH,
} wmBrushStrokeMode;
/* paint_undo.c */
typedef void (*UndoRestoreCb)(struct bContext *C, struct ListBase *lb);
typedef void (*UndoFreeCb)(struct ListBase *lb);

View File

@@ -39,28 +39,25 @@
#include "sculpt_intern.h"
#include <string.h>
//#include <stdio.h>
/* Brush operators */
static int brush_add_exec(bContext *C, wmOperator *op)
{
/*int type = RNA_enum_get(op->ptr, "type");*/
Brush *br = NULL;
Paint *paint = paint_get_active(CTX_data_scene(C));
Brush *br = paint_brush(paint);
br = add_brush("Brush");
if (br)
br = copy_brush(br);
else
br = add_brush("Brush");
if(br)
paint_brush_set(paint_get_active(CTX_data_scene(C)), br);
paint_brush_set(paint_get_active(CTX_data_scene(C)), br);
return OPERATOR_FINISHED;
}
static EnumPropertyItem brush_type_items[] = {
{OB_MODE_SCULPT, "SCULPT", ICON_SCULPTMODE_HLT, "Sculpt", ""},
{OB_MODE_VERTEX_PAINT, "VERTEX_PAINT", ICON_VPAINT_HLT, "Vertex Paint", ""},
{OB_MODE_WEIGHT_PAINT, "WEIGHT_PAINT", ICON_WPAINT_HLT, "Weight Paint", ""},
{OB_MODE_TEXTURE_PAINT, "TEXTURE_PAINT", ICON_TPAINT_HLT, "Texture Paint", ""},
{0, NULL, 0, NULL, NULL}};
void BRUSH_OT_add(wmOperatorType *ot)
{
/* identifiers */
@@ -72,9 +69,43 @@ void BRUSH_OT_add(wmOperatorType *ot)
ot->exec= brush_add_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
ot->flag= OPTYPE_UNDO;
}
RNA_def_enum(ot->srna, "type", brush_type_items, OB_MODE_VERTEX_PAINT, "Type", "Which paint mode to create the brush for.");
static int brush_scale_size_exec(bContext *C, wmOperator *op)
{
/*int type = RNA_enum_get(op->ptr, "type");*/
Paint *paint = paint_get_active(CTX_data_scene(C));
Brush *br = paint_brush(paint);
float factor = RNA_float_get(op->ptr, "scalar");
if (br) {
if (U.sculpt_paint_settings & SCULPT_PAINT_USE_UNIFIED_SIZE) {
U.sculpt_paint_unified_size *= factor;
}
else {
br->size *= factor;
}
}
return OPERATOR_FINISHED;
}
void BRUSH_OT_scale_size(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Scale Sculpt/Paint Brush Size";
ot->description= "Change brush size by a scalar";
ot->idname= "BRUSH_OT_scale_size";
/* api callbacks */
ot->exec= brush_scale_size_exec;
/* flags */
ot->flag= OPTYPE_UNDO;
RNA_def_float(ot->srna, "scalar", 1, 0, 2, "Scalar", "Factor to scale brush size by", 0, 2);
}
static int vertex_color_set_exec(bContext *C, wmOperator *op)
@@ -108,8 +139,10 @@ void ED_operatortypes_paint(void)
{
/* brush */
WM_operatortype_append(BRUSH_OT_add);
WM_operatortype_append(BRUSH_OT_scale_size);
WM_operatortype_append(BRUSH_OT_curve_preset);
/* image */
WM_operatortype_append(PAINT_OT_texture_paint_toggle);
WM_operatortype_append(PAINT_OT_texture_paint_radial_control);
@@ -141,6 +174,7 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_face_select_all);
}
static void ed_keymap_paint_brush_switch(wmKeyMap *keymap, const char *path)
{
wmKeyMapItem *kmi;
@@ -180,15 +214,13 @@ static void ed_keymap_paint_brush_switch(wmKeyMap *keymap, const char *path)
static void ed_keymap_paint_brush_size(wmKeyMap *keymap, const char *path)
{
wmKeyMapItem *kmi;
kmi= WM_keymap_add_item(keymap, "WM_OT_context_scale_int", LEFTBRACKETKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", path);
RNA_float_set(kmi->ptr, "value", 0.9);
kmi= WM_keymap_add_item(keymap, "WM_OT_context_scale_int", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", path);
RNA_float_set(kmi->ptr, "value", 10.0/9.0); // 1.1111....
}
kmi= WM_keymap_add_item(keymap, "BRUSH_OT_scale_size", LEFTBRACKETKEY, KM_PRESS, 0, 0);
RNA_float_set(kmi->ptr, "scalar", 0.9);
kmi= WM_keymap_add_item(keymap, "BRUSH_OT_scale_size", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
RNA_float_set(kmi->ptr, "scalar", 10.0/9.0); // 1.1111....
}
void ED_keymap_paint(wmKeyConfig *keyconf)
{
@@ -200,12 +232,15 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
keymap= WM_keymap_find(keyconf, "Sculpt", 0, 0);
keymap->poll= sculpt_poll;
RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, 0, 0)->ptr, "mode", WM_RADIALCONTROL_SIZE);
RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_RADIALCONTROL_STRENGTH);
RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", WM_RADIALCONTROL_ANGLE);
RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", WM_RADIALCONTROL_ANGLE);
WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "mode", WM_BRUSHSTROKE_NORMAL);
RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "mode", WM_BRUSHSTROKE_INVERT);
RNA_enum_set(WM_keymap_add_item(keymap, "SCULPT_OT_brush_stroke", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", WM_BRUSHSTROKE_SMOOTH);
//stroke_mode_modal_keymap(keyconf);
for(i=0; i<=5; i++)
RNA_int_set(WM_keymap_add_item(keymap, "OBJECT_OT_subdivision_set", ZEROKEY+i, KM_PRESS, KM_CTRL, 0)->ptr, "level", i);
@@ -221,7 +256,8 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
ed_keymap_paint_brush_switch(keymap, "tool_settings.sculpt.active_brush_index");
ed_keymap_paint_brush_size(keymap, "tool_settings.sculpt.brush.size");
/* */
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", AKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.sculpt.brush.use_anchor");
@@ -254,11 +290,10 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", LKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.sculpt.active_brush_name");
RNA_string_set(kmi->ptr, "value", "Layer");
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", TKEY, KM_PRESS, KM_SHIFT, 0); // was just T in 2.4x
RNA_string_set(kmi->ptr, "data_path", "tool_settings.sculpt.active_brush_name");
RNA_string_set(kmi->ptr, "value", "Flatten");
/* Vertex Paint mode */
keymap= WM_keymap_find(keyconf, "Vertex Paint", 0, 0);

View File

@@ -20,7 +20,7 @@
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
* Contributor(s): Jason Wilkins, Tom Musgrove.
*
* ***** END GPL LICENSE BLOCK *****
*
@@ -35,6 +35,7 @@
#include "BKE_context.h"
#include "BKE_paint.h"
#include "BKE_brush.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -49,6 +50,9 @@
#include "ED_view3d.h"
#include "paint_intern.h"
#include "sculpt_intern.h" // XXX, for expedience in getting this working, refactor later (or this just shows that this needs unification)
#include "BKE_image.h"
#include <float.h>
#include <math.h>
@@ -96,54 +100,748 @@ static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata
glDisable(GL_LINE_SMOOTH);
}
static void paint_draw_cursor(bContext *C, int x, int y, void *customdata)
#if 0
// grid texture for testing
#define GRID_WIDTH 8
#define GRID_LENGTH 8
#define W (0xFFFFFFFF)
#define G (0x00888888)
#define E (0xE1E1E1E1)
#define C (0xC3C3C3C3)
#define O (0xB4B4B4B4)
#define Q (0xA9A9A9A9)
static unsigned grid_texture0[256] =
{
Paint *paint = paint_get_active(CTX_data_scene(C));
Brush *brush = paint_brush(paint);
W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,G,G,G,G,G,G,G,G,G,G,G,G,G,G,W,
W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,W,
};
if(!(paint->flags & PAINT_SHOW_BRUSH))
return;
static unsigned grid_texture1[64] =
{
C,C,C,C,C,C,C,C,
C,G,G,G,G,G,G,C,
C,G,G,G,G,G,G,C,
C,G,G,G,G,G,G,C,
C,G,G,G,G,G,G,C,
C,G,G,G,G,G,G,C,
C,G,G,G,G,G,G,C,
C,C,C,C,C,C,C,C,
};
glColor4ubv(paint_get_active(CTX_data_scene(C))->paint_cursor_col);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
static unsigned grid_texture2[16] =
{
O,O,O,O,
O,G,G,O,
O,G,G,O,
O,O,O,O,
};
glTranslatef((float)x, (float)y, 0.0f);
glutil_draw_lined_arc(0.0, M_PI*2.0, brush->size, 40);
glTranslatef((float)-x, (float)-y, 0.0f);
static unsigned grid_texture3[4] =
{
Q,Q,
Q,Q,
};
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
static unsigned grid_texture4[1] =
{
Q,
};
#undef W
#undef G
#undef E
#undef C
#undef O
#undef Q
static void load_grid()
{
static GLuint overlay_texture;
if (!overlay_texture) {
//GLfloat largest_supported_anisotropy;
glGenTextures(1, &overlay_texture);
glBindTexture(GL_TEXTURE_2D, overlay_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, grid_texture0);
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, grid_texture1);
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, grid_texture2);
glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, grid_texture3);
glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, grid_texture4);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
//glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_supported_anisotropy);
}
}
#endif
extern float get_tex_pixel(Brush* br, float u, float v);
typedef struct Snapshot {
float size[3];
float ofs[3];
float rot;
int brush_size;
int winx;
int winy;
int brush_map_mode;
int curve_changed_timestamp;
} Snapshot;
static int same_snap(Snapshot* snap, Brush* brush, ViewContext* vc)
{
MTex* mtex = &brush->mtex;
return
(mtex->tex &&
mtex->ofs[0] == snap->ofs[0] &&
mtex->ofs[1] == snap->ofs[1] &&
mtex->ofs[2] == snap->ofs[2] &&
mtex->size[0] == snap->size[0] &&
mtex->size[1] == snap->size[1] &&
mtex->size[2] == snap->size[2] &&
mtex->rot == snap->rot) &&
((mtex->brush_map_mode == MTEX_MAP_MODE_FIXED && sculpt_get_brush_size(brush) <= snap->brush_size) || (sculpt_get_brush_size(brush) == snap->brush_size)) && // make brush smaller shouldn't cause a resample
mtex->brush_map_mode == snap->brush_map_mode &&
vc->ar->winx == snap->winx &&
vc->ar->winy == snap->winy;
}
static void make_snap(Snapshot* snap, Brush* brush, ViewContext* vc)
{
if (brush->mtex.tex) {
snap->brush_map_mode = brush->mtex.brush_map_mode;
copy_v3_v3(snap->ofs, brush->mtex.ofs);
copy_v3_v3(snap->size, brush->mtex.size);
snap->rot = brush->mtex.rot;
}
else {
snap->brush_map_mode = -1;
snap->ofs[0]= snap->ofs[0]= snap->ofs[0]= -1;
snap->size[0]= snap->size[0]= snap->size[0]= -1;
snap->rot = -1;
}
snap->brush_size = sculpt_get_brush_size(brush);
snap->winx = vc->ar->winx;
snap->winy = vc->ar->winy;
}
int load_tex(Sculpt *sd, Brush* br, ViewContext* vc)
{
static GLuint overlay_texture = 0;
static int init = 0;
static int tex_changed_timestamp = -1;
static int curve_changed_timestamp = -1;
static Snapshot snap;
static int old_size = -1;
GLubyte* buffer = 0;
int size;
int j;
int refresh;
if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED && !br->mtex.tex) return 0;
refresh =
!overlay_texture ||
(br->mtex.tex &&
(!br->mtex.tex->preview ||
br->mtex.tex->preview->changed_timestamp[0] != tex_changed_timestamp)) ||
!br->curve ||
br->curve->changed_timestamp != curve_changed_timestamp ||
!same_snap(&snap, br, vc);
if (refresh) {
if (br->mtex.tex && br->mtex.tex->preview)
tex_changed_timestamp = br->mtex.tex->preview->changed_timestamp[0];
if (br->curve)
curve_changed_timestamp = br->curve->changed_timestamp;
make_snap(&snap, br, vc);
if (br->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) {
int s = sculpt_get_brush_size(br);
int r = 1;
for (s >>= 1; s > 0; s >>= 1)
r++;
size = (1<<r);
if (size < 256)
size = 256;
if (size < old_size)
size = old_size;
}
else
size = 512;
if (old_size != size) {
if (overlay_texture) {
glDeleteTextures(1, &overlay_texture);
overlay_texture = 0;
}
init = 0;
old_size = size;
}
buffer = MEM_mallocN(sizeof(GLubyte)*size*size, "load_tex");
#pragma omp parallel for schedule(static) if (sd->flags & SCULPT_USE_OPENMP)
for (j= 0; j < size; j++) {
int i;
float y;
float len;
for (i= 0; i < size; i++) {
// largely duplicated from tex_strength
const float rotation = -br->mtex.rot;
float diameter = sculpt_get_brush_size(br);
int index = j*size + i;
float x;
float avg;
x = (float)i/size;
y = (float)j/size;
x -= 0.5f;
y -= 0.5f;
if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) {
x *= vc->ar->winx / diameter;
y *= vc->ar->winy / diameter;
}
else {
x *= 2;
y *= 2;
}
len = sqrtf(x*x + y*y);
if ((br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) || len <= 1) {
/* it is probably worth optimizing for those cases where
the texture is not rotated by skipping the calls to
atan2, sqrtf, sin, and cos. */
if (br->mtex.tex && (rotation > 0.001 || rotation < -0.001)) {
const float angle = atan2(y, x) + rotation;
x = len * cos(angle);
y = len * sin(angle);
}
x *= br->mtex.size[0];
y *= br->mtex.size[1];
x += br->mtex.ofs[0];
y += br->mtex.ofs[1];
avg = br->mtex.tex ? get_tex_pixel(br, x, y) : 1;
avg += br->texture_sample_bias;
if (br->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED)
avg *= brush_curve_strength(br, len, 1); /* Falloff curve */
buffer[index] = (GLubyte)(255*avg);
}
else {
buffer[index] = 0;
}
}
}
if (!overlay_texture)
glGenTextures(1, &overlay_texture);
}
else {
size= old_size;
}
glBindTexture(GL_TEXTURE_2D, overlay_texture);
if (refresh) {
if (!init) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, size, size, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
init = 1;
}
else {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_ALPHA, GL_UNSIGNED_BYTE, buffer);
}
if (buffer)
MEM_freeN(buffer);
}
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (br->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
}
return 1;
}
/* Convert a point in model coordinates to 2D screen coordinates. */
// XXX duplicated from sculpt.c, deal with this later.
static void projectf(bglMats *mats, const float v[3], float p[2])
{
double ux, uy, uz;
gluProject(v[0],v[1],v[2], mats->modelview, mats->projection,
(GLint *)mats->viewport, &ux, &uy, &uz);
p[0]= ux;
p[1]= uy;
}
static int project_brush_radius(RegionView3D* rv3d, float radius, float location[3], bglMats* mats)
{
float view[3], nonortho[3], ortho[3], offset[3], p1[2], p2[2];
viewvector(rv3d, location, view);
// create a vector that is not orthogonal to view
if (fabsf(view[0]) < 0.1) {
nonortho[0] = view[0] + 1;
nonortho[1] = view[1];
nonortho[2] = view[2];
}
else if (fabsf(view[1]) < 0.1) {
nonortho[0] = view[0];
nonortho[1] = view[1] + 1;
nonortho[2] = view[2];
}
else {
nonortho[0] = view[0];
nonortho[1] = view[1];
nonortho[2] = view[2] + 1;
}
// get a vector in the plane of the view
cross_v3_v3v3(ortho, nonortho, view);
normalize_v3(ortho);
// make a point on the surface of the brush tagent to the view
mul_v3_fl(ortho, radius);
add_v3_v3v3(offset, location, ortho);
// project the center of the brush, and the tagent point to the view onto the screen
projectf(mats, location, p1);
projectf(mats, offset, p2);
// the distance between these points is the size of the projected brush in pixels
return len_v2v2(p1, p2);
}
int sculpt_get_brush_geometry(bContext* C, int x, int y, int* pixel_radius, float location[3], float modelview[16], float projection[16], int viewport[4])
{
struct PaintStroke *stroke;
float window[2];
int hit;
stroke = paint_stroke_new(C, NULL, NULL, NULL, NULL);
window[0] = x + stroke->vc.ar->winrct.xmin;
window[1] = y + stroke->vc.ar->winrct.ymin;
memcpy(modelview, stroke->vc.rv3d->viewmat, sizeof(float[16]));
memcpy(projection, stroke->vc.rv3d->winmat, sizeof(float[16]));
memcpy(viewport, stroke->mats.viewport, sizeof(int[4]));
if (stroke->vc.obact->sculpt && stroke->vc.obact->sculpt->pbvh && sculpt_stroke_get_location(C, stroke, location, window)) {
*pixel_radius = project_brush_radius(stroke->vc.rv3d, sculpt_get_brush_unprojected_radius(stroke->brush), location, &stroke->mats);
if (*pixel_radius == 0)
*pixel_radius = sculpt_get_brush_size(stroke->brush);
mul_m4_v3(stroke->vc.obact->sculpt->ob->obmat, location);
hit = 1;
}
else {
Sculpt* sd = CTX_data_tool_settings(C)->sculpt;
Brush* brush = paint_brush(&sd->paint);
*pixel_radius = sculpt_get_brush_size(brush);
hit = 0;
}
paint_stroke_free(stroke);
return hit;
}
// XXX duplicated from sculpt.c
float unproject_brush_radius(Object *ob, ViewContext *vc, float center[3], float offset)
{
float delta[3], scale, loc[3];
mul_v3_m4v3(loc, ob->obmat, center);
initgrabz(vc->rv3d, loc[0], loc[1], loc[2]);
window_to_3d_delta(vc->ar, delta, offset, 0);
scale= fabsf(mat4_to_scale(ob->obmat));
scale= (scale == 0.0f)? 1.0f: scale;
return len_v3(delta)/scale;
}
// XXX paint cursor now does a lot of the same work that is needed during a sculpt stroke
// problem: all this stuff was not intended to be used at this point, so things feel a
// bit hacked. I've put lots of stuff in Brush that probably better goes in Paint
// Functions should be refactored so that they can be used between sculpt.c and
// paint_stroke.c clearly and optimally and the lines of communication between the
// two modules should be more clearly defined.
static void paint_draw_cursor(bContext *C, int x, int y, void *unused)
{
ViewContext vc;
(void)unused;
view3d_set_viewcontext(C, &vc);
if (vc.obact->sculpt) {
Paint *paint = paint_get_active(CTX_data_scene(C));
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Brush *brush = paint_brush(paint);
int pixel_radius, viewport[4];
float location[3], modelview[16], projection[16];
int hit;
int flip;
int sign;
float* col;
float alpha;
float visual_strength = sculpt_get_brush_alpha(brush)*sculpt_get_brush_alpha(brush);
const float min_alpha = 0.20f;
const float max_alpha = 0.80f;
{
const float u = 0.5f;
const float v = 1 - u;
const float r = 20;
const float dx = sd->last_x - x;
const float dy = sd->last_y - y;
if (dx*dx + dy*dy >= r*r) {
sd->last_angle = atan2(dx, dy);
sd->last_x = u*sd->last_x + v*x;
sd->last_y = u*sd->last_y + v*y;
}
}
if(!sculpt_get_lock_brush_size(brush) && !(paint->flags & PAINT_SHOW_BRUSH))
return;
hit = sculpt_get_brush_geometry(C, x, y, &pixel_radius, location, modelview, projection, viewport);
if (sculpt_get_lock_brush_size(brush))
sculpt_set_brush_size(brush, pixel_radius);
// XXX: no way currently to know state of pen flip or invert key modifier without starting a stroke
flip = 1;
sign = flip * ((brush->flag & BRUSH_DIR_IN)? -1 : 1);
if (sign < 0 && ELEM4(brush->sculpt_tool, SCULPT_TOOL_DRAW, SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY, SCULPT_TOOL_PINCH))
col = brush->sub_col;
else
col = brush->add_col;
alpha = (paint->flags & PAINT_SHOW_BRUSH_ON_SURFACE) ? min_alpha + (visual_strength*(max_alpha-min_alpha)) : 0.50f;
if (ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_FIXED, MTEX_MAP_MODE_TILED) && brush->flag & BRUSH_TEXTURE_OVERLAY) {
glPushAttrib(
GL_COLOR_BUFFER_BIT|
GL_CURRENT_BIT|
GL_DEPTH_BUFFER_BIT|
GL_ENABLE_BIT|
GL_LINE_BIT|
GL_POLYGON_BIT|
GL_STENCIL_BUFFER_BIT|
GL_TRANSFORM_BIT|
GL_VIEWPORT_BIT|
GL_TEXTURE_BIT);
if (load_tex(sd, brush, &vc)) {
glEnable(GL_BLEND);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_FALSE);
glDepthFunc(GL_ALWAYS);
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) {
glTranslatef(0.5f, 0.5f, 0);
if (brush->flag & BRUSH_RAKE) {
glRotatef(sd->last_angle*(float)(180.0/M_PI), 0, 0, 1);
}
else {
glRotatef(sd->special_rotation*(float)(180.0/M_PI), 0, 0, 1);
}
glTranslatef(-0.5f, -0.5f, 0);
if (sd->draw_pressure && (brush->flag & BRUSH_SIZE_PRESSURE)) {
glTranslatef(0.5f, 0.5f, 0);
glScalef(1.0f/sd->pressure_value, 1.0f/sd->pressure_value, 1);
glTranslatef(-0.5f, -0.5f, 0);
}
}
glColor4f(
U.sculpt_paint_overlay_col[0],
U.sculpt_paint_overlay_col[1],
U.sculpt_paint_overlay_col[2],
brush->texture_overlay_alpha / 100.0f);
glBegin(GL_QUADS);
if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_FIXED) {
if (sd->draw_anchored) {
glTexCoord2f(0, 0);
glVertex2f(sd->anchored_initial_mouse[0]-sd->anchored_size - vc.ar->winrct.xmin, sd->anchored_initial_mouse[1]-sd->anchored_size - vc.ar->winrct.ymin);
glTexCoord2f(1, 0);
glVertex2f(sd->anchored_initial_mouse[0]+sd->anchored_size - vc.ar->winrct.xmin, sd->anchored_initial_mouse[1]-sd->anchored_size - vc.ar->winrct.ymin);
glTexCoord2f(1, 1);
glVertex2f(sd->anchored_initial_mouse[0]+sd->anchored_size - vc.ar->winrct.xmin, sd->anchored_initial_mouse[1]+sd->anchored_size - vc.ar->winrct.ymin);
glTexCoord2f(0, 1);
glVertex2f(sd->anchored_initial_mouse[0]-sd->anchored_size - vc.ar->winrct.xmin, sd->anchored_initial_mouse[1]+sd->anchored_size - vc.ar->winrct.ymin);
}
else {
glTexCoord2f(0, 0);
glVertex2f((float)x-sculpt_get_brush_size(brush), (float)y-sculpt_get_brush_size(brush));
glTexCoord2f(1, 0);
glVertex2f((float)x+sculpt_get_brush_size(brush), (float)y-sculpt_get_brush_size(brush));
glTexCoord2f(1, 1);
glVertex2f((float)x+sculpt_get_brush_size(brush), (float)y+sculpt_get_brush_size(brush));
glTexCoord2f(0, 1);
glVertex2f((float)x-sculpt_get_brush_size(brush), (float)y+sculpt_get_brush_size(brush));
}
}
else {
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(1, 0);
glVertex2f(viewport[2], 0);
glTexCoord2f(1, 1);
glVertex2f(viewport[2], viewport[3]);
glTexCoord2f(0, 1);
glVertex2f(0, viewport[3]);
}
glEnd();
glPopMatrix();
}
glPopAttrib();
}
if (hit) {
float unprojected_radius;
// XXX duplicated from brush_strength & paint_stroke_add_step, refactor later
//wmEvent* event = CTX_wm_window(C)->eventstate;
if (sd->draw_pressure && (brush->flag & BRUSH_ALPHA_PRESSURE))
visual_strength *= sd->pressure_value;
// don't show effect of strength past the soft limit
if (visual_strength > 1) visual_strength = 1;
if (sd->draw_anchored) {
unprojected_radius = unproject_brush_radius(CTX_data_active_object(C), &vc, location, sd->anchored_size);
}
else {
if (brush->flag & BRUSH_ANCHORED)
unprojected_radius = unproject_brush_radius(CTX_data_active_object(C), &vc, location, 8);
else
unprojected_radius = unproject_brush_radius(CTX_data_active_object(C), &vc, location, sculpt_get_brush_size(brush));
}
if (sd->draw_pressure && (brush->flag & BRUSH_SIZE_PRESSURE))
unprojected_radius *= sd->pressure_value;
if (!sculpt_get_lock_brush_size(brush))
sculpt_set_brush_unprojected_radius(brush, unprojected_radius);
if(!(paint->flags & PAINT_SHOW_BRUSH))
return;
}
glPushAttrib(
GL_COLOR_BUFFER_BIT|
GL_CURRENT_BIT|
GL_DEPTH_BUFFER_BIT|
GL_ENABLE_BIT|
GL_LINE_BIT|
GL_POLYGON_BIT|
GL_STENCIL_BUFFER_BIT|
GL_TRANSFORM_BIT|
GL_VIEWPORT_BIT|
GL_TEXTURE_BIT);
glColor4f(col[0], col[1], col[2], alpha);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
if (sd->draw_anchored) {
glTranslatef(sd->anchored_initial_mouse[0] - vc.ar->winrct.xmin, sd->anchored_initial_mouse[1] - vc.ar->winrct.ymin, 0.0f);
glutil_draw_lined_arc(0.0, M_PI*2.0, sd->anchored_size, 40);
glTranslatef(-sd->anchored_initial_mouse[0] + vc.ar->winrct.xmin, -sd->anchored_initial_mouse[1] + vc.ar->winrct.xmin, 0.0f);
}
else {
glTranslatef((float)x, (float)y, 0.0f);
glutil_draw_lined_arc(0.0, M_PI*2.0, sculpt_get_brush_size(brush), 40);
glTranslatef(-(float)x, -(float)y, 0.0f);
}
glPopAttrib();
}
else {
Paint *paint = paint_get_active(CTX_data_scene(C));
Brush *brush = paint_brush(paint);
if(!(paint->flags & PAINT_SHOW_BRUSH))
return;
glColor4ubv(paint_get_active(CTX_data_scene(C))->paint_cursor_col);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glTranslatef((float)x, (float)y, 0.0f);
glutil_draw_lined_arc(0.0, M_PI*2.0, brush->size, 40); // XXX: for now use the brushes size instead of potentially using the unified size because the feature has been enabled for sculpt
glTranslatef((float)-x, (float)-y, 0.0f);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
}
}
/* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */
static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, float mouse[2])
static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, float mouse_in[2])
{
Paint *paint = paint_get_active(CTX_data_scene(C)); // XXX
Brush *brush = paint_brush(paint); // XXX
float mouse[2];
PointerRNA itemptr;
float pressure = 1;
float center[3] = {0, 0, 0};
int flip= event->shift?1:0;
float location[3];
float pressure;
int pen_flip;
ViewContext vc; // XXX
PaintStroke *stroke = op->customdata;
/* XXX: can remove the if statement once all modes have this */
if(stroke->get_location)
stroke->get_location(C, stroke, center, mouse);
view3d_set_viewcontext(C, &vc); // XXX
/* Tablet */
if(event->custom == EVT_DATA_TABLET) {
wmTabletData *wmtab= event->customdata;
if(wmtab->Active != EVT_TABLET_NONE)
pressure= wmtab->Pressure;
if(wmtab->Active == EVT_TABLET_ERASER)
flip = 1;
pressure = (wmtab->Active != EVT_TABLET_NONE) ? wmtab->Pressure : 1;
pen_flip = (wmtab->Active == EVT_TABLET_ERASER);
}
else {
pressure = 1;
pen_flip = 0;
}
// XXX: temporary check for sculpt mode until things are more unified
if (vc.obact->sculpt) {
float delta[3];
brush_jitter_pos(brush, mouse_in, mouse);
// XXX: meh, this is round about because brush_jitter_pos isn't written in the best way to be reused here
if (brush->flag & BRUSH_JITTER_PRESSURE) {
sub_v3_v3v3(delta, mouse, mouse_in);
mul_v3_fl(delta, pressure);
add_v3_v3v3(mouse, mouse_in, delta);
}
}
else
copy_v3_v3(mouse, mouse_in);
/* XXX: can remove the if statement once all modes have this */
if(stroke->get_location)
stroke->get_location(C, stroke, location, mouse);
else
zero_v3(location);
/* Add to stroke */
RNA_collection_add(op->ptr, "stroke", &itemptr);
RNA_float_set_array(&itemptr, "location", center);
RNA_float_set_array(&itemptr, "mouse", mouse);
RNA_boolean_set(&itemptr, "flip", flip);
RNA_float_set(&itemptr, "pressure", pressure);
RNA_float_set_array(&itemptr, "location", location);
RNA_float_set_array(&itemptr, "mouse", mouse);
RNA_boolean_set (&itemptr, "pen_flip", pen_flip);
RNA_float_set (&itemptr, "pressure", pressure);
stroke->last_mouse_position[0] = mouse[0];
stroke->last_mouse_position[1] = mouse[1];
@@ -154,10 +852,14 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev
/* Returns zero if no sculpt changes should be made, non-zero otherwise */
static int paint_smooth_stroke(PaintStroke *stroke, float output[2], wmEvent *event)
{
output[0] = event->x;
output[0] = event->x;
output[1] = event->y;
if(stroke->brush->flag & BRUSH_SMOOTH_STROKE && stroke->brush->sculpt_tool != SCULPT_TOOL_GRAB) {
if ((stroke->brush->flag & BRUSH_SMOOTH_STROKE) &&
!ELEM4(stroke->brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK) &&
!(stroke->brush->flag & BRUSH_ANCHORED) &&
!(stroke->brush->flag & BRUSH_RESTORE_MESH))
{
float u = stroke->brush->smooth_stroke_factor, v = 1.0 - u;
float dx = stroke->last_mouse_position[0] - event->x, dy = stroke->last_mouse_position[1] - event->y;
@@ -176,7 +878,9 @@ static int paint_smooth_stroke(PaintStroke *stroke, float output[2], wmEvent *ev
/* Returns zero if the stroke dots should not be spaced, non-zero otherwise */
static int paint_space_stroke_enabled(Brush *br)
{
return (br->flag & BRUSH_SPACE) && !(br->flag & BRUSH_ANCHORED) && (br->sculpt_tool != SCULPT_TOOL_GRAB);
return (br->flag & BRUSH_SPACE) &&
!(br->flag & BRUSH_ANCHORED) &&
!ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK);
}
/* For brushes with stroke spacing enabled, moves mouse in steps
@@ -187,23 +891,34 @@ static int paint_space_stroke(bContext *C, wmOperator *op, wmEvent *event, const
int cnt = 0;
if(paint_space_stroke_enabled(stroke->brush)) {
float mouse[2] = {stroke->last_mouse_position[0], stroke->last_mouse_position[1]};
float vec[2] = {final_mouse[0] - mouse[0], final_mouse[1] - mouse[1]};
float mouse[2];
float vec[2];
float length, scale;
int steps = 0, i;
/* Normalize the vector between the last stroke dot and the goal */
length = sqrt(vec[0]*vec[0] + vec[1]*vec[1]);
copy_v2_v2(mouse, stroke->last_mouse_position);
sub_v2_v2v2(vec, final_mouse, mouse);
length = len_v2(vec);
if(length > FLT_EPSILON) {
scale = stroke->brush->spacing / length;
vec[0] *= scale;
vec[1] *= scale;
int steps;
int i;
float pressure = 1;
// XXX duplicate code
if(event->custom == EVT_DATA_TABLET) {
wmTabletData *wmtab= event->customdata;
if(wmtab->Active != EVT_TABLET_NONE)
pressure = stroke->brush->flag & BRUSH_SIZE_PRESSURE ? wmtab->Pressure : 1;
}
scale = (sculpt_get_brush_size(stroke->brush)*pressure*stroke->brush->spacing/50.0f) / length;
mul_v2_fl(vec, scale);
steps = (int)(1.0f / scale);
steps = (int)(length / stroke->brush->spacing);
for(i = 0; i < steps; ++i, ++cnt) {
mouse[0] += vec[0];
mouse[1] += vec[1];
add_v2_v2(mouse, vec);
paint_brush_stroke_add_step(C, op, event, mouse);
}
}
@@ -283,14 +998,25 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
//ED_region_tag_redraw(ar);
}
}
else
else {
paint_brush_stroke_add_step(C, op, event, mouse);
}
}
else
;//ED_region_tag_redraw(ar);
}
}
/* 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 &&
stroke->stroke_started &&
paint_space_stroke_enabled(stroke->brush) &&
!(stroke->brush->flag & BRUSH_ANCHORED) &&
!(stroke->brush->flag & BRUSH_SMOOTH_STROKE))
{
paint_brush_stroke_add_step(C, op, event, mouse);
}
return OPERATOR_RUNNING_MODAL;
}

View File

@@ -216,6 +216,10 @@ void BRUSH_OT_curve_preset(wmOperatorType *ot)
{CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""},
{CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""},
{CURVE_PRESET_MAX, "MAX", 0, "Max", ""},
{CURVE_PRESET_MID9, "MID9", 0, "Mid9", ""},
{CURVE_PRESET_LINE, "LINE", 0, "Line", ""},
{CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""},
{CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""},
{0, NULL, 0, NULL, NULL}};
ot->name= "Preset";
@@ -225,7 +229,7 @@ void BRUSH_OT_curve_preset(wmOperatorType *ot)
ot->exec= brush_curve_preset_exec;
ot->poll= brush_curve_preset_poll;
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
ot->flag= OPTYPE_UNDO;
RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
}

File diff suppressed because it is too large Load Diff

View File

@@ -32,6 +32,9 @@
#include "DNA_listBase.h"
#include "DNA_vec_types.h"
#include "DNA_key_types.h"
#include "BLI_pbvh.h"
struct bContext;
struct Brush;
@@ -65,8 +68,49 @@ void sculpt_stroke_free(struct SculptStroke *);
void sculpt_stroke_add_point(struct SculptStroke *, const short x, const short y);
void sculpt_stroke_apply(struct Sculpt *sd, struct SculptStroke *);
void sculpt_stroke_apply_all(struct Sculpt *sd, struct SculptStroke *);
int sculpt_stroke_get_location(bContext *C, struct PaintStroke *stroke, float out[3], float mouse[2]);
/* Partial Mesh Visibility */
void sculptmode_pmv(int mode);
/* Undo */
typedef struct SculptUndoNode {
struct SculptUndoNode *next, *prev;
char idname[MAX_ID_NAME]; /* name instead of pointer*/
void *node; /* only during push, not valid afterwards! */
float (*co)[3];
short (*no)[3];
int totvert;
/* non-multires */
int maxvert; /* to verify if totvert it still the same */
int *index; /* to restore into right location */
/* multires */
int maxgrid; /* same for grid */
int gridsize; /* same for grid */
int totgrid; /* to restore into right location */
int *grids; /* to restore into right location */
/* layer brush */
float *layer_disp;
/* shape keys */
char *shapeName[32]; /* keep size in sync with keyblock dna */
} SculptUndoNode;
SculptUndoNode *sculpt_undo_push_node(SculptSession *ss, PBVHNode *node);
SculptUndoNode *sculpt_undo_get_node(PBVHNode *node);
void sculpt_undo_push_begin(char *name);
void sculpt_undo_push_end(void);
struct MultiresModifierData *sculpt_multires_active(struct Scene *scene, struct Object *ob);
int sculpt_modifiers_active(Scene *scene, Object *ob);
void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]);
void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos);
#endif

View File

@@ -0,0 +1,302 @@
/*
* $Id: sculpt.c 29425 2010-06-12 15:05:19Z jwilkins $
*
* ***** 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.
*
* The Original Code is Copyright (C) 2006 by Nicholas Bishop
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*
* Implements the Sculpt Mode tools
*
*/
#include "BLI_math.h"
#include "BLI_ghash.h"
#include "BLI_threads.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_mesh_types.h"
#include "DNA_key_types.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_paint.h"
#include "BKE_mesh.h"
#include "BKE_key.h"
#include "WM_api.h"
#include "WM_types.h"
#include "ED_sculpt.h"
#include "paint_intern.h"
#include "sculpt_intern.h"
/************************** Undo *************************/
static void update_cb(PBVHNode *node, void *unused)
{
(void)unused;
BLI_pbvh_node_mark_update(node);
}
static void sculpt_undo_restore(bContext *C, ListBase *lb)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
DerivedMesh *dm = mesh_get_derived_final(scene, ob, 0);
SculptSession *ss = ob->sculpt;
SculptUndoNode *unode;
MVert *mvert;
MultiresModifierData *mmd;
int *index;
int i, j, update= 0;
sculpt_update_mesh_elements(scene, ob, 0);
for(unode=lb->first; unode; unode=unode->next) {
if(!(strcmp(unode->idname, ob->id.name)==0))
continue;
if(unode->maxvert) {
char *shapeName= (char*)unode->shapeName;
/* regular mesh restore */
if(ss->totvert != unode->maxvert)
continue;
if (ss->kb && strcmp(ss->kb->name, shapeName)) {
/* shape key has been changed before calling undo operator */
Key *key= ob_get_key(ob);
KeyBlock *kb= key_get_named_keyblock(key, shapeName);
if (kb) {
ob->shapenr= BLI_findindex(&key->block, kb) + 1;
ob->shapeflag|= OB_SHAPE_LOCK;
sculpt_update_mesh_elements(scene, ob, 0);
WM_event_add_notifier(C, NC_OBJECT|ND_DATA, ob);
} else {
/* key has been removed -- skip this undo node */
continue;
}
}
index= unode->index;
mvert= ss->mvert;
if (ss->kb) {
float (*vertCos)[3];
vertCos= key_to_vertcos(ob, ss->kb);
for(i=0; i<unode->totvert; i++)
swap_v3_v3(vertCos[index[i]], unode->co[i]);
/* propagate new coords to keyblock */
sculpt_vertcos_to_key(ob, ss->kb, vertCos);
/* pbvh uses it's own mvert array, so coords should be */
/* propagated to pbvh here */
BLI_pbvh_apply_vertCos(ss->pbvh, vertCos);
MEM_freeN(vertCos);
} else {
for(i=0; i<unode->totvert; i++) {
swap_v3_v3(mvert[index[i]].co, unode->co[i]);
mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
}
}
}
else if(unode->maxgrid && dm->getGridData) {
/* multires restore */
DMGridData **grids, *grid;
float (*co)[3];
int gridsize;
if(dm->getNumGrids(dm) != unode->maxgrid)
continue;
if(dm->getGridSize(dm) != unode->gridsize)
continue;
grids= dm->getGridData(dm);
gridsize= dm->getGridSize(dm);
co = unode->co;
for(j=0; j<unode->totgrid; j++) {
grid= grids[unode->grids[j]];
for(i=0; i<gridsize*gridsize; i++, co++)
swap_v3_v3(grid[i].co, co[0]);
}
}
update= 1;
}
if(update) {
/* we update all nodes still, should be more clever, but also
needs to work correct when exiting/entering sculpt mode and
the nodes get recreated, though in that case it could do all */
BLI_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, NULL);
BLI_pbvh_update(ss->pbvh, PBVH_UpdateBB|PBVH_UpdateOriginalBB|PBVH_UpdateRedraw, NULL);
if((mmd=sculpt_multires_active(scene, ob)))
multires_mark_as_modified(ob);
if(ss->modifiers_active || ((Mesh*)ob->data)->id.us > 1)
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
}
}
static void sculpt_undo_free(ListBase *lb)
{
SculptUndoNode *unode;
for(unode=lb->first; unode; unode=unode->next) {
if(unode->co)
MEM_freeN(unode->co);
if(unode->no)
MEM_freeN(unode->no);
if(unode->index)
MEM_freeN(unode->index);
if(unode->grids)
MEM_freeN(unode->grids);
if(unode->layer_disp)
MEM_freeN(unode->layer_disp);
}
}
SculptUndoNode *sculpt_undo_get_node(PBVHNode *node)
{
ListBase *lb= undo_paint_push_get_list(UNDO_PAINT_MESH);
SculptUndoNode *unode;
if(!lb)
return NULL;
for(unode=lb->first; unode; unode=unode->next)
if(unode->node == node)
return unode;
return NULL;
}
SculptUndoNode *sculpt_undo_push_node(SculptSession *ss, PBVHNode *node)
{
ListBase *lb= undo_paint_push_get_list(UNDO_PAINT_MESH);
Object *ob= ss->ob;
SculptUndoNode *unode;
int totvert, allvert, totgrid, maxgrid, gridsize, *grids;
/* list is manipulated by multiple threads, so we lock */
BLI_lock_thread(LOCK_CUSTOM1);
if((unode= sculpt_undo_get_node(node))) {
BLI_unlock_thread(LOCK_CUSTOM1);
return unode;
}
unode= MEM_callocN(sizeof(SculptUndoNode), "SculptUndoNode");
strcpy(unode->idname, ob->id.name);
unode->node= node;
BLI_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
BLI_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
&maxgrid, &gridsize, NULL, NULL);
unode->totvert= totvert;
/* we will use this while sculpting, is mapalloc slow to access then? */
unode->co= MEM_mapallocN(sizeof(float)*3*allvert, "SculptUndoNode.co");
unode->no= MEM_mapallocN(sizeof(short)*3*allvert, "SculptUndoNode.no");
undo_paint_push_count_alloc(UNDO_PAINT_MESH, (sizeof(float)*3 + sizeof(short)*3 + sizeof(int))*allvert);
BLI_addtail(lb, unode);
if(maxgrid) {
/* multires */
unode->maxgrid= maxgrid;
unode->totgrid= totgrid;
unode->gridsize= gridsize;
unode->grids= MEM_mapallocN(sizeof(int)*totgrid, "SculptUndoNode.grids");
}
else {
/* regular mesh */
unode->maxvert= ss->totvert;
unode->index= MEM_mapallocN(sizeof(int)*allvert, "SculptUndoNode.index");
}
BLI_unlock_thread(LOCK_CUSTOM1);
/* copy threaded, hopefully this is the performance critical part */
{
PBVHVertexIter vd;
BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) {
copy_v3_v3(unode->co[vd.i], vd.co);
if(vd.no) VECCOPY(unode->no[vd.i], vd.no)
else normal_float_to_short_v3(unode->no[vd.i], vd.fno);
if(vd.vert_indices) unode->index[vd.i]= vd.vert_indices[vd.i];
}
BLI_pbvh_vertex_iter_end;
}
if(unode->grids)
memcpy(unode->grids, grids, sizeof(int)*totgrid);
/* store active shape key */
if(ss->kb) BLI_strncpy((char*)unode->shapeName, ss->kb->name, sizeof(ss->kb->name));
else unode->shapeName[0]= '\0';
return unode;
}
void sculpt_undo_push_begin(char *name)
{
undo_paint_push_begin(UNDO_PAINT_MESH, name,
sculpt_undo_restore, sculpt_undo_free);
}
void sculpt_undo_push_end(void)
{
ListBase *lb= undo_paint_push_get_list(UNDO_PAINT_MESH);
SculptUndoNode *unode;
/* we don't need normals in the undo stack */
for(unode=lb->first; unode; unode=unode->next) {
if(unode->no) {
MEM_freeN(unode->no);
unode->no= NULL;
}
if(unode->layer_disp) {
MEM_freeN(unode->layer_disp);
unode->layer_disp= NULL;
}
}
undo_paint_push_end(UNDO_PAINT_MESH);
}

View File

@@ -792,7 +792,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propn
uiLayoutSetContextPointer(layout, "edit_image", &imaptr);
if(!compact)
uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL);
uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL, NULL);
// XXX missing: reload, pack

View File

@@ -4278,7 +4278,7 @@ static void draw_actuator_sound(uiLayout *layout, PointerRNA *ptr, bContext *C)
{
uiLayout *row, *col;
uiTemplateID(layout, C, ptr, "sound", NULL, "SOUND_OT_open", NULL);
uiTemplateID(layout, C, ptr, "sound", NULL, "SOUND_OT_open", NULL, NULL);
if (!RNA_pointer_get(ptr, "sound").data)
{
uiItemL(layout, "Select a sound from the list or load a new one", 0);

View File

@@ -237,7 +237,7 @@ static void nla_panel_animdata (const bContext *C, Panel *pa)
/* Active Action Properties ------------------------------------- */
/* action */
row= uiLayoutRow(layout, 1);
uiTemplateID(row, (bContext *)C, &adt_ptr, "action", "ACTION_OT_new", NULL, NULL /*"ACTION_OT_unlink"*/); // XXX: need to make these operators
uiTemplateID(row, (bContext *)C, &adt_ptr, "action", "ACTION_OT_new", NULL, NULL /*"ACTION_OT_unlink"*/, NULL); // XXX: need to make these operators
/* extrapolation */
row= uiLayoutRow(layout, 1);

View File

@@ -81,7 +81,7 @@
void node_buts_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
uiTemplateIDBrowse(layout, C, ptr, "nodetree", NULL, NULL, "");
uiTemplateIDBrowse(layout, C, ptr, "nodetree", NULL, NULL, "", NULL);
}
static void node_buts_value(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -306,7 +306,7 @@ static void node_shader_buts_material(uiLayout *layout, bContext *C, PointerRNA
bNode *node= ptr->data;
uiLayout *col;
uiTemplateID(layout, C, ptr, "material", "MATERIAL_OT_new", NULL, NULL);
uiTemplateID(layout, C, ptr, "material", "MATERIAL_OT_new", NULL, NULL, NULL);
if(!node->id) return;
@@ -467,7 +467,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
PointerRNA imaptr;
PropertyRNA *prop;
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL, NULL);
if(!node->id) return;
@@ -504,7 +504,7 @@ static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, Point
const char *layer_name;
char scene_name[19];
uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL);
uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, NULL);
if(!node->id) return;
@@ -1204,7 +1204,7 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *C, PointerRNA *pt
static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL, NULL);
}
static void node_texture_buts_output(uiLayout *layout, bContext *C, PointerRNA *ptr)

View File

@@ -69,6 +69,7 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_material.h"
#include "gpu_buffers.h"
#include "smoke_API.h"

View File

@@ -130,7 +130,7 @@ typedef struct PreviewImage {
unsigned int w[2];
unsigned int h[2];
short changed[2];
short pad0, pad1;
short changed_timestamp[2];
unsigned int * rect[2];
} PreviewImage;

View File

@@ -33,9 +33,9 @@
#include "DNA_ID.h"
#include "DNA_texture_types.h"
#ifndef MAX_MTEX
#define MAX_MTEX 18
#endif
//#ifndef MAX_MTEX // XXX Not used?
//#define MAX_MTEX 18
//#endif
struct CurveMapping;
struct MTex;
@@ -43,8 +43,8 @@ struct Image;
typedef struct BrushClone {
struct Image *image; /* image for clone tool */
float offset[2]; /* offset of clone image from canvas */
float alpha, pad; /* transparency for drawing of clone image */
float offset[2]; /* offset of clone image from canvas */
float alpha, pad; /* transparency for drawing of clone image */
} BrushClone;
typedef struct Brush {
@@ -53,50 +53,94 @@ typedef struct Brush {
struct BrushClone clone;
struct CurveMapping *curve; /* falloff curve */
struct MTex mtex;
short flag, blend; /* general purpose flag, blend mode */
int size; /* brush diameter */
float jitter; /* jitter the position of the brush */
float spacing; /* spacing of paint operations */
int smooth_stroke_radius; /* turning radius (in pixels) for smooth stroke */
float smooth_stroke_factor; /* higher values limit fast changes in the stroke direction */
float rate; /* paint operations / second (airbrush) */
struct Image *image_icon;
float rgb[3]; /* color */
float alpha; /* opacity */
float normal_weight;
char sculpt_tool; /* active sculpt tool */
short blend, pad; /* blend mode */
int size; /* brush diameter */
int flag; /* general purpose flag */
float jitter; /* jitter the position of the brush */
int spacing; /* spacing of paint operations */
int smooth_stroke_radius; /* turning radius (in pixels) for smooth stroke */
float smooth_stroke_factor; /* higher values limit fast changes in the stroke direction */
float rate; /* paint operations / second (airbrush) */
float rgb[3]; /* color */
float alpha; /* opacity */
int sculpt_plane; /* the direction of movement for sculpt vertices */
float plane_offset; /* offset for plane brushes (clay, flatten, fill, scrape) */
char sculpt_tool; /* active sculpt tool */
char vertexpaint_tool; /* active vertex/weight paint tool/blend mode */
char imagepaint_tool; /* active image paint tool */
char pad2;
char pad3;
float autosmooth_factor;
float crease_pinch_factor;
float plane_trim;
float texture_sample_bias;
int texture_overlay_alpha;
float unprojected_radius;
float add_col[3];
float sub_col[3];
} Brush;
/* Brush.flag */
#define BRUSH_AIRBRUSH 1
#define BRUSH_TORUS 2
#define BRUSH_ALPHA_PRESSURE 4
#define BRUSH_SIZE_PRESSURE 8
#define BRUSH_JITTER_PRESSURE 16 /* was BRUSH_RAD_PRESSURE */
#define BRUSH_SPACING_PRESSURE 32
#define BRUSH_FIXED_TEX 64
#define BRUSH_RAKE 128
#define BRUSH_ANCHORED 256
#define BRUSH_DIR_IN 512
#define BRUSH_SPACE 1024
#define BRUSH_SMOOTH_STROKE 2048
#define BRUSH_PERSISTENT 4096
#define BRUSH_ACCUMULATE 8192
#define BRUSH_LOCK_ALPHA 16384
#define BRUSH_AIRBRUSH (1<<0)
#define BRUSH_TORUS (1<<1)
#define BRUSH_ALPHA_PRESSURE (1<<2)
#define BRUSH_SIZE_PRESSURE (1<<3)
#define BRUSH_JITTER_PRESSURE (1<<4) /* was BRUSH_RAD_PRESSURE */
#define BRUSH_SPACING_PRESSURE (1<<5)
#define BRUSH_FIXED_TEX (1<<6)
#define BRUSH_RAKE (1<<7)
#define BRUSH_ANCHORED (1<<8)
#define BRUSH_DIR_IN (1<<9)
#define BRUSH_SPACE (1<<10)
#define BRUSH_SMOOTH_STROKE (1<<11)
#define BRUSH_PERSISTENT (1<<12)
#define BRUSH_ACCUMULATE (1<<13)
#define BRUSH_LOCK_ALPHA (1<<14)
#define BRUSH_ORIGINAL_NORMAL (1<<15)
#define BRUSH_OFFSET_PRESSURE (1<<16)
#define BRUSH_SPACE_ATTEN (1<<18)
#define BRUSH_ADAPTIVE_SPACE (1<<19)
#define BRUSH_LOCK_SIZE (1<<20)
#define BRUSH_TEXTURE_OVERLAY (1<<21)
#define BRUSH_EDGE_TO_EDGE (1<<22)
#define BRUSH_RESTORE_MESH (1<<23)
#define BRUSH_INVERSE_SMOOTH_PRESSURE (1<<24)
#define BRUSH_RANDOM_ROTATION (1<<25)
#define BRUSH_PLANE_TRIM (1<<26)
#define BRUSH_FRONTFACE (1<<27)
/* Brush.sculpt_tool */
#define SCULPT_TOOL_DRAW 1
#define SCULPT_TOOL_SMOOTH 2
#define SCULPT_TOOL_PINCH 3
#define SCULPT_TOOL_INFLATE 4
#define SCULPT_TOOL_GRAB 5
#define SCULPT_TOOL_LAYER 6
#define SCULPT_TOOL_FLATTEN 7
#define SCULPT_TOOL_CLAY 8
#define SCULPT_TOOL_DRAW 1
#define SCULPT_TOOL_SMOOTH 2
#define SCULPT_TOOL_PINCH 3
#define SCULPT_TOOL_INFLATE 4
#define SCULPT_TOOL_GRAB 5
#define SCULPT_TOOL_LAYER 6
#define SCULPT_TOOL_FLATTEN 7
#define SCULPT_TOOL_CLAY 8
#define SCULPT_TOOL_FILL 9
#define SCULPT_TOOL_SCRAPE 10
#define SCULPT_TOOL_NUDGE 11
#define SCULPT_TOOL_THUMB 12
#define SCULPT_TOOL_SNAKE_HOOK 13
#define SCULPT_TOOL_ROTATE 14
//#define SCULPT_TOOL_WAX 15 // XXX: reuse this slot later
#define SCULPT_TOOL_CREASE 16
#define SCULPT_TOOL_BLOB 17
#define SCULPT_TOOL_CLAY_TUBES 18
/* ImagePaintSettings.tool */
#define PAINT_TOOL_DRAW 0
@@ -104,5 +148,16 @@ typedef struct Brush {
#define PAINT_TOOL_SMEAR 2
#define PAINT_TOOL_CLONE 3
/* direction that the brush displaces along */
enum {
SCULPT_DISP_DIR_AREA,
SCULPT_DISP_DIR_VIEW,
SCULPT_DISP_DIR_X,
SCULPT_DISP_DIR_Y,
SCULPT_DISP_DIR_Z,
};
#define MAX_BRUSH_PIXEL_RADIUS 200
#endif

View File

@@ -64,7 +64,8 @@ typedef struct CurveMap {
typedef struct CurveMapping {
int flag, cur; /* cur; for buttons, to show active curve */
int preset, pad;
int preset;
int changed_timestamp;
rctf curr, clipr; /* current rect, clip rect (is default rect too) */
@@ -87,7 +88,9 @@ typedef enum CurveMappingPreset {
CURVE_PRESET_SHARP,
CURVE_PRESET_SMOOTH,
CURVE_PRESET_MAX,
CURVE_PRESET_MID9
CURVE_PRESET_MID9,
CURVE_PRESET_ROUND,
CURVE_PRESET_ROOT,
} CurveMappingPreset;
/* histogram->mode */

View File

@@ -569,12 +569,30 @@ typedef struct Sculpt {
Paint paint;
/* For rotating around a pivot point */
float pivot[3];
//float pivot[3]; XXX not used?
int flags;
/* Control tablet input */
char tablet_size, tablet_strength;
char pad[6];
//char tablet_size, tablet_strength; XXX not used?
int radial_symm[3];
// all this below is used to communicate with the cursor drawing routine
/* record movement of mouse so that rake can start at an intuitive angle */
float last_x, last_y;
float last_angle;
int draw_anchored;
int anchored_size;
float anchored_location[3];
float anchored_initial_mouse[2];
int draw_pressure;
float pressure_value;
float special_rotation;
int pad;
} Sculpt;
typedef struct VPaint {
@@ -1105,19 +1123,22 @@ typedef struct Scene {
/* Paint.flags */
typedef enum {
PAINT_SHOW_BRUSH = 1,
PAINT_FAST_NAVIGATE = 2
PAINT_SHOW_BRUSH = (1<<0),
PAINT_FAST_NAVIGATE = (1<<1),
PAINT_SHOW_BRUSH_ON_SURFACE = (1<<2),
} PaintFlags;
/* Sculpt.flags */
/* These can eventually be moved to paint flags? */
typedef enum SculptFlags {
SCULPT_SYMM_X = 1,
SCULPT_SYMM_Y = 2,
SCULPT_SYMM_Z = 4,
SCULPT_LOCK_X = 64,
SCULPT_LOCK_Y = 128,
SCULPT_LOCK_Z = 256
SCULPT_SYMM_X = (1<<0),
SCULPT_SYMM_Y = (1<<1),
SCULPT_SYMM_Z = (1<<2),
SCULPT_LOCK_X = (1<<3),
SCULPT_LOCK_Y = (1<<4),
SCULPT_LOCK_Z = (1<<5),
SCULPT_SYMMETRY_FEATHER = (1<<6),
SCULPT_USE_OPENMP = (1<<7),
} SculptFlags;
/* ImagePaintSettings.flag */

View File

@@ -341,9 +341,10 @@ typedef struct UserDef {
short gp_settings;
short tb_leftmouse, tb_rightmouse;
struct SolidLight light[3];
short sculpt_paint_settings; /* user preferences for sculpt and paint */
short tw_hotspot, tw_flag, tw_handlesize, tw_size;
short textimeout,texcollectrate;
short wmdrawmethod, wmpad;
short wmdrawmethod; /* removed wmpad */
int memcachelimit;
int prefetchframes;
short frameserverport;
@@ -373,6 +374,11 @@ typedef struct UserDef {
short autokey_flag; /* flags for autokeying */
struct ColorBand coba_weight; /* from texture.h */
int sculpt_paint_unified_size; /* unified radius of brush in pixels */
float sculpt_paint_unified_unprojected_radius;/* unified radius of brush in Blender units */
float sculpt_paint_unified_alpha; /* unified strength of brush */
float sculpt_paint_overlay_col[3];
} UserDef;
extern UserDef U; /* from blenkernel blender.c */
@@ -524,6 +530,11 @@ extern UserDef U; /* from blenkernel blender.c */
#define GP_PAINT_DOSMOOTH (1<<0)
#define GP_PAINT_DOSIMPLIFY (1<<1)
/* sculpt_paint_settings */
#define SCULPT_PAINT_USE_UNIFIED_SIZE (1<<0)
#define SCULPT_PAINT_USE_UNIFIED_ALPHA (1<<1)
#define SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE (1<<2)
/* color picker types */
#define USER_CP_CIRCLE 0
#define USER_CP_SQUARE_SV 1

View File

@@ -307,8 +307,7 @@ typedef struct wmOperator {
typedef enum wmRadialControlMode {
WM_RADIALCONTROL_SIZE,
WM_RADIALCONTROL_STRENGTH,
WM_RADIALCONTROL_ANGLE
WM_RADIALCONTROL_ANGLE,
} wmRadialControlMode;
#endif /* DNA_WINDOWMANAGER_TYPES_H */

View File

@@ -45,7 +45,6 @@ if env['WITH_BF_GAMEENGINE']:
if env['BF_UNIT_TEST']:
defs.append('UNIT_TEST')
if env['OURPLATFORM'] == 'linux2':
cflags='-pthread'
incs += ' ../../../extern/binreloc/include'

View File

@@ -52,6 +52,7 @@ INCLUDE_DIRECTORIES(
../../gpu
../../imbuf
../../render/extern/include
../../../../extern/glew/include
. )
FILE(GLOB INC_FILES ../*.h ../../makesdna/*.h)

View File

@@ -30,6 +30,7 @@
#include "DNA_brush_types.h"
#include "DNA_texture_types.h"
#include "DNA_scene_types.h"
#include "BLI_math.h"
@@ -51,6 +52,58 @@ static void rna_Brush_update(Main *bmain, Scene *scene, PointerRNA *ptr)
WM_main_add_notifier(NC_BRUSH|NA_EDITED, br);
}
static int rna_Brush_is_sculpt_brush(Brush *me, bContext *C)
{
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
int i;
for (i= 0; i < sd->paint.brush_count; i++) {
if (strcmp(me->id.name+2, sd->paint.brushes[i]->id.name+2) == 0)
return 1;
}
return 0;
}
static int rna_Brush_is_vpaint_brush(Brush *me, bContext *C)
{
VPaint *vp = CTX_data_tool_settings(C)->vpaint;
int i;
for (i= 0; i < vp->paint.brush_count; i++) {
if (strcmp(me->id.name+2, vp->paint.brushes[i]->id.name+2) == 0)
return 1;
}
return 0;
}
static int rna_Brush_is_wpaint_brush(Brush *me, bContext *C)
{
VPaint *vp = CTX_data_tool_settings(C)->wpaint;
int i;
for (i= 0; i < vp->paint.brush_count; i++) {
if (strcmp(me->id.name+2, vp->paint.brushes[i]->id.name+2) == 0)
return 1;
}
return 0;
}
static int rna_Brush_is_imapaint_brush(Brush *me, bContext *C)
{
ImagePaintSettings *data = &(CTX_data_tool_settings(C)->imapaint);
int i;
for (i= 0; i < data->paint.brush_count; i++) {
if (strcmp(me->id.name+2, data->paint.brushes[i]->id.name+2) == 0)
return 1;
}
return 0;
}
#else
static void rna_def_brush_texture_slot(BlenderRNA *brna)
@@ -100,14 +153,42 @@ static void rna_def_brush(BlenderRNA *brna)
static EnumPropertyItem brush_sculpt_tool_items[] = {
{SCULPT_TOOL_DRAW, "DRAW", 0, "Draw", ""},
{SCULPT_TOOL_SMOOTH, "SMOOTH", 0, "Smooth", ""},
{SCULPT_TOOL_CREASE, "CREASE", 0, "Crease", ""},
{SCULPT_TOOL_BLOB, "BLOB", 0, "Blob", ""},
{SCULPT_TOOL_PINCH, "PINCH", 0, "Pinch", ""},
{SCULPT_TOOL_INFLATE, "INFLATE", 0, "Inflate", ""},
{SCULPT_TOOL_GRAB, "GRAB", 0, "Grab", ""},
{SCULPT_TOOL_SNAKE_HOOK, "SNAKE_HOOK", 0, "Snake Hook", ""},
{SCULPT_TOOL_ROTATE, "ROTATE", 0, "Rotate", ""},
{SCULPT_TOOL_THUMB, "THUMB", 0, "Thumb", ""},
{SCULPT_TOOL_NUDGE, "NUDGE", 0, "Nudge", ""},
{SCULPT_TOOL_LAYER, "LAYER", 0, "Layer", ""},
{SCULPT_TOOL_FLATTEN, "FLATTEN", 0, "Flatten", ""},
{SCULPT_TOOL_CLAY, "CLAY", 0, "Clay", ""},
//{SCULPT_TOOL_CLAY_TUBES, "CLAY_TUBES", 0, "Clay Tubes", ""}, XXX: remove clay tubes from UI
{SCULPT_TOOL_FILL, "FILL", 0, "Fill", ""},
{SCULPT_TOOL_SCRAPE, "SCRAPE", 0, "Scrape", ""},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem brush_stroke_method_items[] = {
{0, "DOTS", 0, "Dots", ""},
{BRUSH_RESTORE_MESH, "DRAG_DOT", 0, "Drag Dot", ""},
{BRUSH_SPACE, "SPACE", 0, "Space", ""},
{BRUSH_ANCHORED, "ANCHORED", 0, "Anchored", ""},
{BRUSH_AIRBRUSH, "AIRBRUSH", 0, "Airbrush", ""},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem texture_angle_source_items[] = {
{0, "USER", 0, "User", ""},
{BRUSH_RAKE, "RAKE", 0, "Rake", ""},
{BRUSH_RANDOM_ROTATION, "RANDOM", 0, "Random", ""},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem texture_angle_source_no_random_items[] = {
{0, "USER", 0, "User", ""},
{BRUSH_RAKE, "RAKE", 0, "Rake", ""},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem brush_vertexpaint_tool_items[] = {
{0, "MIX", 0, "Mix", "Use mix blending mode while painting"},
{1, "ADD", 0, "Add", "Use add blending mode while painting"},
@@ -129,11 +210,76 @@ static void rna_def_brush(BlenderRNA *brna)
{0, "ADD", 0, "Add", "Add effect of brush"},
{BRUSH_DIR_IN, "SUBTRACT", 0, "Subtract", "Subtract effect of brush"},
{0, NULL, 0, NULL, NULL}};
static const EnumPropertyItem prop_flatten_contrast_items[]= {
{0, "FLATTEN", 0, "Flatten", "Add effect of brush"},
{BRUSH_DIR_IN, "CONTRAST", 0, "Contrast", "Subtract effect of brush"},
{0, NULL, 0, NULL, NULL}};
static const EnumPropertyItem prop_fill_deepen_items[]= {
{0, "FILL", 0, "Fill", "Add effect of brush"},
{BRUSH_DIR_IN, "DEEPEN", 0, "Deepen", "Subtract effect of brush"},
{0, NULL, 0, NULL, NULL}};
static const EnumPropertyItem prop_scrape_peaks_items[]= {
{0, "SCRAPE", 0, "Scrape", "Add effect of brush"},
{BRUSH_DIR_IN, "PEAKS", 0, "Peaks", "Subtract effect of brush"},
{0, NULL, 0, NULL, NULL}};
static const EnumPropertyItem prop_pinch_magnify_items[]= {
{0, "PINCH", 0, "Pinch", "Add effect of brush"},
{BRUSH_DIR_IN, "MAGNIFY", 0, "Magnify", "Subtract effect of brush"},
{0, NULL, 0, NULL, NULL}};
static const EnumPropertyItem prop_inflate_deflate_items[]= {
{0, "INFLATE", 0, "Inflate", "Add effect of brush"},
{BRUSH_DIR_IN, "DEFLATE", 0, "Deflate", "Subtract effect of brush"},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem brush_sculpt_plane_items[] = {
{SCULPT_DISP_DIR_AREA, "AREA", 0, "Area Plane", ""},
{SCULPT_DISP_DIR_VIEW, "VIEW", 0, "View Plane", ""},
{SCULPT_DISP_DIR_X, "X", 0, "X Plane", ""},
{SCULPT_DISP_DIR_Y, "Y", 0, "Y Plane", ""},
{SCULPT_DISP_DIR_Z, "Z", 0, "Z Plane", ""},
{0, NULL, 0, NULL, NULL}};
FunctionRNA *func;
PropertyRNA *parm;
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);
/* functions */
func= RNA_def_function(srna, "is_sculpt_brush", "rna_Brush_is_sculpt_brush");
RNA_def_function_ui_description(func, "Returns true if Brush can be used for sculpting");
parm= RNA_def_pointer(func, "context", "Context", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
parm= RNA_def_boolean(func, "ret", 0, "", "");
RNA_def_function_return(func, parm);
func= RNA_def_function(srna, "is_vpaint_brush", "rna_Brush_is_vpaint_brush");
RNA_def_function_ui_description(func, "Returns true if Brush can be used for vertex painting");
parm= RNA_def_pointer(func, "context", "Context", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
parm= RNA_def_boolean(func, "ret", 0, "", "");
RNA_def_function_return(func, parm);
func= RNA_def_function(srna, "is_wpaint_brush", "rna_Brush_is_wpaint_brush");
RNA_def_function_ui_description(func, "Returns true if Brush can be used for weight painting");
parm= RNA_def_pointer(func, "context", "Context", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
parm= RNA_def_boolean(func, "ret", 0, "", "");
RNA_def_function_return(func, parm);
func= RNA_def_function(srna, "is_imapaint_brush", "rna_Brush_is_imapaint_brush");
RNA_def_function_ui_description(func, "Returns true if Brush can be used for image painting");
parm= RNA_def_pointer(func, "context", "Context", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
parm= RNA_def_boolean(func, "ret", 0, "", "");
RNA_def_function_return(func, parm);
/* enums */
prop= RNA_def_property(srna, "blend", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_blend_items);
@@ -144,7 +290,7 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_enum_items(prop, brush_sculpt_tool_items);
RNA_def_property_ui_text(prop, "Sculpt Tool", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "vertexpaint_tool", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, brush_vertexpaint_tool_items);
RNA_def_property_ui_text(prop, "Vertex/Weight Paint Tool", "");
@@ -158,33 +304,94 @@ static void rna_def_brush(BlenderRNA *brna)
prop= RNA_def_property(srna, "direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_flip_direction_items);
RNA_def_property_ui_text(prop, "Direction", "Mapping type to use for this image in the game engine");
RNA_def_property_ui_text(prop, "Direction", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "stroke_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, brush_stroke_method_items);
RNA_def_property_ui_text(prop, "Stroke Method", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "texture_angle_source", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, texture_angle_source_items);
RNA_def_property_ui_text(prop, "Texture Angle Source", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "texture_angle_source_no_random", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, texture_angle_source_no_random_items);
RNA_def_property_ui_text(prop, "Texture Angle Source", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "flatten_contrast", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_flatten_contrast_items);
RNA_def_property_ui_text(prop, "Flatten/Contrast", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "inflate_deflate", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_inflate_deflate_items);
RNA_def_property_ui_text(prop, "Inflate/Deflate", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "fill_deepen", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_fill_deepen_items);
RNA_def_property_ui_text(prop, "Fill/Deepen", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "scrape_peaks", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_scrape_peaks_items);
RNA_def_property_ui_text(prop, "Scrape/Peaks", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "pinch_magnify", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_pinch_magnify_items);
RNA_def_property_ui_text(prop, "Pinch/Magnify", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "sculpt_plane", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, brush_sculpt_plane_items);
RNA_def_property_ui_text(prop, "Sculpt Plane", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
/* number values */
prop= RNA_def_property(srna, "size", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 1, 200);
RNA_def_property_ui_text(prop, "Size", "Diameter of the brush");
prop= RNA_def_property(srna, "size", PROP_INT, PROP_DISTANCE);
RNA_def_property_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS*10);
RNA_def_property_ui_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS, 1, 0);
RNA_def_property_ui_text(prop, "Size", "Radius of the brush in pixels");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "unprojected_radius", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_range(prop, 0, FLT_MAX);
RNA_def_property_ui_range(prop, 0, 1, 0, 0);
RNA_def_property_ui_text(prop, "Surface Size", "Radius of brush in Blender units");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "jitter", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "jitter");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Jitter", "Jitter the position of the brush while painting");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "spacing", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "spacing");
RNA_def_property_range(prop, 1.0f, 100.0f);
RNA_def_property_ui_text(prop, "Spacing", "Spacing between brush stamps");
prop= RNA_def_property(srna, "spacing", PROP_INT, PROP_PERCENTAGE);
RNA_def_property_int_sdna(prop, NULL, "spacing");
RNA_def_property_range(prop, 1, 1000);
RNA_def_property_ui_range(prop, 1, 500, 5, 0);
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, "smooth_stroke_radius", PROP_INT, PROP_NONE);
prop= RNA_def_property(srna, "smooth_stroke_radius", PROP_INT, PROP_DISTANCE);
RNA_def_property_range(prop, 10, 200);
RNA_def_property_ui_text(prop, "Smooth Stroke Radius", "Minimum distance from last point before stroke continues");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "smooth_stroke_factor", PROP_FLOAT, PROP_NONE);
prop= RNA_def_property(srna, "smooth_stroke_factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.5, 0.99);
RNA_def_property_ui_text(prop, "Smooth Stroke Factor", "Higher values give a smoother stroke");
RNA_def_property_update(prop, 0, "rna_Brush_update");
@@ -202,10 +409,56 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Color", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
prop= RNA_def_property(srna, "strength", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "alpha");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, 10.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 0.001);
RNA_def_property_ui_text(prop, "Strength", "How powerful the effect of the brush is when applied");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "plane_offset", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "plane_offset");
RNA_def_property_float_default(prop, 0);
RNA_def_property_range(prop, -2.0f, 2.0f);
RNA_def_property_ui_range(prop, -0.5f, 0.5f, 0.001, 0.001);
RNA_def_property_ui_text(prop, "Plane Offset", "Adjusts plane on which the brush acts towards or away from the object surface");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "plane_trim", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "plane_trim");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0, 1.0f);
RNA_def_property_ui_text(prop, "Plane Trim", "If a vertex is further from offset plane than this then it is not affected");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "texture_sample_bias", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "texture_sample_bias");
RNA_def_property_float_default(prop, 0);
RNA_def_property_range(prop, -1, 1);
RNA_def_property_ui_text(prop, "Texture Sample Bias", "Value added to texture samples");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "normal_weight", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "normal_weight");
RNA_def_property_float_default(prop, 0);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Strength", "The amount of pressure on the brush");
RNA_def_property_ui_text(prop, "Normal Weight", "How much grab will pull vertexes out of surface during a grab");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "crease_pinch_factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "crease_pinch_factor");
RNA_def_property_float_default(prop, 2.0f/3.0f);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Crease Brush Pinch Factor", "How much the crease brush pinches");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "autosmooth_factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "autosmooth_factor");
RNA_def_property_float_default(prop, 0);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 0.001);
RNA_def_property_ui_text(prop, "Autosmooth", "Amount of smoothing to automatically apply to each stroke");
RNA_def_property_update(prop, 0, "rna_Brush_update");
/* flag */
@@ -214,6 +467,11 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Airbrush", "Keep applying paint effect while holding mouse (spray)");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "use_original_normal", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ORIGINAL_NORMAL);
RNA_def_property_ui_text(prop, "Original Normal", "When locked keep using normal of surface where stroke was initiated");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "use_wrap", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_TORUS);
RNA_def_property_ui_text(prop, "Wrap", "Enable torus wrapping while painting");
@@ -225,6 +483,12 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Strength Pressure", "Enable tablet pressure sensitivity for strength");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "use_offset_pressure", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_OFFSET_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
RNA_def_property_ui_text(prop, "Plane Offset Pressure", "Enable tablet pressure sensitivity for offset");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "use_size_pressure", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SIZE_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
@@ -243,11 +507,32 @@ 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_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);
RNA_def_property_ui_text(prop, "Inverse Smooth Pressure", "Lighter pressure causes more smoothing to be applied");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "use_rake", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_RAKE);
RNA_def_property_ui_text(prop, "Rake", "Rotate the brush texture to match the stroke direction");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "use_random_rotation", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_RANDOM_ROTATION);
RNA_def_property_ui_text(prop, "Random Rotation", "Rotate the brush texture at random");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "use_plane_trim", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_PLANE_TRIM);
RNA_def_property_ui_text(prop, "Use Plane Trim", "Enable Plane Trim");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "use_frontface", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_FRONTFACE);
RNA_def_property_ui_text(prop, "Use Front-Face", "Brush only affects vertexes that face the viewer");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "use_anchor", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ANCHORED);
RNA_def_property_ui_text(prop, "Anchored", "Keep the brush anchored to the initial location");
@@ -273,6 +558,37 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Accumulate", "Accumulate stroke dabs on top of each other");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "use_space_atten", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_SPACE_ATTEN);
RNA_def_property_ui_text(prop, "Use Automatic Strength Adjustment", "Automatically adjusts strength to give consistent results for different spacings");
RNA_def_property_update(prop, 0, "rna_Brush_update");
/* adaptive space is not implemented yet */
prop= RNA_def_property(srna, "use_adaptive_space", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ADAPTIVE_SPACE);
RNA_def_property_ui_text(prop, "Adaptive Spacing", "Space daubs according to surface orientation instead of screen space");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "lock_brush_size", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_LOCK_SIZE);
RNA_def_property_ui_text(prop, "Use Blender Units", "When locked brush stays same size relative to object; when unlocked brush size is given in pixels");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "use_texture_overlay", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_TEXTURE_OVERLAY);
RNA_def_property_ui_text(prop, "Use Texture Overlay", "Show texture in viewport");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "edge_to_edge", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_EDGE_TO_EDGE);
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, "restore_mesh", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_RESTORE_MESH);
RNA_def_property_ui_text(prop, "Restore Mesh", "Allows a single dot to be carefully positioned");
RNA_def_property_update(prop, 0, "rna_Brush_update");
/* not exposed in the interface yet
prop= RNA_def_property(srna, "fixed_tex", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_FIXED_TEX);
@@ -303,6 +619,31 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Texture", "");
RNA_def_property_update(prop, NC_TEXTURE, "rna_Brush_update");
prop= RNA_def_property(srna, "texture_overlay_alpha", PROP_INT, PROP_PERCENTAGE);
RNA_def_property_int_sdna(prop, NULL, "texture_overlay_alpha");
RNA_def_property_range(prop, 1, 100);
RNA_def_property_ui_text(prop, "Texture Overlay Alpha", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "add_col", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "add_col");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Add Color", "Color of cursor when adding");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "sub_col", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "sub_col");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Subract Color", "Color of cursor when subtracting");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop= RNA_def_property(srna, "image_icon", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "image_icon");
RNA_def_property_struct_type(prop, "Image");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Image Icon", "");
RNA_def_property_update(prop, 0, "rna_Brush_update");
/* clone tool */
prop= RNA_def_property(srna, "clone_image", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "clone.image");
@@ -357,16 +698,19 @@ 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, "pen_flip", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_ui_text(prop, "Flip", "");
// used in uv painting
prop= RNA_def_property(srna, "time", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_ui_text(prop, "Time", "");
prop= RNA_def_property(srna, "flip", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_ui_text(prop, "Flip", "");
/* XXX: Tool (this will be for pressing a modifier key for a different brush,
e.g. switching to a Smooth brush in the middle of the stroke */
// XXX: i don't think blender currently supports the ability to properly do a remappable modifier in the middle of a stroke
}
void RNA_def_brush(BlenderRNA *brna)

View File

@@ -213,6 +213,12 @@ static int rna_Image_depth_get(PointerRNA *ptr)
return depth;
}
static int rna_Image_is_image_icon(Image *me, bContext *C)
{
const char prefix[] = ".imageicon.";
return strncmp(me->id.name+2, prefix, sizeof(prefix)-1) == 0;
}
#else
static void rna_def_imageuser(BlenderRNA *brna)
@@ -292,6 +298,9 @@ static void rna_def_image(BlenderRNA *brna)
{IMA_STD_FIELD, "ODD", 0, "Lower First", "Lower field first"},
{0, NULL, 0, NULL, NULL}};
FunctionRNA *func;
PropertyRNA *parm;
srna= RNA_def_struct(brna, "Image", "ID");
RNA_def_struct_ui_text(srna, "Image", "Image datablock referencing an external or packed image");
RNA_def_struct_ui_icon(srna, ICON_IMAGE_DATA);
@@ -333,6 +342,14 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Field Order", "Order of video fields. Select which lines are displayed first");
RNA_def_property_update(prop, NC_IMAGE|ND_DISPLAY, NULL);
/* functions */
func= RNA_def_function(srna, "is_image_icon", "rna_Image_is_image_icon");
RNA_def_function_ui_description(func, "Returns true if Image name is prefixed with .imageicon.");
parm= RNA_def_pointer(func, "context", "Context", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED);
parm= RNA_def_boolean(func, "ret", 0, "", "");
RNA_def_function_return(func, parm);
/* booleans */
prop= RNA_def_property(srna, "fields", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_FIELDS);

View File

@@ -193,7 +193,7 @@ static void rna_Paint_active_brush_name_get(PointerRNA *ptr, char *value)
Paint *p= ptr->data;
Brush *br = paint_brush(p);
BLI_strncpy(value, br->id.name+2, sizeof(br->id.name-2));
BLI_strncpy(value, br->id.name+2, sizeof(br->id.name)-2);
}
@@ -212,7 +212,7 @@ static void rna_Paint_active_brush_name_set(PointerRNA *ptr, const char *value)
for(i = 0; i < p->brush_count; ++i) {
br = p->brushes[i];
if (strcmp(br->id.name+2, value)==0) {
paint_brush_set(p, br);
return;
@@ -262,6 +262,10 @@ static void rna_def_paint(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flags", PAINT_SHOW_BRUSH);
RNA_def_property_ui_text(prop, "Show Brush", "");
prop= RNA_def_property(srna, "show_brush_on_surface", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", PAINT_SHOW_BRUSH_ON_SURFACE);
RNA_def_property_ui_text(prop, "Show Brush On Surface", "");
prop= RNA_def_property(srna, "fast_navigate", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", PAINT_FAST_NAVIGATE);
RNA_def_property_ui_text(prop, "Fast Navigate", "For multires, show low resolution while navigating the view");
@@ -274,7 +278,14 @@ static void rna_def_sculpt(BlenderRNA *brna)
srna= RNA_def_struct(brna, "Sculpt", "Paint");
RNA_def_struct_ui_text(srna, "Sculpt", "");
prop= RNA_def_property(srna, "radial_symm", PROP_INT, PROP_XYZ);
RNA_def_property_int_sdna(prop, NULL, "radial_symm");
RNA_def_property_int_default(prop, 1);
RNA_def_property_range(prop, 1, 64);
RNA_def_property_ui_range(prop, 0, 32, 1, 1);
RNA_def_property_ui_text(prop, "Radial Symmetry Count X Axis", "Number of times to copy strokes across the surface");
prop= RNA_def_property(srna, "symmetry_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_SYMM_X);
RNA_def_property_ui_text(prop, "Symmetry X", "Mirror brush across the X axis");
@@ -298,6 +309,14 @@ static void rna_def_sculpt(BlenderRNA *brna)
prop= RNA_def_property(srna, "lock_z", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_LOCK_Z);
RNA_def_property_ui_text(prop, "Lock Z", "Disallow changes to the Z axis of vertices");
prop= RNA_def_property(srna, "use_symmetry_feather", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_SYMMETRY_FEATHER);
RNA_def_property_ui_text(prop, "Symmetry Feathering", "Reduce the strength of the brush where it overlaps symmetrical daubs");
prop= RNA_def_property(srna, "use_openmp", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", SCULPT_USE_OPENMP);
RNA_def_property_ui_text(prop, "Use OpenMP", "Take advantage of multiple CPU cores to improve sculpting performance");
}
static void rna_def_vertex_paint(BlenderRNA *brna)

View File

@@ -274,6 +274,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_string(func, "new", "", 0, "", "Operator identifier to create a new ID block.");
RNA_def_string(func, "open", "", 0, "", "Operator identifier to open a file for creating a new ID block.");
RNA_def_string(func, "unlink", "", 0, "", "Operator identifier to unlink the ID block.");
RNA_def_string(func, "filter", "", 0, "", "Function identifier to filter the ID block.");
func= RNA_def_function(srna, "template_ID_preview", "uiTemplateIDPreview");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
@@ -281,6 +282,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_string(func, "new", "", 0, "", "Operator identifier to create a new ID block.");
RNA_def_string(func, "open", "", 0, "", "Operator identifier to open a file for creating a new ID block.");
RNA_def_string(func, "unlink", "", 0, "", "Operator identifier to unlink the ID block.");
RNA_def_string(func, "filter", "", 0, "", "Function identifier to filter the ID block.");
RNA_def_int(func, "rows", 0, 0, INT_MAX, "Number of thumbnail preview rows to display", "", 0, INT_MAX);
RNA_def_int(func, "cols", 0, 0, INT_MAX, "Number of thumbnail preview columns to display", "", 0, INT_MAX);

View File

@@ -32,6 +32,7 @@
#include "DNA_curve_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
#include "DNA_brush_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -867,7 +868,7 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Transform", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
rna_def_userdef_theme_spaces_vertex(srna);
rna_def_userdef_theme_spaces_edge(srna);
rna_def_userdef_theme_spaces_face(srna);
@@ -2194,7 +2195,43 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "gp_eraser");
RNA_def_property_range(prop, 0, 100);
RNA_def_property_ui_text(prop, "Grease Pencil Eraser Radius", "Radius of eraser 'brush'");
/* sculpt and paint */
prop= RNA_def_property(srna, "sculpt_paint_overlay_col", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "sculpt_paint_overlay_col");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Sculpt/Paint Overlay Color", "Color of texture overlay");
prop= RNA_def_property(srna, "sculpt_paint_use_unified_size", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "sculpt_paint_settings", SCULPT_PAINT_USE_UNIFIED_SIZE);
RNA_def_property_ui_text(prop, "Sculpt/Paint Use Unified Radius", "Instead of per brush radius, the radius is shared across brushes");
prop= RNA_def_property(srna, "sculpt_paint_use_unified_strength", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "sculpt_paint_settings", SCULPT_PAINT_USE_UNIFIED_ALPHA);
RNA_def_property_ui_text(prop, "Sculpt/Paint Use Unified Strength", "Instead of per brush strength, the strength is shared across brushes");
prop= RNA_def_property(srna, "sculpt_paint_unified_lock_brush_size", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "sculpt_paint_settings", SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE);
RNA_def_property_ui_text(prop, "Sculpt/Paint Use Unified Blender Units", "When locked all brushes stay same size relative to object; when unlocked all brush sizes are given in pixels");
prop= RNA_def_property(srna, "sculpt_paint_unified_size", PROP_INT, PROP_DISTANCE);
RNA_def_property_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS*10);
RNA_def_property_ui_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS, 1, 0);
RNA_def_property_ui_text(prop, "Sculpt/Paint Unified Size", "Unified radius of the brush in pixels");
prop= RNA_def_property(srna, "sculpt_paint_unified_unprojected_radius", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_range(prop, 0, FLT_MAX);
RNA_def_property_ui_range(prop, 0, 1, 0, 0);
RNA_def_property_ui_text(prop, "Sculpt/Paint Unified Surface Size", "Unified radius of brush in Blender units");
prop= RNA_def_property(srna, "sculpt_paint_unified_strength", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "sculpt_paint_unified_alpha");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, 10.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 0.001);
RNA_def_property_ui_text(prop, "Sculpt/Paint Unified Strength", "Unified power of effect of brushes when applied");
/* duplication linking */
prop= RNA_def_property(srna, "duplicate_mesh", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_MESH);

View File

@@ -24,7 +24,7 @@ if env['WITH_BF_COLLADA']:
if env['OURPLATFORM'] == 'linux2':
cflags='-pthread'
incs += ' ../../../extern/binreloc/include'
incs += ' ../../../extern/binreloc/include'
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
incs += ' ' + env['BF_PTHREADS_INC']
@@ -35,4 +35,4 @@ if env['WITH_GHOST_COCOA']:
if env['BF_BUILDINFO']:
defs.append('NAN_BUILDINFO')
env.BlenderLib ( 'bf_windowmanager', sources, Split(incs), defs, libtype=['core'], priority=[5] )
env.BlenderLib ( 'bf_windowmanager', sources, Split(incs), defines=defs, libtype=['core'], priority=[5] )

View File

@@ -389,6 +389,7 @@ static void wm_draw_triple_free(wmWindow *win)
wmDrawTriple *triple= win->drawdata;
glDeleteTextures(triple->nx*triple->ny, triple->bind);
MEM_freeN(triple);
win->drawdata= NULL;
@@ -560,7 +561,8 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
else {
win->drawdata= MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
if(!wm_triple_gen_textures(win, win->drawdata)) {
if(!wm_triple_gen_textures(win, win->drawdata))
{
wm_draw_triple_fail(C, win);
return;
}

View File

@@ -61,6 +61,7 @@
#include "BKE_scene.h"
#include "BKE_screen.h" /* BKE_ST_MAXNAME */
#include "BKE_utildefines.h"
#include "BKE_brush.h" // JW
#include "BIF_gl.h"
#include "BIF_glutil.h" /* for paint cursor */
@@ -69,6 +70,7 @@
#include "ED_screen.h"
#include "ED_util.h"
#include "ED_view3d.h" // JW
#include "RNA_access.h"
#include "RNA_define.h"
@@ -2595,19 +2597,28 @@ typedef struct wmRadialControl {
GLuint tex;
} wmRadialControl;
extern Paint *paint_get_active(Scene *sce);
extern struct Brush *paint_brush(struct Paint *paint);
static void wm_radial_control_paint(bContext *C, int x, int y, void *customdata)
{
wmRadialControl *rc = (wmRadialControl*)customdata;
ARegion *ar = CTX_wm_region(C);
float r1=0.0f, r2=0.0f, r3=0.0f, angle=0.0f;
/* Keep cursor in the original place */
x = rc->initial_mouse[0] - ar->winrct.xmin;
y = rc->initial_mouse[1] - ar->winrct.ymin;
Paint *paint = paint_get_active(CTX_data_scene(C));
Brush *brush = paint_brush(paint);
glPushMatrix();
glTranslatef((float)x, (float)y, 0.0f);
ViewContext vc;
int hit = 0;
int flip;
int sign;
float* col;
const float str = rc->mode == WM_RADIALCONTROL_STRENGTH ? (rc->value + 0.5) : (brush->texture_overlay_alpha / 100.0f);
if(rc->mode == WM_RADIALCONTROL_SIZE) {
r1= rc->value;
@@ -2615,29 +2626,37 @@ static void wm_radial_control_paint(bContext *C, int x, int y, void *customdata)
r3= r1;
} else if(rc->mode == WM_RADIALCONTROL_STRENGTH) {
r1= (1 - rc->value) * WM_RADIAL_CONTROL_DISPLAY_SIZE;
r2= WM_RADIAL_CONTROL_DISPLAY_SIZE;
r3= WM_RADIAL_CONTROL_DISPLAY_SIZE;
r2= r3= WM_RADIAL_CONTROL_DISPLAY_SIZE;
} else if(rc->mode == WM_RADIALCONTROL_ANGLE) {
r1= r2= WM_RADIAL_CONTROL_DISPLAY_SIZE;
r3= WM_RADIAL_CONTROL_DISPLAY_SIZE;
r1= r2= r3= WM_RADIAL_CONTROL_DISPLAY_SIZE;
angle = rc->value;
}
glColor4ub(255, 255, 255, 128);
glEnable( GL_LINE_SMOOTH );
/* Keep cursor in the original place */
x = rc->initial_mouse[0] - ar->winrct.xmin;
y = rc->initial_mouse[1] - ar->winrct.ymin;
view3d_set_viewcontext(C, &vc);
// XXX: no way currently to know state of pen flip or invert key modifier without starting a stroke
flip = 1;
sign = flip * ((brush->flag & BRUSH_DIR_IN)? -1 : 1);
if (sign < 0 && ELEM4(brush->sculpt_tool, SCULPT_TOOL_DRAW, SCULPT_TOOL_INFLATE, SCULPT_TOOL_CLAY, SCULPT_TOOL_PINCH))
col = brush->sub_col;
else
col = brush->add_col;
glTranslatef((float)x, (float)y, 0.0f);
glEnable(GL_BLEND);
if(rc->mode == WM_RADIALCONTROL_ANGLE)
fdrawline(0, 0, WM_RADIAL_CONTROL_DISPLAY_SIZE, 0);
if(rc->tex) {
const float str = rc->mode == WM_RADIALCONTROL_STRENGTH ? (rc->value + 0.5) : 1;
if(rc->mode == WM_RADIALCONTROL_ANGLE) {
glRotatef(angle, 0, 0, 1);
fdrawline(0, 0, WM_RADIAL_CONTROL_DISPLAY_SIZE, 0);
}
if(rc->mode == WM_RADIALCONTROL_ANGLE) {
glRotatef(angle, 0, 0, 1);
}
if (rc->tex) {
glBindTexture(GL_TEXTURE_2D, rc->tex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -2645,7 +2664,7 @@ static void wm_radial_control_paint(bContext *C, int x, int y, void *customdata)
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glColor4f(0,0,0, str);
glColor4f(U.sculpt_paint_overlay_col[0],U.sculpt_paint_overlay_col[1],U.sculpt_paint_overlay_col[2], str);
glTexCoord2f(0,0);
glVertex2f(-r3, -r3);
glTexCoord2f(1,0);
@@ -2658,11 +2677,20 @@ static void wm_radial_control_paint(bContext *C, int x, int y, void *customdata)
glDisable(GL_TEXTURE_2D);
}
glColor4ub(255, 255, 255, 128);
if(rc->mode == WM_RADIALCONTROL_ANGLE) {
glColor4f(col[0], col[1], col[2], 0.5f);
glEnable(GL_LINE_SMOOTH);
glRotatef(-angle, 0, 0, 1);
fdrawline(0, 0, WM_RADIAL_CONTROL_DISPLAY_SIZE, 0);
glRotatef(angle, 0, 0, 1);
fdrawline(0, 0, WM_RADIAL_CONTROL_DISPLAY_SIZE, 0);
glDisable(GL_LINE_SMOOTH);
}
glColor4f(col[0], col[1], col[2], 0.5f);
glutil_draw_lined_arc(0.0, M_PI*2.0, r1, 40);
glutil_draw_lined_arc(0.0, M_PI*2.0, r2, 40);
glDisable(GL_BLEND);
glDisable( GL_LINE_SMOOTH );
glPopMatrix();
}
@@ -2674,6 +2702,7 @@ int WM_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
float dist;
double new_value = RNA_float_get(op->ptr, "new_value");
int ret = OPERATOR_RUNNING_MODAL;
float initial_value = RNA_float_get(op->ptr, "initial_value");
mode = RNA_int_get(op->ptr, "mode");
RNA_int_get_array(op->ptr, "initial_mouse", initial_mouse);
@@ -2682,6 +2711,16 @@ int WM_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
case MOUSEMOVE:
delta[0]= initial_mouse[0] - event->x;
delta[1]= initial_mouse[1] - event->y;
//if (mode == WM_RADIALCONTROL_SIZE)
// delta[0]+= initial_value;
//else if(mode == WM_RADIALCONTROL_STRENGTH)
// delta[0]+= WM_RADIAL_CONTROL_DISPLAY_SIZE * (1 - initial_value);
//else if(mode == WM_RADIALCONTROL_ANGLE) {
// delta[0]+= WM_RADIAL_CONTROL_DISPLAY_SIZE * cos(initial_value*M_PI/180.0f);
// delta[1]+= WM_RADIAL_CONTROL_DISPLAY_SIZE * sin(initial_value*M_PI/180.0f);
//}
dist= sqrt(delta[0]*delta[0]+delta[1]*delta[1]);
if(mode == WM_RADIALCONTROL_SIZE)
@@ -2728,6 +2767,11 @@ int WM_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
ED_region_tag_redraw(CTX_wm_region(C));
//if (ret != OPERATOR_RUNNING_MODAL) {
// wmWindow *win = CTX_wm_window(C);
// WM_cursor_restore(win);
//}
return ret;
}
@@ -2735,10 +2779,15 @@ int WM_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event)
int WM_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
wmRadialControl *rc = MEM_callocN(sizeof(wmRadialControl), "radial control");
wmWindow *win = CTX_wm_window(C);
int mode = RNA_int_get(op->ptr, "mode");
float initial_value = RNA_float_get(op->ptr, "initial_value");
//float initial_size = RNA_float_get(op->ptr, "initial_size");
int mouse[2] = {event->x, event->y};
//if (initial_size == 0)
// initial_size = WM_RADIAL_CONTROL_DISPLAY_SIZE;
if(mode == WM_RADIALCONTROL_SIZE) {
rc->max_value = 200;
mouse[0]-= initial_value;
@@ -2775,6 +2824,8 @@ int WM_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
rc->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), op->type->poll,
wm_radial_control_paint, op->customdata);
//WM_cursor_modal(win, CURSOR_NONE);
/* add modal handler */
WM_event_add_modal_handler(C, op);

View File

@@ -36,12 +36,14 @@
struct ARegion;
struct ARegionType;
struct Base;
struct Brush;
struct bNodeTree;
struct CSG_FaceIteratorDescriptor;
struct CSG_VertexIteratorDescriptor;
struct ColorBand;
struct CurveMapping;
struct EditBone;
struct EditFace;
struct EditMesh;
struct ID;
struct FCurve;
@@ -54,16 +56,20 @@ struct LOD_Decimation_Info;
struct MTex;
struct Main;
struct Material;
struct MCol;
struct MenuType;
struct Mesh;
struct ModifierData;
struct MultiresModifierData;
struct NodeBlurData;
struct Object;
struct PBVHNode;
struct Render;
struct RenderEngine;
struct RenderLayer;
struct RenderResult;
struct ScrArea;
struct SculptSession;
struct ShadeInput;
struct ShadeResult;
struct SpaceImage;
@@ -375,6 +381,24 @@ void smoke_get_index(void) {return;}
void smoke_step(void) {return;}
*/
/* sculpt */
/*
void ED_sculpt_force_update(struct bContext *C) {}
struct SculptUndoNode *sculpt_undo_push_node(struct SculptSession *ss, struct PBVHNode *node) {return (struct SculptUndoNode *)NULL;}
void sculpt_undo_push_end(void) {}
void sculpt_undo_push_begin(char *name) {}
struct SculptUndoNode *sculpt_undo_get_node(struct PBVHNode *node) {return (struct SculptUndoNode *) NULL;}
struct MultiresModifierData *sculpt_multires_active(struct Scene *scene, struct Object *ob) {return (struct MultiresModifierData *) NULL;}
int sculpt_modifiers_active(struct Scene *scene, struct Object *ob) {return 0;}
*/
int sculpt_get_brush_size(struct Brush *brush) {return 0;}
void sculpt_set_brush_size(struct Brush *brush, int size) {}
int sculpt_get_lock_brush_size(struct Brush *brush){ return 0;}
float sculpt_get_brush_unprojected_radius(struct Brush *brush){return 0.0f;}
void sculpt_set_brush_unprojected_radius(struct Brush *brush, float unprojected_radius){}
float sculpt_get_brush_alpha(struct Brush *brush){return 0.0f;}
void sculpt_set_brush_alpha(struct Brush *brush, float alpha){}
char blender_path[] = "";
/* CSG */