svn merge ^/trunk/blender -r43461:43472

This commit is contained in:
2012-01-17 21:08:25 +00:00
57 changed files with 4011 additions and 226 deletions

View File

@@ -20,6 +20,7 @@
#include <list>
#include <iterator>
#include <limits>
#include <cstddef>
#include <carve/polyline_decl.hpp>

View File

@@ -149,6 +149,7 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
sub.prop(cscene, "debug_use_spatial_splits")
sub.prop(cscene, "use_cache")
class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
bl_label = "Layers"
bl_options = {'DEFAULT_CLOSED'}
@@ -708,7 +709,7 @@ def draw_device(self, context):
scene = context.scene
layout = self.layout
if scene.render.engine == "CYCLES":
if scene.render.engine == 'CYCLES':
cscene = scene.cycles
layout.prop(cscene, "feature_set")
@@ -719,6 +720,7 @@ def draw_device(self, context):
elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL':
layout.prop(cscene, "device")
def draw_pause(self, context):
layout = self.layout
scene = context.scene
@@ -726,7 +728,7 @@ def draw_pause(self, context):
if scene.render.engine == "CYCLES":
view = context.space_data
if view.viewport_shade == "RENDERED":
if view.viewport_shade == 'RENDERED':
cscene = scene.cycles
layout.prop(cscene, "preview_pause", icon="PAUSE", text="")

View File

@@ -70,6 +70,7 @@ KM_HIERARCHY = [
('Image', 'IMAGE_EDITOR', 'WINDOW', [
('UV Editor', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image
('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d
('UV Sculpt', 'EMPTY', 'WINDOW', []),
('Image Generic', 'IMAGE_EDITOR', 'WINDOW', [])
]),

View File

@@ -308,13 +308,13 @@ def xml2rna(root_xml,
rna2xml_node(root_xml, root_rna)
# -----------------------------------------------------------------------------
# Utility function used by presets.
# The idea is you can run a preset like a script with a few args.
#
# This roughly matches the operator 'bpy.ops.script.python_file_run'
def _get_context_val(context, path):
path_full = "context." + path
try:
@@ -328,6 +328,7 @@ def _get_context_val(context, path):
return value
def xml_file_run(context, filepath, rna_map):
import xml.dom.minidom

View File

@@ -76,6 +76,7 @@ def CLIP_camera_for_clip(context, clip):
return camera
def CLIP_track_view_selected(sc, track):
if track.select_anchor:
return True
@@ -118,7 +119,7 @@ class CLIP_OT_track_to_empty(Operator):
constraint.track = track.name
constraint.use_3d_position = False
constraint.object = tracking_object.name
constraint.camera = CLIP_camera_for_clip(context, clip);
constraint.camera = CLIP_camera_for_clip(context, clip)
def execute(self, context):
sc = context.space_data

View File

@@ -166,9 +166,10 @@ class BRUSH_OT_active_index_set(Operator):
if attr is None:
return {'CANCELLED'}
toolsettings = context.tool_settings
for i, brush in enumerate((cur for cur in bpy.data.brushes if getattr(cur, attr))):
if i == self.index:
getattr(context.tool_settings, self.mode).brush = brush
getattr(toolsettings, self.mode).brush = brush
return {'FINISHED'}
return {'CANCELLED'}
@@ -1768,4 +1769,3 @@ class WM_OT_addon_expand(Operator):
info = addon_utils.module_bl_info(mod)
info["show_expanded"] = not info["show_expanded"]
return {'FINISHED'}

View File

@@ -162,22 +162,25 @@ class CLIP_PT_tools_tracking(Panel):
def draw(self, context):
layout = self.layout
# clip = context.space_data.clip # UNUSED
row = layout.row(align=True)
row.operator("clip.track_markers", text="", icon='FRAME_PREV').backwards = True
props = row.operator("clip.track_markers", text="", icon='FRAME_PREV')
props.backwards = True
props = row.operator("clip.track_markers", text="",
icon='PLAY_REVERSE')
props.backwards = True
props.sequence = True
row.operator("clip.track_markers", text="", icon='PLAY').sequence = True
props = row.operator("clip.track_markers", text="", icon='PLAY')
props.sequence = True
row.operator("clip.track_markers", text="", icon='FRAME_NEXT')
col = layout.column(align=True)
col.operator("clip.clear_track_path", text="Clear After").action = 'REMAINED'
props = col.operator("clip.clear_track_path", text="Clear After")
props.action = 'REMAINED'
col.operator("clip.clear_track_path", text="Clear Before").action = 'UPTO'
props = col.operator("clip.clear_track_path", text="Clear Before")
props.action = 'UPTO'
col.operator("clip.clear_track_path", text="Clear").action = 'ALL'
layout.operator("clip.join_tracks", text="Join")
@@ -478,7 +481,8 @@ class CLIP_PT_tracking_camera(Panel):
label = bpy.types.CLIP_MT_camera_presets.bl_label
row.menu('CLIP_MT_camera_presets', text=label)
row.operator("clip.camera_preset_add", text="", icon='ZOOMIN')
row.operator("clip.camera_preset_add", text="", icon='ZOOMOUT').remove_active = True
props = row.operator("clip.camera_preset_add", text="", icon='ZOOMOUT')
props.remove_active = True
row = layout.row(align=True)
sub = row.split(percentage=0.65)
@@ -942,7 +946,8 @@ class CLIP_MT_select(Menu):
layout.separator()
layout.operator("clip.select_all", text="Select/Deselect all").action = 'TOGGLE'
props = layout.operator("clip.select_all", text="Select/Deselect all")
props.action = 'TOGGLE'
layout.operator("clip.select_all", text="Inverse").action = 'INVERT'
layout.menu("CLIP_MT_select_grouped")
@@ -967,8 +972,12 @@ class CLIP_MT_tracking_specials(Menu):
def draw(self, context):
layout = self.layout
layout.operator("clip.disable_markers", text="Enable Markers").action = 'ENABLE'
layout.operator("clip.disable_markers", text="Disable markers").action = 'DISABLE'
props = layout.operator("clip.disable_markers",
text="Enable Markers")
props.action = 'ENABLE'
props = layout.operator("clip.disable_markers", text="Disable markers")
props.action = 'DISABLE'
layout.separator()
layout.operator("clip.set_origin")

View File

@@ -52,6 +52,7 @@ class IMAGE_MT_view(Menu):
layout.prop(sima, "use_realtime_update")
if show_uvedit:
layout.prop(toolsettings, "show_uv_local_view")
layout.prop(uv, "show_other_objects")
layout.separator()
@@ -146,10 +147,12 @@ class IMAGE_MT_image(Menu):
if ima.source in {'FILE', 'GENERATED'} and ima.type != 'OPEN_EXR_MULTILAYER':
layout.operator("image.pack", text="Pack As PNG").as_png = True
if not context.tool_settings.use_uv_sculpt:
layout.separator()
layout.prop(sima, "use_image_paint")
layout.separator()
class IMAGE_MT_image_invert(Menu):
bl_label = "Invert"
@@ -256,6 +259,10 @@ class IMAGE_MT_uvs(Menu):
layout.separator()
layout.prop(toolsettings, "use_uv_sculpt")
layout.separator()
layout.prop(uv, "use_live_unwrap")
layout.operator("uv.unwrap")
layout.operator("uv.pin", text="Unpin").clear = True
@@ -267,6 +274,8 @@ class IMAGE_MT_uvs(Menu):
layout.operator("uv.average_islands_scale")
layout.operator("uv.minimize_stretch")
layout.operator("uv.stitch")
layout.operator("uv.mark_seam")
layout.operator("uv.seams_from_islands")
layout.operator("mesh.faces_mirror_uv")
layout.separator()
@@ -697,8 +706,8 @@ class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
settings = context.tool_settings.image_paint
brush = settings.brush
toolsettings = context.tool_settings.image_paint
brush = toolsettings.brush
layout.prop(brush, "image_tool", text="")
@@ -753,5 +762,80 @@ class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel):
row.operator("brush.curve_preset", icon='LINCURVE', text="").shape = 'LINE'
row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
class IMAGE_UV_sculpt_curve(bpy.types.Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'UI'
bl_label = "UV Sculpt Curve"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
sima = context.space_data
toolsettings = context.tool_settings.image_paint
return sima.show_uvedit and context.tool_settings.use_uv_sculpt and not (sima.show_paint and toolsettings.brush)
def draw(self, context):
layout = self.layout
toolsettings = context.tool_settings
uvsculpt = toolsettings.uv_sculpt
brush = uvsculpt.brush
layout.template_curve_mapping(brush, "curve")
row = layout.row(align=True)
row.operator("brush.curve_preset", icon="SMOOTHCURVE", text="").shape = 'SMOOTH'
row.operator("brush.curve_preset", icon="SPHERECURVE", text="").shape = 'ROUND'
row.operator("brush.curve_preset", icon="ROOTCURVE", text="").shape = 'ROOT'
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'
class IMAGE_UV_sculpt(bpy.types.Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'UI'
bl_label = "UV Sculpt"
@classmethod
def poll(cls, context):
sima = context.space_data
toolsettings = context.tool_settings.image_paint
return sima.show_uvedit and context.tool_settings.use_uv_sculpt and not (sima.show_paint and toolsettings.brush)
def draw(self, context):
layout = self.layout
toolsettings = context.tool_settings
uvsculpt = toolsettings.uv_sculpt
brush = uvsculpt.brush
if brush:
col = layout.column()
row = col.row(align=True)
row.prop(brush, "size", slider=True)
row.prop(brush, "use_pressure_size", toggle=True, text="")
row = col.row(align=True)
row.prop(brush, "strength", slider=True)
row.prop(brush, "use_pressure_strength", toggle=True, text="")
split = layout.split()
col = split.column()
col.prop(toolsettings, "uv_sculpt_lock_borders")
col.prop(toolsettings, "uv_sculpt_all_islands")
split = layout.split()
col = split.column()
col.prop(toolsettings, "uv_sculpt_tool")
if toolsettings.uv_sculpt_tool == 'RELAX':
col.prop(toolsettings, "uv_relax_method")
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)

View File

@@ -28,7 +28,7 @@ class TIME_HT_header(Header):
layout = self.layout
scene = context.scene
tools = context.tool_settings
toolsettings = context.tool_settings
screen = context.screen
row = layout.row(align=True)
@@ -80,11 +80,11 @@ class TIME_HT_header(Header):
layout.separator()
row = layout.row(align=True)
row.prop(tools, "use_keyframe_insert_auto", text="", toggle=True)
row.prop(tools, "use_keyframe_insert_keyingset", text="", toggle=True)
if screen.is_animation_playing and tools.use_keyframe_insert_auto:
row.prop(toolsettings, "use_keyframe_insert_auto", text="", toggle=True)
row.prop(toolsettings, "use_keyframe_insert_keyingset", text="", toggle=True)
if screen.is_animation_playing and toolsettings.use_keyframe_insert_auto:
subsub = row.row()
subsub.prop(tools, "use_record_with_nla", toggle=True)
subsub.prop(toolsettings, "use_record_with_nla", toggle=True)
row = layout.row(align=True)
row.prop_search(scene.keying_sets_all, "active", scene, "keying_sets_all", text="")
@@ -193,10 +193,10 @@ class TIME_MT_autokey(Menu):
def draw(self, context):
layout = self.layout
tools = context.tool_settings
toolsettings = context.tool_settings
layout.prop_enum(tools, "auto_keying_mode", 'ADD_REPLACE_KEYS')
layout.prop_enum(tools, "auto_keying_mode", 'REPLACE_KEYS')
layout.prop_enum(toolsettings, "auto_keying_mode", 'ADD_REPLACE_KEYS')
layout.prop_enum(toolsettings, "auto_keying_mode", 'REPLACE_KEYS')
def marker_menu_generic(layout):

View File

@@ -425,6 +425,7 @@ class USERPREF_PT_system(Panel):
col.label(text="OpenGL:")
col.prop(system, "gl_clip_alpha", slider=True)
col.prop(system, "use_mipmaps")
col.prop(system, "use_16bit_textures")
col.label(text="Anisotropic Filtering")
col.prop(system, "anisotropic_filter", text="")
col.prop(system, "use_vertex_buffer_objects")

View File

@@ -760,7 +760,7 @@ class VIEW3D_MT_object_clear(Menu):
layout.operator("object.location_clear", text="Location")
layout.operator("object.rotation_clear", text="Rotation")
layout.operator("object.scale_clear", text="Scale")
layout ("object.origin_clear", text="Origin")
layout.operator("object.origin_clear", text="Origin")
class VIEW3D_MT_object_specials(Menu):
@@ -1109,9 +1109,9 @@ class VIEW3D_MT_sculpt(Menu):
def draw(self, context):
layout = self.layout
tool_settings = context.tool_settings
sculpt = tool_settings.sculpt
brush = tool_settings.sculpt.brush
toolsettings = context.tool_settings
sculpt = toolsettings.sculpt
brush = toolsettings.sculpt.brush
layout.operator("ed.undo")
layout.operator("ed.redo")
@@ -1147,8 +1147,8 @@ class VIEW3D_MT_sculpt(Menu):
layout.prop(sculpt, "show_brush")
# TODO, make available from paint menu!
layout.prop(tool_settings, "sculpt_paint_use_unified_size", text="Unify Size")
layout.prop(tool_settings, "sculpt_paint_use_unified_strength", text="Unify Strength")
layout.prop(toolsettings, "sculpt_paint_use_unified_size", text="Unify Size")
layout.prop(toolsettings, "sculpt_paint_use_unified_strength", text="Unify Strength")
# ********** Particle menu **********
@@ -1452,7 +1452,7 @@ class VIEW3D_MT_edit_mesh(Menu):
def draw(self, context):
layout = self.layout
settings = context.tool_settings
toolsettings = context.tool_settings
layout.operator("ed.undo")
layout.operator("ed.redo")
@@ -1484,9 +1484,9 @@ class VIEW3D_MT_edit_mesh(Menu):
layout.separator()
layout.prop(settings, "use_mesh_automerge")
layout.prop_menu_enum(settings, "proportional_edit")
layout.prop_menu_enum(settings, "proportional_edit_falloff")
layout.prop(toolsettings, "use_mesh_automerge")
layout.prop_menu_enum(toolsettings, "proportional_edit")
layout.prop_menu_enum(toolsettings, "proportional_edit_falloff")
layout.separator()
@@ -1719,7 +1719,7 @@ class VIEW3D_MT_edit_mesh_showhide(ShowHideMenu, Menu):
def draw_curve(self, context):
layout = self.layout
settings = context.tool_settings
toolsettings = context.tool_settings
layout.menu("VIEW3D_MT_transform")
layout.menu("VIEW3D_MT_mirror")
@@ -1741,8 +1741,8 @@ def draw_curve(self, context):
layout.separator()
layout.prop_menu_enum(settings, "proportional_edit")
layout.prop_menu_enum(settings, "proportional_edit_falloff")
layout.prop_menu_enum(toolsettings, "proportional_edit")
layout.prop_menu_enum(toolsettings, "proportional_edit_falloff")
layout.separator()
@@ -1871,7 +1871,7 @@ class VIEW3D_MT_edit_meta(Menu):
def draw(self, context):
layout = self.layout
settings = context.tool_settings
toolsettings = context.tool_settings
layout.operator("ed.undo")
layout.operator("ed.redo")
@@ -1890,8 +1890,8 @@ class VIEW3D_MT_edit_meta(Menu):
layout.separator()
layout.prop_menu_enum(settings, "proportional_edit")
layout.prop_menu_enum(settings, "proportional_edit_falloff")
layout.prop_menu_enum(toolsettings, "proportional_edit")
layout.prop_menu_enum(toolsettings, "proportional_edit_falloff")
layout.separator()
@@ -1915,7 +1915,7 @@ class VIEW3D_MT_edit_lattice(Menu):
def draw(self, context):
layout = self.layout
settings = context.tool_settings
toolsettings = context.tool_settings
layout.menu("VIEW3D_MT_transform")
layout.menu("VIEW3D_MT_mirror")
@@ -1927,8 +1927,8 @@ class VIEW3D_MT_edit_lattice(Menu):
layout.separator()
layout.prop_menu_enum(settings, "proportional_edit")
layout.prop_menu_enum(settings, "proportional_edit_falloff")
layout.prop_menu_enum(toolsettings, "proportional_edit")
layout.prop_menu_enum(toolsettings, "proportional_edit_falloff")
class VIEW3D_MT_edit_armature(Menu):

View File

@@ -453,18 +453,18 @@ class PaintPanel():
@staticmethod
def paint_settings(context):
ts = context.tool_settings
toolsettings = context.tool_settings
if context.sculpt_object:
return ts.sculpt
return toolsettings.sculpt
elif context.vertex_paint_object:
return ts.vertex_paint
return toolsettings.vertex_paint
elif context.weight_paint_object:
return ts.weight_paint
return toolsettings.weight_paint
elif context.image_paint_object:
return ts.image_paint
return toolsettings.image_paint
elif context.particle_edit_object:
return ts.particle_edit
return toolsettings.particle_edit
return None
@@ -487,6 +487,7 @@ class PaintPanel():
ptr = ups if ups.use_unified_strength else brush
parent.prop(ptr, prop_name, icon=icon, text=text, slider=slider)
class VIEW3D_PT_tools_brush(PaintPanel, Panel):
bl_label = "Brush"
@@ -497,6 +498,7 @@ class VIEW3D_PT_tools_brush(PaintPanel, Panel):
def draw(self, context):
layout = self.layout
toolsettings = context.tool_settings
settings = self.paint_settings(context)
brush = settings.brush
@@ -541,7 +543,7 @@ class VIEW3D_PT_tools_brush(PaintPanel, Panel):
row = col.row(align=True)
ups = context.tool_settings.unified_paint_settings
ups = toolsettings.unified_paint_settings
if ((ups.use_unified_size and ups.use_locked_size) or
((not ups.use_unified_size) and brush.use_locked_size)):
self.prop_unified_size(row, context, brush, "use_locked_size", icon='LOCKED')
@@ -675,9 +677,9 @@ class VIEW3D_PT_tools_brush(PaintPanel, Panel):
# Weight Paint Mode #
elif context.weight_paint_object and brush:
layout.prop(context.tool_settings, "vertex_group_weight", text="Weight", slider=True)
layout.prop(context.tool_settings, "use_auto_normalize", text="Auto Normalize")
layout.prop(context.tool_settings, "use_multipaint", text="Multi-Paint")
layout.prop(toolsettings, "vertex_group_weight", text="Weight", slider=True)
layout.prop(toolsettings, "use_auto_normalize", text="Auto Normalize")
layout.prop(toolsettings, "use_multipaint", text="Multi-Paint")
col = layout.column()
@@ -956,8 +958,8 @@ class VIEW3D_PT_sculpt_options(PaintPanel, Panel):
def draw(self, context):
layout = self.layout
tool_settings = context.tool_settings
sculpt = tool_settings.sculpt
toolsettings = context.tool_settings
sculpt = toolsettings.sculpt
layout.label(text="Lock:")
row = layout.row(align=True)
@@ -1003,11 +1005,11 @@ class VIEW3D_PT_tools_brush_appearance(PaintPanel, Panel):
@classmethod
def poll(cls, context):
ts = context.tool_settings
return ((context.sculpt_object and ts.sculpt) or
(context.vertex_paint_object and ts.vertex_paint) or
(context.weight_paint_object and ts.weight_paint) or
(context.image_paint_object and ts.image_paint))
toolsettings = context.tool_settings
return ((context.sculpt_object and toolsettings.sculpt) or
(context.vertex_paint_object and toolsettings.vertex_paint) or
(context.weight_paint_object and toolsettings.weight_paint) or
(context.image_paint_object and toolsettings.image_paint))
def draw(self, context):
layout = self.layout
@@ -1102,8 +1104,8 @@ class VIEW3D_PT_tools_vertexpaint(PaintPanel, Panel):
def draw(self, context):
layout = self.layout
tool_settings = context.tool_settings
vpaint = tool_settings.vertex_paint
toolsettings = context.tool_settings
vpaint = toolsettings.vertex_paint
col = layout.column()
#col.prop(vpaint, "mode", text="")
@@ -1141,8 +1143,9 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
ob = context.active_object
mesh = ob.data
ipaint = context.tool_settings.image_paint
settings = context.tool_settings.image_paint
toolsettings = context.tool_settings
ipaint = toolsettings.image_paint
settings = toolsettings.image_paint
use_projection = ipaint.use_projection
col = layout.column()
@@ -1199,8 +1202,6 @@ class VIEW3D_PT_imagepaint_options(PaintPanel):
def draw(self, context):
layout = self.layout
tool_settings = context.tool_settings
col = layout.column()
self.unified_paint_settings(col, context)

View File

@@ -53,7 +53,10 @@ struct CustomData;
struct DerivedMesh;
struct Scene;
struct MLoopUV;
struct UvVertMap;
struct UvMapVert;
struct UvElementMap;
struct UvElement;
#ifdef __cplusplus
extern "C" {
#endif
@@ -180,6 +183,38 @@ typedef struct UvMapVert {
unsigned char tfindex, separate, flag;
} UvMapVert;
typedef struct UvElementMap {
/* address UvElements by their vertex */
struct UvElement **vert;
/* UvElement Store */
struct UvElement *buf;
/* Total number of UVs in the layer. Useful to know */
int totalUVs;
/* Number of Islands in the mesh */
int totalIslands;
/* Stores the starting index in buf where each island begins */
int *islandIndices;
} UvElementMap;
typedef struct UvElement {
/* Next UvElement corresponding to same vertex */
struct UvElement *next;
/* Face the element belongs to */
struct BMFace *face;
/* Index in the editFace of the uv */
unsigned char tfindex;
/* Whether this element is the first of coincident elements */
unsigned char separate;
/* general use flag */
unsigned char flag;
/* If generating element map with island sorting, this stores the island index */
unsigned short island;
} UvElement;
/* invalid island index is max short. If any one has the patience
* to make that many islands, he can bite me :p */
#define INVALID_ISLAND 0xFFFF
UvVertMap *make_uv_vert_map(struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv, unsigned int totpoly, unsigned int totvert, int selected, float *limit);
UvMapVert *get_uv_map_vert(UvVertMap *vmap, unsigned int v);
void free_uv_vert_map(UvVertMap *vmap);

View File

@@ -66,6 +66,11 @@ Paint *paint_get_active(Scene *sce)
return &ts->wpaint->paint;
case OB_MODE_TEXTURE_PAINT:
return &ts->imapaint.paint;
case OB_MODE_EDIT:
if(ts->use_uv_sculpt)
return &ts->uvsculpt->paint;
else
return &ts->imapaint.paint;
}
}

View File

@@ -297,6 +297,10 @@ void free_scene(Scene *sce)
free_paint(&sce->toolsettings->sculpt->paint);
MEM_freeN(sce->toolsettings->sculpt);
}
if(sce->toolsettings->uvsculpt) {
free_paint(&sce->toolsettings->uvsculpt->paint);
MEM_freeN(sce->toolsettings->uvsculpt);
}
free_paint(&sce->toolsettings->imapaint.paint);
MEM_freeN(sce->toolsettings);

View File

@@ -116,9 +116,10 @@ MINLINE void star_m3_v3(float rmat[3][3],float a[3]);
/*********************************** Length **********************************/
MINLINE float len_squared_v2(const float v[2]);
MINLINE float len_v2(const float a[2]);
MINLINE float len_v2v2(const float a[2], const float b[2]);
MINLINE float len_squared_v2v2(const float a[3], const float b[3]);
MINLINE float len_squared_v2v2(const float a[2], const float b[2]);
MINLINE float len_v3(const float a[3]);
MINLINE float len_v3v3(const float a[3], const float b[3]);
MINLINE float len_squared_v3v3(const float a[3], const float b[3]);

View File

@@ -429,6 +429,11 @@ MINLINE void star_m3_v3(float rmat[][3], float a[3])
/*********************************** Length **********************************/
MINLINE float len_squared_v2(const float v[2])
{
return v[0]*v[0] + v[1]*v[1];
}
MINLINE float len_v2(const float v[2])
{
return (float)sqrtf(v[0]*v[0] + v[1]*v[1]);
@@ -448,7 +453,7 @@ MINLINE float len_v3(const float a[3])
return sqrtf(dot_v3v3(a, a));
}
MINLINE float len_squared_v2v2(const float a[3], const float b[3])
MINLINE float len_squared_v2v2(const float a[2], const float b[2])
{
float d[2];

View File

@@ -4794,7 +4794,7 @@ static void lib_link_scene(FileData *fd, Main *main)
link_paint(fd, sce, &sce->toolsettings->vpaint->paint);
link_paint(fd, sce, &sce->toolsettings->wpaint->paint);
link_paint(fd, sce, &sce->toolsettings->imapaint.paint);
link_paint(fd, sce, &sce->toolsettings->uvsculpt->paint);
sce->toolsettings->skgen_template = newlibadr(fd, sce->id.lib, sce->toolsettings->skgen_template);
for(base= sce->base.first; base; base= next) {
@@ -4924,6 +4924,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
direct_link_paint(fd, (Paint**)&sce->toolsettings->sculpt);
direct_link_paint(fd, (Paint**)&sce->toolsettings->vpaint);
direct_link_paint(fd, (Paint**)&sce->toolsettings->wpaint);
direct_link_paint(fd, (Paint**)&sce->toolsettings->uvsculpt);
sce->toolsettings->imapaint.paintcursor= NULL;
sce->toolsettings->particle.paintcursor= NULL;

View File

@@ -2077,6 +2077,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
if(tos->sculpt) {
writestruct(wd, DATA, "Sculpt", 1, tos->sculpt);
}
if(tos->uvsculpt) {
writestruct(wd, DATA, "UvSculpt", 1, tos->uvsculpt);
}
// write_paint(wd, &tos->imapaint.paint);

View File

@@ -53,6 +53,7 @@ void ED_space_image_zoom(struct SpaceImage *sima, struct ARegion *ar, float *zoo
void ED_space_image_uv_aspect(struct SpaceImage *sima, float *aspx, float *aspy);
void ED_space_image_paint_update(struct wmWindowManager *wm, struct ToolSettings *settings);
void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct ToolSettings *settings);
void ED_image_size(struct Image *ima, int *width, int *height);
void ED_image_aspect(struct Image *ima, float *aspx, float *aspy);

View File

@@ -182,6 +182,12 @@ int EDBM_init_backbuf_circle(struct ViewContext *vc, short xs, short ys, short
void EDBM_deselect_by_material(struct BMEditMesh *em, const short index, const short select);
struct UvElementMap *EDBM_make_uv_element_map(struct BMEditMesh *em, int selected, int doIslands);
void EDBM_free_uv_element_map(struct UvElementMap *vmap);
void EDBM_add_data_layer(struct BMEditMesh *em, struct CustomData *data, int type, const char *name);
void EDBM_free_data_layer(struct BMEditMesh *em, struct CustomData *data, int type);
void EDBM_select_swap(struct BMEditMesh *em); /* exported for UV */
int EDBM_texFaceCheck(struct BMEditMesh *em);

View File

@@ -84,7 +84,7 @@ void ED_uvedit_live_unwrap_end(short cancel);
void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel);
/* uvedit_draw.c */
void draw_uvedit_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct Object *obedit);
void draw_uvedit_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct Object *obedit, struct Object *obact);
/* uvedit_buttons.c */
void ED_uvedit_buttons_register(struct ARegionType *art);

View File

@@ -283,10 +283,10 @@ void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct AR
int winx, int winy, float viewmat[][4], float winmat[][4]);
struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag, char err_out[256]);
struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype, char err_out[256]);
struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype, char err_out[256]);
Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, short do_clip);
int ED_view3d_lock(struct RegionView3D *rv3d);

View File

@@ -255,7 +255,15 @@ enum {
TH_PATH_BEFORE,
TH_PATH_AFTER,
TH_CAMERA_PATH,
TH_LOCK_MARKER
TH_LOCK_MARKER,
TH_STITCH_PREVIEW_FACE,
TH_STITCH_PREVIEW_EDGE,
TH_STITCH_PREVIEW_VERT,
TH_STITCH_PREVIEW_STITCHABLE,
TH_STITCH_PREVIEW_UNSTITCHABLE,
TH_STITCH_PREVIEW_ACTIVE
};
/* XXX WARNING: previous is saved in file, so do not change order! */

View File

@@ -410,6 +410,28 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp= ts->preview_back;
break;
case TH_STITCH_PREVIEW_FACE:
cp = ts->preview_stitch_face;
break;
case TH_STITCH_PREVIEW_EDGE:
cp = ts->preview_stitch_edge;
break;
case TH_STITCH_PREVIEW_VERT:
cp = ts->preview_stitch_vert;
break;
case TH_STITCH_PREVIEW_STITCHABLE:
cp = ts->preview_stitch_stitchable;
break;
case TH_STITCH_PREVIEW_UNSTITCHABLE:
cp = ts->preview_stitch_unstitchable;
break;
case TH_STITCH_PREVIEW_ACTIVE:
cp = ts->preview_stitch_active;
break;
case TH_MARKER_OUTLINE:
cp= ts->marker_outline; break;
case TH_MARKER:
@@ -746,6 +768,11 @@ void ui_theme_init_default(void)
SETCOL(btheme->tima.face_select, 255, 133, 0, 60);
SETCOL(btheme->tima.editmesh_active, 255, 255, 255, 128);
SETCOLF(btheme->tima.preview_back, 0.45, 0.45, 0.45, 1.0);
SETCOLF(btheme->tima.preview_stitch_face, 0.5, 0.5, 0.0, 0.2);
SETCOLF(btheme->tima.preview_stitch_edge, 1.0, 0.0, 1.0, 0.2);
SETCOLF(btheme->tima.preview_stitch_vert, 0.0, 0.0, 1.0, 0.2);
SETCOLF(btheme->tima.preview_stitch_stitchable, 0.0, 1.0, 0.0, 1.0);
SETCOLF(btheme->tima.preview_stitch_unstitchable, 1.0, 0.0, 0.0, 1.0);
/* space text */
btheme->text= btheme->tv3d;
@@ -1679,6 +1706,19 @@ void init_userdef_do_versions(void)
}
}
if (bmain->versionfile < 262){
bTheme *btheme;
for(btheme= U.themes.first; btheme; btheme= btheme->next) {
SETCOLF(btheme->tima.preview_stitch_face, 0.071, 0.259, 0.694, 0.150);
SETCOLF(btheme->tima.preview_stitch_edge, 1.0, 0.522, 0.0, 0.7);
SETCOLF(btheme->tima.preview_stitch_vert, 1.0, 0.522, 0.0, 0.5);
SETCOLF(btheme->tima.preview_stitch_stitchable, 0.0, 1.0, 0.0, 1.0);
SETCOLF(btheme->tima.preview_stitch_unstitchable, 1.0, 0.0, 0.0, 1.0);
SETCOLF(btheme->tima.preview_stitch_active, 0.886, 0.824, 0.765, 0.140);
}
U.use_16bit_textures = 0;
}
/* GL Texture Garbage Collection (variable abused above!) */
if (U.textimeout == 0) {
U.texcollectrate = 60;

View File

@@ -752,6 +752,230 @@ UvMapVert *EDBM_get_uv_map_vert(UvVertMap *vmap, unsigned int v)
return vmap->vert[v];
}
/* from editmesh_lib.c in trunk */
#if 0 /* BMESH_TODO */
/* A specialized vert map used by stitch operator */
UvElementMap *EDBM_make_uv_element_map(EditMesh *em, int selected, int do_islands)
{
EditVert *ev;
EditFace *efa;
/* vars from original func */
UvElementMap *vmap;
UvElement *buf;
UvElement *islandbuf;
MTFace *tf;
unsigned int a;
int i,j, totuv, nverts, nislands = 0, islandbufsize = 0;
unsigned int *map;
/* for uv island creation */
EditFace **stack;
int stacksize = 0;
/* we need the vert */
for(ev = em->verts.first, i = 0; ev; ev = ev->next, i++)
ev->tmp.l = i;
totuv = 0;
for(efa = em->faces.first; efa; efa = efa->next)
if(!selected || ((!efa->h) && (efa->f & SELECT)))
totuv += (efa->v4)? 4: 3;
if(totuv == 0)
return NULL;
vmap = (UvElementMap *)MEM_callocN(sizeof(*vmap), "UvVertElementMap");
if(!vmap)
return NULL;
vmap->vert = (UvElement**)MEM_callocN(sizeof(*vmap->vert)*em->totvert, "UvElementVerts");
buf = vmap->buf = (UvElement*)MEM_callocN(sizeof(*vmap->buf)*totuv, "UvElement");
if(!vmap->vert || !vmap->buf) {
EDBM_free_uv_element_map(vmap);
return NULL;
}
vmap->totalUVs = totuv;
for(efa = em->faces.first; efa; a++, efa = efa->next) {
if(!selected || ((!efa->h) && (efa->f & SELECT))) {
nverts = (efa->v4)? 4: 3;
for(i = 0; i<nverts; i++) {
buf->tfindex = i;
buf->face = efa;
buf->separate = 0;
buf->island = INVALID_ISLAND;
buf->next = vmap->vert[(*(&efa->v1 + i))->tmp.l];
vmap->vert[(*(&efa->v1 + i))->tmp.l] = buf;
buf++;
}
}
efa->tmp.l = INVALID_ISLAND;
}
/* sort individual uvs for each vert */
for(a = 0, ev = em->verts.first; ev; a++, ev = ev->next) {
UvElement *newvlist = NULL, *vlist = vmap->vert[a];
UvElement *iterv, *v, *lastv, *next;
float *uv, *uv2;
while(vlist) {
v= vlist;
vlist= vlist->next;
v->next= newvlist;
newvlist= v;
efa = v->face;
tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
uv = tf->uv[v->tfindex];
lastv= NULL;
iterv= vlist;
while(iterv) {
next= iterv->next;
efa = iterv->face;
tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
uv2 = tf->uv[iterv->tfindex];
if(fabsf(uv[0]-uv2[0]) < STD_UV_CONNECT_LIMIT && fabsf(uv[1]-uv2[1]) < STD_UV_CONNECT_LIMIT) {
if(lastv) lastv->next = next;
else vlist = next;
iterv->next = newvlist;
newvlist = iterv;
}
else
lastv = iterv;
iterv = next;
}
newvlist->separate = 1;
}
vmap->vert[a] = newvlist;
}
if(do_islands) {
/* at this point, every UvElement in vert points to a UvElement sharing the same vertex. Now we should sort uv's in islands. */
/* map holds the map from current vmap->buf to the new, sorted map*/
map = MEM_mallocN(sizeof(*map)*totuv, "uvelement_remap");
stack = MEM_mallocN(sizeof(*stack)*em->totface, "uv_island_face_stack");
islandbuf = MEM_callocN(sizeof(*islandbuf)*totuv, "uvelement_island_buffer");
for(i = 0; i < totuv; i++) {
if(vmap->buf[i].island == INVALID_ISLAND) {
vmap->buf[i].island = nislands;
stack[0] = vmap->buf[i].face;
stack[0]->tmp.l = nislands;
stacksize=1;
while(stacksize > 0) {
efa = stack[--stacksize];
nverts = efa->v4? 4 : 3;
for(j = 0; j < nverts; j++) {
UvElement *element, *initelement = vmap->vert[(*(&efa->v1 + j))->tmp.l];
for(element = initelement; element; element = element->next) {
if(element->separate)
initelement = element;
if(element->face == efa) {
/* found the uv corresponding to our face and vertex. Now fill it to the buffer */
element->island = nislands;
map[element - vmap->buf] = islandbufsize;
islandbuf[islandbufsize].tfindex = element->tfindex;
islandbuf[islandbufsize].face = element->face;
islandbuf[islandbufsize].separate = element->separate;
islandbuf[islandbufsize].island = nislands;
islandbufsize++;
for(element = initelement; element; element = element->next) {
if(element->separate && element != initelement)
break;
if(element->face->tmp.l == INVALID_ISLAND) {
stack[stacksize++] = element->face;
element->face->tmp.l = nislands;
}
}
break;
}
}
}
}
nislands++;
}
}
/* remap */
for(i = 0; i < em->totvert; i++) {
/* important since we may do selection only. Some of these may be NULL */
if(vmap->vert[i])
vmap->vert[i] = &islandbuf[map[vmap->vert[i] - vmap->buf]];
}
vmap->islandIndices = MEM_callocN(sizeof(*vmap->islandIndices)*nislands,"UvVertMap2_island_indices");
if(!vmap->islandIndices) {
MEM_freeN(islandbuf);
MEM_freeN(stack);
MEM_freeN(map);
EDBM_free_uv_element_map(vmap);
}
j = 0;
for(i = 0; i < totuv; i++) {
UvElement *element = vmap->buf[i].next;
if(element == NULL)
islandbuf[map[i]].next = NULL;
else
islandbuf[map[i]].next = &islandbuf[map[element - vmap->buf]];
if(islandbuf[i].island != j) {
j++;
vmap->islandIndices[j] = i;
}
}
MEM_freeN(vmap->buf);
vmap->buf = islandbuf;
vmap->totalIslands = nislands;
MEM_freeN(stack);
MEM_freeN(map);
}
return vmap;
}
#else
UvElementMap *EDBM_make_uv_element_map(BMEditMesh *em, int selected, int do_islands)
{
(void)em;
(void)selected;
(void)do_islands;
return NULL;
}
#endif /* BMESH_TODO */
UvMapVert *EM_get_uv_map_vert(UvVertMap *vmap, unsigned int v)
{
return vmap->vert[v];
}
void EDBM_free_uv_vert_map(UvVertMap *vmap)
{
if (vmap) {
@@ -761,6 +985,15 @@ void EDBM_free_uv_vert_map(UvVertMap *vmap)
}
}
void EDBM_free_uv_element_map(UvElementMap *vmap)
{
if (vmap) {
if (vmap->vert) MEM_freeN(vmap->vert);
if (vmap->buf) MEM_freeN(vmap->buf);
if (vmap->islandIndices) MEM_freeN(vmap->islandIndices);
MEM_freeN(vmap);
}
}
/* last_sel, use em->act_face otherwise get the last selected face in the editselections
* at the moment, last_sel is mainly useful for gaking sure the space image dosnt flicker */

View File

@@ -89,7 +89,7 @@
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_util.h"
#include "ED_image.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -514,11 +514,15 @@ void ED_object_enter_editmode(bContext *C, int flag)
static int editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
ToolSettings *toolsettings = CTX_data_tool_settings(C);
if(!CTX_data_edit_object(C))
ED_object_enter_editmode(C, EM_WAITCURSOR);
else
ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */
ED_space_image_uv_sculpt_update(CTX_wm_manager(C), toolsettings);
return OPERATOR_FINISHED;
}

View File

@@ -23,10 +23,12 @@ set(INC
../../blenkernel
../../blenlib
../../blenloader
../../bmesh
../../gpu
../../imbuf
../../makesdna
../../makesrna
../uvedit
../../render/extern/include
../../windowmanager
../../../../intern/guardedalloc
@@ -45,6 +47,7 @@ set(SRC
paint_vertex.c
sculpt.c
sculpt_undo.c
sculpt_uv.c
paint_intern.h
sculpt_intern.h

View File

@@ -8,7 +8,7 @@ defs = []
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
incs += ' ../../render/extern/include'
incs += ' ../../gpu ../../makesrna ../../blenloader ../../bmesh'
incs += ' ../../gpu ../../makesrna ../../blenloader ../../bmesh ../uvedit'
if env['OURPLATFORM'] == 'linux':
cflags='-pthread'

View File

@@ -50,6 +50,7 @@
#include "BLI_memarena.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BLI_editVert.h"
#include "PIL_time.h"
@@ -80,6 +81,10 @@
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_global.h"
#include "BKE_deform.h"
#include "BKE_tessmesh.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -91,6 +96,7 @@
#include "ED_sculpt.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
#include "ED_mesh.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -100,6 +106,7 @@
#include "RNA_enum_types.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "paint_intern.h"
@@ -3742,15 +3749,13 @@ static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, floa
static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels_f, float co[2])
{
unsigned char rgba_ub[4];
unsigned char rgba_smear[4];
float rgba[4];
if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1)==0)
if (project_paint_PickColor(ps, co, rgba, NULL, 1)==0)
return;
IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba_smear, projPixel->pixel.f_pt);
/* (ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*((unsigned int *)rgba_smear), *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */
blend_color_mix(((ProjPixelClone *)projPixel)->clonepx.ch, rgba_smear, (rgba_ub), (int)(alpha*mask*255));
blend_color_mix_float(((ProjPixelClone *)projPixel)->clonepx.f, projPixel->pixel.f_pt, rgba, alpha*mask);
BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena);
}
@@ -3782,8 +3787,8 @@ static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, flo
{
if (ps->is_texbrush) {
/* rgba already holds a texture result here from higher level function */
float rgba_br[3];
if(use_color_correction){
float rgba_br[3];
srgb_to_linearrgb_v3_v3(rgba_br, ps->brush->rgb);
mul_v3_v3(rgba, rgba_br);
}
@@ -3999,7 +4004,7 @@ static void *do_projectpaint_thread(void *ph_v)
for (node= smearPixels_f; node; node= node->next) {
projPixel = node->link;
IMAPAINT_CHAR_RGBA_TO_FLOAT(projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.ch);
copy_v4_v4(projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f);
}
BLI_memarena_free(smearArena);
@@ -4167,7 +4172,8 @@ static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, s
if(texpaint || (sima && sima->lock)) {
int w = imapaintpartial.x2 - imapaintpartial.x1;
int h = imapaintpartial.y2 - imapaintpartial.y1;
GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h, !texpaint);
/* Testing with partial update in uv editor too */
GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h, 0);//!texpaint);
}
}
@@ -4606,6 +4612,16 @@ static Brush *image_paint_brush(bContext *C)
return paint_brush(&settings->imapaint.paint);
}
static Brush *uv_sculpt_brush(bContext *C)
{
Scene *scene= CTX_data_scene(C);
ToolSettings *settings= scene->toolsettings;
if(!settings->uvsculpt)
return NULL;
return paint_brush(&settings->uvsculpt->paint);
}
static int image_paint_poll(bContext *C)
{
Object *obact = CTX_data_active_object(C);
@@ -4630,6 +4646,30 @@ static int image_paint_poll(bContext *C)
return 0;
}
static int uv_sculpt_brush_poll(bContext *C)
{
BMEditMesh *em;
int ret;
Object *obedit = CTX_data_edit_object(C);
SpaceImage *sima= CTX_wm_space_image(C);
Scene *scene = CTX_data_scene(C);
ToolSettings *toolsettings = scene->toolsettings;
if(!uv_sculpt_brush(C) || !obedit || obedit->type != OB_MESH)
return 0;
em = ((Mesh *)obedit->data)->edit_btmesh;
ret = EDBM_texFaceCheck(em);
if(ret && sima) {
ARegion *ar= CTX_wm_region(C);
if((toolsettings->use_uv_sculpt) && ar->regiontype==RGN_TYPE_WINDOW)
return 1;
}
return 0;
}
static int image_paint_3d_poll(bContext *C)
{
if(CTX_wm_region_view3d(C))
@@ -5086,7 +5126,7 @@ void PAINT_OT_image_paint(wmOperatorType *ot)
RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
}
static int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
{
RegionView3D *rv3d= CTX_wm_region_view3d(C);
@@ -5112,16 +5152,27 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)
#define PX_SIZE_FADE_MIN 4.0f
Scene *scene= CTX_data_scene(C);
Brush *brush= image_paint_brush(C);
//Brush *brush= image_paint_brush(C);
Paint *paint= paint_get_active(scene);
Brush *brush= paint_brush(paint);
if(paint && brush && paint->flags & PAINT_SHOW_BRUSH) {
ToolSettings *ts;
float zoomx, zoomy;
const float size= (float)brush_size(scene, brush);
const short use_zoom= get_imapaint_zoom(C, &zoomx, &zoomy);
const float pixel_size= MAX2(size * zoomx, size * zoomy);
float pixel_size;
float alpha= 0.5f;
ts = scene->toolsettings;
if(use_zoom && !ts->use_uv_sculpt){
pixel_size = MAX2(size * zoomx, size * zoomy);
}
else {
pixel_size = size;
}
/* fade out the brush (cheap trick to work around brush interfearing with sampling [#])*/
if(pixel_size < PX_SIZE_FADE_MIN) {
return;
@@ -5134,7 +5185,8 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)
glTranslatef((float)x, (float)y, 0.0f);
if(use_zoom)
/* No need to scale for uv sculpting, on the contrary it might be useful to keep unscaled */
if(use_zoom && !ts->use_uv_sculpt)
glScalef(zoomx, zoomy, 1.0f);
glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha);
@@ -5152,14 +5204,16 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)
static void toggle_paint_cursor(bContext *C, int enable)
{
ToolSettings *settings= CTX_data_scene(C)->toolsettings;
wmWindowManager *wm= CTX_wm_manager(C);
Scene *scene = CTX_data_scene(C);
ToolSettings *settings= scene->toolsettings;
if(settings->imapaint.paintcursor && !enable) {
WM_paint_cursor_end(CTX_wm_manager(C), settings->imapaint.paintcursor);
WM_paint_cursor_end(wm, settings->imapaint.paintcursor);
settings->imapaint.paintcursor = NULL;
}
else if(enable)
settings->imapaint.paintcursor= WM_paint_cursor_activate(CTX_wm_manager(C), image_paint_poll, brush_drawcursor, NULL);
settings->imapaint.paintcursor= WM_paint_cursor_activate(wm, image_paint_poll, brush_drawcursor, NULL);
}
/* enable the paint cursor if it isn't already.
@@ -5178,6 +5232,27 @@ void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings)
}
}
void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings)
{
if(settings->use_uv_sculpt) {
if(!settings->uvsculpt) {
settings->uvsculpt = MEM_callocN(sizeof(*settings->uvsculpt), "UV Smooth paint");
settings->uv_sculpt_tool = UV_SCULPT_TOOL_GRAB;
settings->uv_sculpt_settings = UV_SCULPT_LOCK_BORDERS | UV_SCULPT_ALL_ISLANDS;
settings->uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN;
}
paint_init(&settings->uvsculpt->paint, PAINT_CURSOR_SCULPT);
WM_paint_cursor_activate(wm, uv_sculpt_brush_poll,
brush_drawcursor, NULL);
}
else {
if(settings->uvsculpt)
settings->uvsculpt->paint.flags &= ~PAINT_SHOW_BRUSH;
}
}
/************************ grab clone operator ************************/
typedef struct GrabClone {
@@ -5499,6 +5574,11 @@ int image_texture_paint_poll(bContext *C)
return (texture_paint_poll(C) || image_paint_poll(C));
}
int uv_sculpt_poll(bContext *C)
{
return uv_sculpt_brush_poll(C);
}
int facemask_paint_poll(bContext *C)
{
return paint_facesel_test(CTX_data_active_object(C));

View File

@@ -103,6 +103,10 @@ void PAINT_OT_texture_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_project_image(struct wmOperatorType *ot);
void PAINT_OT_image_from_view(struct wmOperatorType *ot);
/* uv sculpting */
int uv_sculpt_poll(struct bContext *C);
void SCULPT_OT_uv_sculpt_stroke(struct wmOperatorType *ot);
/* paint_utils.c */

View File

@@ -340,6 +340,39 @@ static void BRUSH_OT_image_tool_set(wmOperatorType *ot)
}
static int brush_uv_sculpt_tool_set_exec(bContext *C, wmOperator *op)
{
Brush *brush;
Scene *scene= CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
ts->uv_sculpt_tool = RNA_enum_get(op->ptr, "tool");
brush = ts->uvsculpt->paint.brush;
/* To update toolshelf */
WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush);
return OPERATOR_FINISHED;
}
static void BRUSH_OT_uv_sculpt_tool_set(wmOperatorType *ot)
{
/* from rna_scene.c */
extern EnumPropertyItem uv_sculpt_tool_items[];
/* identifiers */
ot->name = "UV Sculpt Tool Set";
ot->description = "Set the uv sculpt tool";
ot->idname = "BRUSH_OT_uv_sculpt_tool_set";
/* api callbacks */
ot->exec = brush_uv_sculpt_tool_set_exec;
ot->poll = uv_sculpt_poll;
/* flags */
ot->flag = 0;
/* props */
ot->prop = RNA_def_enum(ot->srna, "tool", uv_sculpt_tool_items, 0, "Tool", "");
}
/**************************** registration **********************************/
void ED_operatortypes_paint(void)
@@ -355,6 +388,7 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(BRUSH_OT_vertex_tool_set);
WM_operatortype_append(BRUSH_OT_weight_tool_set);
WM_operatortype_append(BRUSH_OT_image_tool_set);
WM_operatortype_append(BRUSH_OT_uv_sculpt_tool_set);
/* image */
WM_operatortype_append(PAINT_OT_texture_paint_toggle);
@@ -373,6 +407,9 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_weight_sample);
WM_operatortype_append(PAINT_OT_weight_sample_group);
/* uv */
WM_operatortype_append(SCULPT_OT_uv_sculpt_stroke);
/* vertex selection */
WM_operatortype_append(PAINT_OT_vert_select_all);
WM_operatortype_append(PAINT_OT_vert_select_inverse);
@@ -619,4 +656,22 @@ void ED_keymap_paint(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "PAINT_OT_face_select_linked", LKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "PAINT_OT_face_select_linked_pick", LKEY, KM_PRESS, 0, 0);
keymap= WM_keymap_find(keyconf, "UV Sculpt", 0, 0);
keymap->poll= uv_sculpt_poll;
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", QKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_uv_sculpt");
WM_keymap_add_item(keymap, "SCULPT_OT_uv_sculpt_stroke", LEFTMOUSE, KM_PRESS, 0, 0);
RNA_boolean_set(WM_keymap_add_item(keymap, "SCULPT_OT_uv_sculpt_stroke", LEFTMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);
RNA_boolean_set(WM_keymap_add_item(keymap, "SCULPT_OT_uv_sculpt_stroke", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "temp_relax", 1);
ed_keymap_paint_brush_size(keymap, "tool_settings.uv_sculpt.brush.size");
ed_keymap_paint_brush_radial_control(keymap, "uv_sculpt", 0);
RNA_enum_set(WM_keymap_add_item(keymap, "BRUSH_OT_uv_sculpt_tool_set", SKEY, KM_PRESS, 0, 0)->ptr, "tool", UV_SCULPT_TOOL_RELAX);
RNA_enum_set(WM_keymap_add_item(keymap, "BRUSH_OT_uv_sculpt_tool_set", PKEY, KM_PRESS, 0, 0)->ptr, "tool", UV_SCULPT_TOOL_PINCH);
RNA_enum_set(WM_keymap_add_item(keymap, "BRUSH_OT_uv_sculpt_tool_set", GKEY, KM_PRESS, 0, 0)->ptr, "tool", UV_SCULPT_TOOL_GRAB);
}

View File

@@ -0,0 +1,787 @@
/*
* ***** 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) Blender Foundation, 2002-2009
* All rights reserved.
*
* Contributor(s): Antony Riakiotakis
*
* ***** END GPL LICENSE BLOCK *****
*
* UV Sculpt tools
*
*/
/** \file blender/editors/sculpt_paint/sculpt_uv.c
* \ingroup edsculpt
*/
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_editVert.h"
#include "BLI_math.h"
#include "BLI_ghash.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_brush.h"
#include "BKE_paint.h"
#include "BKE_context.h"
#include "BKE_main.h"
#include "BKE_depsgraph.h"
#include "BKE_mesh.h"
#include "BKE_customdata.h"
#include "BKE_tessmesh.h"
#include "ED_screen.h"
#include "ED_image.h"
#include "ED_mesh.h"
#include "WM_api.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "paint_intern.h"
#include "uvedit_intern.h"
#include "UI_view2d.h"
#define MARK_BOUNDARY 1
typedef struct UvAdjacencyElement {
/* pointer to original uvelement */
UvElement *element;
/* uv pointer for convenience. Caution, this points to the original UVs! */
float *uv;
/* general use flag (Used to check if Element is boundary here) */
char flag;
} UvAdjacencyElement;
typedef struct UvEdge {
unsigned int uv1;
unsigned int uv2;
/* general use flag (Used to check if edge is boundary here, and propagates to adjacency elements) */
char flag;
}UvEdge;
typedef struct UVInitialStrokeElement{
/* index to unique uv */
int uv;
/* strength of brush on initial position */
float strength;
/* initial uv position */
float initial_uv[2];
}UVInitialStrokeElement;
typedef struct UVInitialStroke{
/* Initial Selection,for grab brushes for instance */
UVInitialStrokeElement *initialSelection;
/* total initially selected UVs*/
int totalInitialSelected;
/* initial mouse coordinates */
float init_coord[2];
}UVInitialStroke;
/* custom data for uv smoothing brush */
typedef struct UvSculptData{
/* Contains the first of each set of coincident uvs.
* These will be used to perform smoothing on and propagate the changes
* to their coincident uvs */
UvAdjacencyElement *uv;
/* ...Is what it says */
int totalUniqueUvs;
/* Edges used for adjacency info, used with laplacian smoothing */
UvEdge *uvedges;
/* Need I say more? */
int totalUvEdges;
/* data for initial stroke, used by tools like grab */
UVInitialStroke *initial_stroke;
/* Timer to be used for airbrush-type brush */
wmTimer *timer;
/* To determine quickly adjacent uvs */
UvElementMap *elementMap;
/* uvsmooth Paint for fast reference */
Paint *uvsculpt;
}UvSculptData;
/*********** Improved Laplacian Relaxation Operator ************************/
/* Original code by Raul Fernandez Hernandez "farsthary" *
* adapted to uv smoothing by Antony Riakiatakis *
***************************************************************************/
typedef struct Temp_UvData{
float sum_co[2], p[2], b[2], sum_b[2];
int ncounter;
}Temp_UVData;
void HC_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *sculptdata, float mouse_coord[2], float alpha, float radius, float aspectRatio){
Temp_UVData *tmp_uvdata;
float diff[2];
int i;
float radius_root = sqrt(radius);
Brush *brush = paint_brush(sculptdata->uvsculpt);
tmp_uvdata = (Temp_UVData *)MEM_callocN(sculptdata->totalUniqueUvs * sizeof(Temp_UVData), "Temporal data");
/* counting neighbors */
for (i = 0; i < sculptdata->totalUvEdges; i++){
UvEdge *tmpedge = sculptdata->uvedges+i;
tmp_uvdata[tmpedge->uv1].ncounter++;
tmp_uvdata[tmpedge->uv2].ncounter++;
add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_co, sculptdata->uv[tmpedge->uv1].uv);
add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_co, sculptdata->uv[tmpedge->uv2].uv);
}
for (i = 0; i < sculptdata->totalUniqueUvs; i++){
copy_v2_v2(diff,tmp_uvdata[i].sum_co);
mul_v2_fl(diff,1.f/tmp_uvdata[i].ncounter);
copy_v2_v2(tmp_uvdata[i].p,diff);
tmp_uvdata[i].b[0] = diff[0] - sculptdata->uv[i].uv[0];
tmp_uvdata[i].b[1] = diff[1] - sculptdata->uv[i].uv[1];
}
for (i = 0; i < sculptdata->totalUvEdges; i++){
UvEdge *tmpedge = sculptdata->uvedges+i;
add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_b, tmp_uvdata[tmpedge->uv2].b);
add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_b, tmp_uvdata[tmpedge->uv1].b);
}
for (i = 0; i < sculptdata->totalUniqueUvs; i++){
float dist;
/* This is supposed to happen only if "Pin Edges" is on, since we have initialization on stroke start
* If ever uv brushes get their own mode we should check for toolsettings option too */
if((sculptdata->uv[i].flag & MARK_BOUNDARY)){
continue;
}
sub_v2_v2v2(diff, sculptdata->uv[i].uv, mouse_coord);
diff[1] /= aspectRatio;
if((dist = dot_v2v2(diff, diff)) <= radius){
UvElement *element;
float strength;
strength = alpha*brush_curve_strength(brush, sqrt(dist), radius_root);
sculptdata->uv[i].uv[0] = (1.0-strength)*sculptdata->uv[i].uv[0] + strength*(tmp_uvdata[i].p[0] - 0.5f*(tmp_uvdata[i].b[0] + tmp_uvdata[i].sum_b[0]/tmp_uvdata[i].ncounter));
sculptdata->uv[i].uv[1] = (1.0-strength)*sculptdata->uv[i].uv[1] + strength*(tmp_uvdata[i].p[1] - 0.5f*(tmp_uvdata[i].b[1] + tmp_uvdata[i].sum_b[1]/tmp_uvdata[i].ncounter));
for(element = sculptdata->uv[i].element; element; element = element->next){
#if 0 /* BMESH_TODO */
MTFace *mt;
if(element->separate && element != sculptdata->uv[i].element)
break;
mt = CustomData_em_get(&em->fdata, element->face->data, CD_MTFACE);
copy_v2_v2(mt->uv[element->tfindex], sculptdata->uv[i].uv);
#else
(void)em;
#endif /* BMESH_TODO */
}
}
}
MEM_freeN(tmp_uvdata);
return;
}
static void laplacian_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *sculptdata, float mouse_coord[2], float alpha, float radius, float aspectRatio)
{
Temp_UVData *tmp_uvdata;
float diff[2];
int i;
float radius_root = sqrt(radius);
Brush *brush = paint_brush(sculptdata->uvsculpt);
tmp_uvdata = (Temp_UVData *)MEM_callocN(sculptdata->totalUniqueUvs * sizeof(Temp_UVData), "Temporal data");
/* counting neighbors */
for (i = 0; i < sculptdata->totalUvEdges; i++){
UvEdge *tmpedge = sculptdata->uvedges+i;
tmp_uvdata[tmpedge->uv1].ncounter++;
tmp_uvdata[tmpedge->uv2].ncounter++;
add_v2_v2(tmp_uvdata[tmpedge->uv2].sum_co, sculptdata->uv[tmpedge->uv1].uv);
add_v2_v2(tmp_uvdata[tmpedge->uv1].sum_co, sculptdata->uv[tmpedge->uv2].uv);
}
/* Original Lacplacian algorithm included removal of normal component of translation. here it is not
* needed since we translate along the UV plane always.*/
for (i = 0; i < sculptdata->totalUniqueUvs; i++){
copy_v2_v2(tmp_uvdata[i].p, tmp_uvdata[i].sum_co);
mul_v2_fl(tmp_uvdata[i].p, 1.f/tmp_uvdata[i].ncounter);
}
for (i = 0; i < sculptdata->totalUniqueUvs; i++){
float dist;
/* This is supposed to happen only if "Pin Edges" is on, since we have initialization on stroke start
* If ever uv brushes get their own mode we should check for toolsettings option too */
if((sculptdata->uv[i].flag & MARK_BOUNDARY)){
continue;
}
sub_v2_v2v2(diff, sculptdata->uv[i].uv, mouse_coord);
diff[1] /= aspectRatio;
if((dist = dot_v2v2(diff, diff)) <= radius){
UvElement *element;
float strength;
strength = alpha*brush_curve_strength(brush, sqrt(dist), radius_root);
sculptdata->uv[i].uv[0] = (1.0-strength)*sculptdata->uv[i].uv[0] + strength*tmp_uvdata[i].p[0];
sculptdata->uv[i].uv[1] = (1.0-strength)*sculptdata->uv[i].uv[1] + strength*tmp_uvdata[i].p[1];
for(element = sculptdata->uv[i].element; element; element = element->next){
#if 0 /* BMESH_TODO */
MTFace *mt;
if(element->separate && element != sculptdata->uv[i].element)
break;
mt = CustomData_em_get(&em->fdata, element->face->data, CD_MTFACE);
copy_v2_v2(mt->uv[element->tfindex], sculptdata->uv[i].uv);
#else
(void)em;
#endif /* BMESH_TODO */
}
}
}
MEM_freeN(tmp_uvdata);
return;
}
static void uv_sculpt_stroke_apply(bContext *C, wmOperator *op, wmEvent *event, Object *obedit)
{
float co[2], radius, radius_root;
Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
BMEditMesh *em = ((Mesh *)obedit->data)->edit_btmesh;
unsigned int tool;
UvSculptData *sculptdata = (UvSculptData *)op->customdata;
SpaceImage *sima;
int invert;
int width, height;
float aspectRatio;
float alpha, zoomx, zoomy;
Brush *brush = paint_brush(sculptdata->uvsculpt);
ToolSettings *toolsettings = CTX_data_tool_settings(C);
tool = RNA_boolean_get(op->ptr, "temp_relax")? UV_SCULPT_TOOL_RELAX : toolsettings->uv_sculpt_tool;
invert = RNA_boolean_get(op->ptr, "invert")? -1 : 1;
alpha = brush_alpha(scene, brush);
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
sima = CTX_wm_space_image(C);
ED_space_image_size(sima, &width, &height);
ED_space_image_zoom(sima, ar, &zoomx, &zoomy);
radius = brush_size(scene, brush)/(width*zoomx);
aspectRatio = width/(float)height;
/* We will compare squares to save some computation */
radius = radius*radius;
radius_root = sqrt(radius);
/*
* Pinch Tool
*/
if(tool == UV_SCULPT_TOOL_PINCH){
int i;
alpha *= invert;
for (i = 0; i < sculptdata->totalUniqueUvs; i++){
float dist, diff[2];
/* This is supposed to happen only if "Lock Borders" is on, since we have initialization on stroke start
* If ever uv brushes get their own mode we should check for toolsettings option too */
if(sculptdata->uv[i].flag & MARK_BOUNDARY){
continue;
}
sub_v2_v2v2(diff, sculptdata->uv[i].uv, co);
diff[1] /= aspectRatio;
if((dist = dot_v2v2(diff, diff)) <= radius){
UvElement *element;
float strength;
strength = alpha*brush_curve_strength(brush, sqrt(dist), radius_root);
normalize_v2(diff);
sculptdata->uv[i].uv[0] -= strength*diff[0]*0.001;
sculptdata->uv[i].uv[1] -= strength*diff[1]*0.001;
for(element = sculptdata->uv[i].element; element; element = element->next){
#if 0 /* BMESH_TODO*/
MTFace *mt;
if(element->separate && element != sculptdata->uv[i].element)
break;
mt = CustomData_em_get(&bm->fdata, element->face->data, CD_MTFACE);
copy_v2_v2(mt->uv[element->tfindex], sculptdata->uv[i].uv);
#endif
}
}
}
}
/*
* Smooth Tool
*/
else if(tool == UV_SCULPT_TOOL_RELAX){
unsigned int method = toolsettings->uv_relax_method;
if(method == UV_SCULPT_TOOL_RELAX_HC){
HC_relaxation_iteration_uv(em, sculptdata, co, alpha, radius, aspectRatio);
}else{
laplacian_relaxation_iteration_uv(em, sculptdata, co, alpha, radius, aspectRatio);
}
}
/*
* Grab Tool
*/
else if(tool == UV_SCULPT_TOOL_GRAB){
int i;
float diff[2];
sub_v2_v2v2(diff, co, sculptdata->initial_stroke->init_coord);
for(i = 0; i < sculptdata->initial_stroke->totalInitialSelected; i++ ){
UvElement *element;
int uvindex = sculptdata->initial_stroke->initialSelection[i].uv;
float strength = sculptdata->initial_stroke->initialSelection[i].strength;
sculptdata->uv[uvindex].uv[0] = sculptdata->initial_stroke->initialSelection[i].initial_uv[0] + strength*diff[0];
sculptdata->uv[uvindex].uv[1] = sculptdata->initial_stroke->initialSelection[i].initial_uv[1] + strength*diff[1];
for(element = sculptdata->uv[uvindex].element; element; element = element->next){
#if 0 /* BMESH_TODO */
MTFace *mt;
if(element->separate && element != sculptdata->uv[uvindex].element)
break;
mt = CustomData_em_get(&em->fdata, element->face->data, CD_MTFACE);
copy_v2_v2(mt->uv[element->tfindex], sculptdata->uv[uvindex].uv);
#endif /* BMESH_TODO */
}
}
}
}
static void uv_sculpt_stroke_exit(bContext *C, wmOperator *op)
{
UvSculptData *data = op->customdata;
if(data->timer){
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), data->timer);
}
if(data->elementMap)
{
EDBM_free_uv_element_map(data->elementMap);
}
if(data->uv){
MEM_freeN(data->uv);
}
if(data->uvedges){
MEM_freeN(data->uvedges);
}
if(data->initial_stroke){
if(data->initial_stroke->initialSelection){
MEM_freeN(data->initial_stroke->initialSelection);
}
MEM_freeN(data->initial_stroke);
}
MEM_freeN(data);
op->customdata = NULL;
}
static int get_uv_element_offset_from_face(UvElementMap *map, BMFace *efa, int index, int island_index, int doIslands){
UvElement *element = ED_get_uv_element(map, efa, index);
if(!element || (doIslands && element->island != island_index)){
return -1;
}
return element - map->buf;
}
static unsigned int uv_edge_hash(const void *key){
UvEdge *edge = (UvEdge *)key;
return
BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv2)) +
BLI_ghashutil_inthash(SET_INT_IN_POINTER(edge->uv1));
}
static int uv_edge_compare(const void *a, const void *b){
UvEdge *edge1 = (UvEdge *)a;
UvEdge *edge2 = (UvEdge *)b;
if((edge1->uv1 == edge2->uv1) && (edge1->uv2 == edge2->uv2)){
return 0;
}
return 1;
}
static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
ToolSettings *ts = scene->toolsettings;
UvSculptData *data = MEM_callocN(sizeof(*data), "UV Smooth Brush Data");
BMEditMesh *em = ((Mesh *)obedit->data)->edit_btmesh;
BMesh *bm = em->bm;
op->customdata = data;
if(data){
int counter = 0, i;
ARegion *ar= CTX_wm_region(C);
float co[2];
EditFace *efa;
UvEdge *edges;
GHash *edgeHash;
GHashIterator* ghi;
MTFace *mt;
int do_island_optimization = !(ts->uv_sculpt_settings & UV_SCULPT_ALL_ISLANDS);
int island_index = 0;
/* Holds, for each UvElement in elementMap, a pointer to its unique uv.*/
int *uniqueUv;
data->uvsculpt = &ts->uvsculpt->paint;
if(do_island_optimization){
/* We will need island information */
if(ts->uv_flag & UV_SYNC_SELECTION){
data->elementMap = EDBM_make_uv_element_map(em, 0, 1);
}else{
data->elementMap = EDBM_make_uv_element_map(em, 1, 1);
}
}else {
if(ts->uv_flag & UV_SYNC_SELECTION){
data->elementMap = EDBM_make_uv_element_map(em, 0, 0);
}else{
data->elementMap = EDBM_make_uv_element_map(em, 1, 0);
}
}
if(!data->elementMap){
uv_sculpt_stroke_exit(C, op);
return NULL;
}
/* Mouse coordinates, useful for some functions like grab and sculpt all islands */
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
/* we need to find the active island here */
if(do_island_optimization){
UvElement *element;
NearestHit hit;
Image *ima= CTX_data_edit_image(C);
uv_find_nearest_vert(scene, ima, em, co, NULL, &hit);
element = ED_get_uv_element(data->elementMap, hit.efa, hit.lindex);
island_index = element->island;
}
/* Count 'unique' uvs */
for(i = 0; i < data->elementMap->totalUVs; i++){
if(data->elementMap->buf[i].separate
&& (!do_island_optimization || data->elementMap->buf[i].island == island_index)){
counter++;
}
}
/* Allocate the unique uv buffers */
data->uv = MEM_mallocN(sizeof(*data->uv)*counter, "uv_brush_unique_uvs");
uniqueUv = MEM_mallocN(sizeof(*uniqueUv)*data->elementMap->totalUVs, "uv_brush_unique_uv_map");
edgeHash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "uv_brush_edge_hash");
/* we have at most totalUVs edges */
edges = MEM_mallocN(sizeof(*edges)*data->elementMap->totalUVs, "uv_brush_all_edges");
if(!data->uv || !uniqueUv || !edgeHash || !edges){
if(edges){
MEM_freeN(edges);
}
if(uniqueUv){
MEM_freeN(uniqueUv);
}
if(edgeHash){
MEM_freeN(edgeHash);
}
uv_sculpt_stroke_exit(C, op);
return NULL;
}
data->totalUniqueUvs = counter;
/* So that we can use this as index for the UvElements */
counter = -1;
/* initialize the unique UVs */
for(i = 0; i < bm->totvert; i++){
UvElement *element = data->elementMap->vert[i];
for(; element; element = element->next){
if(element->separate){
if(do_island_optimization && (element->island != island_index)){
/* skip this uv if not on the active island */
for(; element->next && !(element->next->separate); element = element->next)
;
continue;
}
#if 0 /* BMESH_TODO */
efa = element->face;
mt = CustomData_em_get(&bm->fdata, efa->data, CD_MTFACE);
counter++;
data->uv[counter].element = element;
data->uv[counter].flag = 0;
data->uv[counter].uv = mt->uv[element->tfindex];
#else
(void)efa;
(void)mt;
#endif /* BMESH_TODO */
}
/* pointer arithmetic to the rescue, as always :)*/
uniqueUv[element - data->elementMap->buf] = counter;
}
}
#if 0 /* BMESH_TODO */
/* Now, on to generate our uv connectivity data */
for(efa = em->faces.first, counter = 0; efa; efa = efa->next){
int nverts = efa->v4 ? 4 : 3;
for(i = 0; i < nverts; i++){
int offset1, itmp1 = get_uv_element_offset_from_face(data->elementMap, efa, i, island_index, do_island_optimization);
int offset2, itmp2 = get_uv_element_offset_from_face(data->elementMap, efa, (i+1)%nverts, island_index, do_island_optimization);
/* Skip edge if not found(unlikely) or not on valid island */
if(itmp1 == -1 || itmp2 == -1)
continue;
offset1 = uniqueUv[itmp1];
offset2 = uniqueUv[itmp2];
edges[counter].flag = 0;
/* using an order policy, sort uvs according to address space. This avoids
* Having two different UvEdges with the same uvs on different positions */
if(offset1 < offset2){
edges[counter].uv1 = offset1;
edges[counter].uv2 = offset2;
}
else{
edges[counter].uv1 = offset2;
edges[counter].uv2 = offset1;
}
/* Hack! Set the value of the key to its flag. Now we can set the flag when an edge exists twice :) */
if(BLI_ghash_haskey(edgeHash, &edges[counter])){
char *flag = BLI_ghash_lookup(edgeHash, &edges[counter]);
*flag = 1;
}
else{
/* Hack mentioned */
BLI_ghash_insert(edgeHash, &edges[counter], &edges[counter].flag);
}
counter++;
}
}
#endif /* BMESH_TODO */
MEM_freeN(uniqueUv);
/* Allocate connectivity data, we allocate edges once */
data->uvedges = MEM_mallocN(sizeof(*data->uvedges)*BLI_ghash_size(edgeHash), "uv_brush_edge_connectivity_data");
if(!data->uvedges){
BLI_ghash_free(edgeHash, NULL, NULL);
MEM_freeN(edges);
uv_sculpt_stroke_exit(C, op);
return NULL;
}
ghi = BLI_ghashIterator_new(edgeHash);
if(!ghi){
BLI_ghash_free(edgeHash, NULL, NULL);
MEM_freeN(edges);
uv_sculpt_stroke_exit(C, op);
return NULL;
}
/* fill the edges with data */
for(i = 0; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)){
data->uvedges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi));
}
data->totalUvEdges = BLI_ghash_size(edgeHash);
/* cleanup temporary stuff */
BLI_ghashIterator_free(ghi);
BLI_ghash_free(edgeHash, NULL, NULL);
MEM_freeN(edges);
/* transfer boundary edge property to uvs */
if(ts->uv_sculpt_settings & UV_SCULPT_LOCK_BORDERS){
for(i = 0; i < data->totalUvEdges; i++){
if(!data->uvedges[i].flag){
data->uv[data->uvedges[i].uv1].flag |= MARK_BOUNDARY;
data->uv[data->uvedges[i].uv2].flag |= MARK_BOUNDARY;
}
}
}
/* Allocate initial selection for grab tool */
if(ts->uv_sculpt_tool == UV_SCULPT_TOOL_GRAB){
float radius, radius_root;
UvSculptData *sculptdata = (UvSculptData *)op->customdata;
SpaceImage *sima;
int width, height;
float aspectRatio;
float alpha, zoomx, zoomy;
Brush *brush = paint_brush(sculptdata->uvsculpt);
alpha = brush_alpha(scene, brush);
radius = brush_size(scene, brush);
sima = CTX_wm_space_image(C);
ED_space_image_size(sima, &width, &height);
ED_space_image_zoom(sima, ar, &zoomx, &zoomy);
aspectRatio = width/(float)height;
radius /= (width*zoomx);
radius = radius*radius;
radius_root = sqrt(radius);
/* Allocate selection stack */
data->initial_stroke = MEM_mallocN(sizeof(*data->initial_stroke), "uv_sculpt_initial_stroke");
if(!data->initial_stroke){
uv_sculpt_stroke_exit(C, op);
}
data->initial_stroke->initialSelection = MEM_mallocN(sizeof(*data->initial_stroke->initialSelection)*data->totalUniqueUvs, "uv_sculpt_initial_selection");
if(!data->initial_stroke->initialSelection){
uv_sculpt_stroke_exit(C, op);
}
copy_v2_v2(data->initial_stroke->init_coord, co);
counter = 0;
for(i = 0; i < data->totalUniqueUvs; i++){
float dist, diff[2];
if(data->uv[i].flag & MARK_BOUNDARY){
continue;
}
sub_v2_v2v2(diff, data->uv[i].uv, co);
diff[1] /= aspectRatio;
if((dist = dot_v2v2(diff, diff)) <= radius){
float strength;
strength = alpha*brush_curve_strength(brush, sqrt(dist), radius_root);
data->initial_stroke->initialSelection[counter].uv = i;
data->initial_stroke->initialSelection[counter].strength = strength;
copy_v2_v2(data->initial_stroke->initialSelection[counter].initial_uv, data->uv[i].uv);
counter++;
}
}
data->initial_stroke->totalInitialSelected = counter;
}
}
return op->customdata;
}
static int uv_sculpt_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
UvSculptData *data;
Object *obedit = CTX_data_edit_object(C);
if(!(data = uv_sculpt_stroke_init(C, op, event))) {
return OPERATOR_CANCELLED;
}
uv_sculpt_stroke_apply(C, op, event, obedit);
data->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.001f);
if(!data->timer){
uv_sculpt_stroke_exit(C, op);
return OPERATOR_CANCELLED;
}
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;
}
static int uv_sculpt_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
{
UvSculptData *data = (UvSculptData *)op->customdata;
Object *obedit = CTX_data_edit_object(C);
switch(event->type) {
case LEFTMOUSE:
case MIDDLEMOUSE:
case RIGHTMOUSE:
uv_sculpt_stroke_exit(C, op);
return OPERATOR_FINISHED;
case MOUSEMOVE:
case INBETWEEN_MOUSEMOVE:
uv_sculpt_stroke_apply(C, op, event, obedit);
break;
case TIMER:
if(event->customdata == data->timer)
uv_sculpt_stroke_apply(C, op, event, obedit);
break;
default:
return OPERATOR_RUNNING_MODAL;
}
ED_region_tag_redraw(CTX_wm_region(C));
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
DAG_id_tag_update(obedit->data, 0);
return OPERATOR_RUNNING_MODAL;
}
void SCULPT_OT_uv_sculpt_stroke(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Sculpt UVs";
ot->description = "Sculpt UVs using a brush";
ot->idname = "SCULPT_OT_uv_sculpt_stroke";
/* api callbacks */
ot->invoke = uv_sculpt_stroke_invoke;
ot->modal = uv_sculpt_stroke_modal;
ot->poll = uv_sculpt_poll;
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
/* props */
RNA_def_boolean(ot->srna, "invert", 0, "Invert", "Inverts the operator");
RNA_def_boolean(ot->srna, "temp_relax", 0, "Relax", "Relax Tool");
}

View File

@@ -178,6 +178,30 @@ int space_image_main_area_poll(bContext *C)
return 0;
}
/* For IMAGE_OT_curves_point_set to avoid sampling when in uv smooth mode */
int space_image_main_area_not_uv_brush_poll(bContext *C)
{
SpaceImage *sima= CTX_wm_space_image(C);
ToolSettings *toolsettings = CTX_data_scene(C)->toolsettings;
if(sima && !toolsettings->uvsculpt)
return 1;
return 0;
}
static int space_image_image_sample_poll(bContext *C)
{
SpaceImage *sima= CTX_wm_space_image(C);
Object *obedit= CTX_data_edit_object(C);
ToolSettings *toolsettings = CTX_data_scene(C)->toolsettings;
if(obedit){
if(ED_space_image_show_uvedit(sima, obedit) && (toolsettings->use_uv_sculpt))
return 0;
}
return space_image_main_area_poll(C);
}
/********************** view pan operator *********************/
typedef struct ViewPanData {
@@ -1949,7 +1973,7 @@ void IMAGE_OT_sample(wmOperatorType *ot)
ot->invoke= image_sample_invoke;
ot->modal= image_sample_modal;
ot->cancel= image_sample_cancel;
ot->poll= space_image_main_area_poll;
ot->poll= space_image_image_sample_poll;
/* flags */
ot->flag= OPTYPE_BLOCKING;
@@ -2086,7 +2110,7 @@ void IMAGE_OT_curves_point_set(wmOperatorType *ot)
ot->invoke= image_sample_invoke;
ot->modal= image_sample_modal;
ot->cancel= image_sample_cancel;
ot->poll= space_image_main_area_poll;
ot->poll= space_image_main_area_not_uv_brush_poll;
/* properties */
RNA_def_enum(ot->srna, "point", point_items, 0, "Point", "Set black point or white point for curves");

View File

@@ -770,6 +770,9 @@ static void image_main_area_init(wmWindowManager *wm, ARegion *ar)
keymap= WM_keymap_find(wm->defaultconf, "UV Editor", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
keymap= WM_keymap_find(wm->defaultconf, "UV Sculpt", 0, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
/* own keymaps */
keymap= WM_keymap_find(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0);
WM_event_add_keymap_handler(&ar->handlers, keymap);
@@ -782,6 +785,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceImage *sima= CTX_wm_space_image(C);
Object *obact= CTX_data_active_object(C);
Object *obedit= CTX_data_edit_object(C);
Scene *scene= CTX_data_scene(C);
View2D *v2d= &ar->v2d;
@@ -807,7 +811,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
/* and uvs in 0.0-1.0 space */
UI_view2d_view_ortho(v2d);
draw_uvedit_main(sima, ar, scene, obedit);
draw_uvedit_main(sima, ar, scene, obedit, obact);
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);

View File

@@ -40,6 +40,7 @@ set(SRC
uvedit_draw.c
uvedit_ops.c
uvedit_parametrizer.c
uvedit_smart_stitch.c
uvedit_unwrap_ops.c
uvedit_intern.h

View File

@@ -427,12 +427,9 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
}
}
static void draw_uvs_other(Scene *scene, Object *obedit, MTexPoly *activetf)
static void draw_uvs_other(Scene *scene, Object *obedit, Image *curimage)
{
Base *base;
Image *curimage;
curimage= (activetf)? activetf->tpage: NULL;
glColor3ub(96, 96, 96);
@@ -468,6 +465,36 @@ static void draw_uvs_other(Scene *scene, Object *obedit, MTexPoly *activetf)
}
}
static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
{
Mesh *me= ob->data;
Image *curimage = ED_space_image(sima);
if(sima->flag & SI_DRAW_OTHER)
draw_uvs_other(scene, ob, curimage);
glColor3ub(112, 112, 112);
if(me->mtface) {
MPoly *mface= me->mpoly;
MTexPoly *tface= me->mtpoly;
MLoopUV *mloopuv;
int a, b;
for(a=me->totpoly; a>0; a--, tface++, mface++) {
if(tface->tpage == curimage) {
glBegin(GL_LINE_LOOP);
mloopuv = me->mloopuv + mface->loopstart;
for (b=0; b<mface->totloop; b++, mloopuv++) {
glVertex2fv(mloopuv->uv);
}
glEnd();
}
}
}
}
/* draws uv's in the image space */
static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
{
@@ -485,6 +512,12 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
int drawfaces, interpedges;
Image *ima= sima->image;
#if 0 /* BMESH_TODO */
StitchPreviewer *stitch_preview = uv_get_stitch_previewer();
#else
StitchPreviewer *stitch_preview = NULL;
#endif
em= me->edit_btmesh;
activetf= EDBM_get_active_mtexpoly(em, &efa_act, 0); /* will be set to NULL if hidden */
activef = BM_get_actFace(em->bm, 0);
@@ -497,8 +530,11 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
interpedges= (ts->uv_selectmode == UV_SELECT_VERTEX);
/* draw other uvs */
if(sima->flag & SI_DRAW_OTHER)
draw_uvs_other(scene, obedit, activetf);
if(sima->flag & SI_DRAW_OTHER) {
Image *curimage= (activetf)? activetf->tpage: NULL;
draw_uvs_other(scene, obedit, curimage);
}
/* 1. draw shadow mesh */
@@ -846,23 +882,80 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
bglEnd();
}
/* finally draw stitch preview */
if(stitch_preview) {
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glEnable(GL_BLEND);
UI_ThemeColor4(TH_STITCH_PREVIEW_ACTIVE);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glVertexPointer(2, GL_FLOAT, 0, stitch_preview->static_tris);
glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_static_tris*3);
glVertexPointer(2, GL_FLOAT, 0, stitch_preview->static_quads);
glDrawArrays(GL_QUADS, 0, stitch_preview->num_static_quads*4);
glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_tris);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
UI_ThemeColor4(TH_STITCH_PREVIEW_FACE);
glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_tris*3);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
UI_ThemeColor4(TH_STITCH_PREVIEW_EDGE);
glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_tris*3);
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
/*UI_ThemeColor4(TH_STITCH_PREVIEW_VERT);
glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_tris*3);*/
glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_quads);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
UI_ThemeColor4(TH_STITCH_PREVIEW_FACE);
glDrawArrays(GL_QUADS, 0, stitch_preview->num_quads*4);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
UI_ThemeColor4(TH_STITCH_PREVIEW_EDGE);
glDrawArrays(GL_QUADS, 0, stitch_preview->num_quads*4);
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
/*UI_ThemeColor4(TH_STITCH_PREVIEW_VERT);
glDrawArrays(GL_QUADS, 0, stitch_preview->num_quads*4);*/
glDisable(GL_BLEND);
/* draw vert preview */
glPointSize(pointsize*2.0);
UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
glDrawArrays(GL_POINTS, 0, stitch_preview->num_stitchable);
UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE);
glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable);
glDrawArrays(GL_POINTS, 0, stitch_preview->num_unstitchable);
glPopClientAttrib();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
glPointSize(1.0);
}
void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit)
void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit, Object *obact)
{
int show_uvedit, show_uvshadow;
ToolSettings *toolsettings = scene->toolsettings;
int show_uvedit, show_uvshadow, show_texpaint_uvshadow;
show_texpaint_uvshadow = (obact && obact->type == OB_MESH && obact->mode == OB_MODE_TEXTURE_PAINT);
show_uvedit= ED_space_image_show_uvedit(sima, obedit);
show_uvshadow= ED_space_image_show_uvshadow(sima, obedit);
if(show_uvedit || show_uvshadow) {
if(show_uvedit || show_uvshadow || show_texpaint_uvshadow) {
if(show_uvshadow)
draw_uvs_shadow(obedit);
else
else if(show_uvedit)
draw_uvs(sima, scene, obedit);
else
draw_uvs_texpaint(sima, scene, obact);
if(show_uvedit)
if(show_uvedit && !(toolsettings->use_uv_sculpt))
drawcursor_sima(sima, ar);
}
}

View File

@@ -32,11 +32,15 @@
#ifndef ED_UVEDIT_INTERN_H
#define ED_UVEDIT_INTERN_H
struct SpaceImage;
struct EditFace;
struct EditMesh;
struct MTexPoly;
struct Scene;
struct Image;
struct MTFace;
struct Object;
struct Scene;
struct SpaceImage;
struct UvElementMap;
struct wmOperatorType;
struct BMEditMesh;
struct BMFace;
@@ -52,6 +56,7 @@ struct BMVert;
int uvedit_face_visible_nolocal(struct Scene *scene, struct BMFace *efa);
/* geometric utilities */
void uv_center(float uv[][2], float cent[2], int quad);
float uv_area(float uv[][2], int quad);
void uv_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy);
@@ -60,7 +65,55 @@ float poly_uv_area(float uv[][2], int len);
void poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len);
void poly_uv_center(struct BMEditMesh *em, struct BMFace *f, float cent[2]);
/* find nearest */
typedef struct NearestHit {
struct BMFace *efa;
struct MTexPoly *tf;
struct BMLoop *l, *nextl;
struct MLoopUV *luv, *nextluv;
int lindex; //index of loop within face
int vert1, vert2; //index in mesh of edge vertices
} NearestHit;
void uv_find_nearest_vert(struct Scene *scene, struct Image *ima, struct BMEditMesh *em, float co[2], float penalty[2], struct NearestHit *hit);
void uv_find_nearest_edge(struct Scene *scene, struct Image *ima, struct BMEditMesh *em, float co[2], struct NearestHit *hit);
/* utility tool functions */
struct UvElement *ED_get_uv_element(struct UvElementMap *map, struct BMFace *efa, int index);
void uvedit_live_unwrap_update(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit);
/* smart stitch */
/* object that stores display data for previewing before accepting stitching */
typedef struct StitchPreviewer {
/* OpenGL requires different calls for Triangles and Quads.
* here we'll store the quads of the mesh */
float *preview_quads;
/* ...and here we'll store the triangles*/
float *preview_tris;
/* preview data. These will be either the previewed vertices or edges depending on stitch mode settings */
float *preview_stitchable;
float *preview_unstitchable;
/* here we'll store the number of triangles and quads to be drawn */
unsigned int num_tris;
unsigned int num_quads;
unsigned int num_stitchable;
unsigned int num_unstitchable;
/* store static island Quads */
float *static_quads;
/* ...and here we'll store the triangles*/
float *static_tris;
unsigned int num_static_tris;
unsigned int num_static_quads;
} StitchPreviewer;
StitchPreviewer *uv_get_stitch_previewer(void);
/* operators */
void UV_OT_average_islands_scale(struct wmOperatorType *ot);
void UV_OT_cube_project(struct wmOperatorType *ot);
void UV_OT_cylinder_project(struct wmOperatorType *ot);
@@ -70,6 +123,7 @@ void UV_OT_pack_islands(struct wmOperatorType *ot);
void UV_OT_reset(struct wmOperatorType *ot);
void UV_OT_sphere_project(struct wmOperatorType *ot);
void UV_OT_unwrap(struct wmOperatorType *ot);
void UV_OT_stitch(struct wmOperatorType *ot);
#endif /* ED_UVEDIT_INTERN_H */

View File

@@ -20,7 +20,7 @@
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
* Contributor(s): Antony Riakiotakis.
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -103,6 +103,28 @@ int ED_uvedit_test(Object *obedit)
return ret;
}
static int ED_operator_uvedit_can_uv_sculpt(struct bContext *C)
{
SpaceImage *sima= CTX_wm_space_image(C);
ToolSettings *toolsettings = CTX_data_tool_settings(C);
Object *obedit= CTX_data_edit_object(C);
return ED_space_image_show_uvedit(sima, obedit) && !(toolsettings->use_uv_sculpt);
}
static int ED_operator_uvmap_mesh(bContext *C)
{
Object *ob= CTX_data_active_object(C);
if(ob && ob->type==OB_MESH) {
Mesh *me = ob->data;
if(CustomData_get_layer(&me->fdata, CD_MTFACE) != NULL)
return 1;
}
return 0;
}
/**************************** object active image *****************************/
static int is_image_texture_node(bNode *node)
@@ -247,7 +269,13 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist
{
int width, height;
if(sima) {
ED_space_image_size(sima, &width, &height);
}
else {
width= 256;
height= 256;
}
dist[0]= pixeldist/width;
dist[1]= pixeldist/height;
@@ -468,7 +496,7 @@ void uvedit_uv_deselect(BMEditMesh *em, Scene *scene, BMLoop *l)
/*********************** live unwrap utilities ***********************/
static void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit)
void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit)
{
if(sima && (sima->flag & SI_LIVE_UNWRAP)) {
ED_uvedit_live_unwrap_begin(scene, obedit);
@@ -643,16 +671,7 @@ static int uvedit_center(Scene *scene, Image *ima, Object *obedit, float *cent,
/************************** find nearest ****************************/
typedef struct NearestHit {
BMFace *efa;
MTexPoly *tf;
BMLoop *l, *nextl;
MLoopUV *luv, *nextluv;
int lindex; //index of loop within face
int vert1, vert2; //index in mesh of edge vertices
} NearestHit;
static void find_nearest_uv_edge(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit)
void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, float co[2], NearestHit *hit)
{
MTexPoly *tf;
BMFace *efa;
@@ -712,7 +731,7 @@ static void find_nearest_uv_face(Scene *scene, Image *ima, BMEditMesh *em, float
memset(hit, 0, sizeof(*hit));
/*this will fill in hit.vert1 and hit.vert2*/
find_nearest_uv_edge(scene, ima, em, co, hit);
uv_find_nearest_edge(scene, ima, em, co, hit);
hit->l = hit->nextl = NULL;
hit->luv = hit->nextluv = NULL;
@@ -786,7 +805,7 @@ static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int UNUSED(nverts), i
return (c1*c2 >= 0.0f);
}
static void find_nearest_uv_vert(Scene *scene, Image *ima, BMEditMesh *em,
void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em,
float co[2], float penalty[2], NearestHit *hit)
{
BMFace *efa;
@@ -798,7 +817,7 @@ static void find_nearest_uv_vert(Scene *scene, Image *ima, BMEditMesh *em,
int i;
/*this will fill in hit.vert1 and hit.vert2*/
find_nearest_uv_edge(scene, ima, em, co, hit);
uv_find_nearest_edge(scene, ima, em, co, hit);
hit->l = hit->nextl = NULL;
hit->luv = hit->nextluv = NULL;
@@ -918,6 +937,27 @@ static UvMapVert *uv_vertex_map_get(UvVertMap *vmap, BMFace *efa, int a)
return NULL;
}
/* BMESH_TODO - in some cases we already know the loop so looking up the index isnt needed */
UvElement *ED_get_uv_element(UvElementMap *map, BMFace *efa, int index)
{
BMLoop *loop = efa->loops.first;
UvElement *element;
while (index >= 0) {
loop = loop->next;
index--;
}
element = map->vert[BM_GetIndex(loop->v)];
for(; element; element = element->next)
if(element->face == efa)
return element;
return NULL;
}
static int uv_edge_tag_faces(BMEditMesh *em, UvMapVert *first1, UvMapVert *first2, int *totface)
{
UvMapVert *iterv1, *iterv2;
@@ -1536,6 +1576,7 @@ static void UV_OT_weld(wmOperatorType *ot)
ot->poll= ED_operator_uvedit;
}
#if 0 // BMESH_TODO --- this function has been moved elsewhere
/* ******************** stitch operator **************** */
/* just for averaging UVs */
@@ -1703,6 +1744,8 @@ static void UV_OT_stitch(wmOperatorType *ot)
RNA_def_float(ot->srna, "limit", 20.0, 0.0f, FLT_MAX, "Limit", "Limit distance in image pixels", -FLT_MAX, FLT_MAX);
}
#endif
/* ******************** (de)select all operator **************** */
static void select_all_perform(bContext *C, int action)
@@ -1891,7 +1934,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
/* find nearest element */
if(loop) {
/* find edge */
find_nearest_uv_edge(scene, ima, em, co, &hit);
uv_find_nearest_edge(scene, ima, em, co, &hit);
if(hit.efa == NULL) {
BLI_array_free(hitv);
BLI_array_free(hituv);
@@ -1902,7 +1945,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
}
else if(selectmode == UV_SELECT_VERTEX) {
/* find vertex */
find_nearest_uv_vert(scene, ima, em, co, penalty, &hit);
uv_find_nearest_vert(scene, ima, em, co, penalty, &hit);
if(hit.efa == NULL) {
BLI_array_free(hitv);
BLI_array_free(hituv);
@@ -1923,7 +1966,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
}
else if(selectmode == UV_SELECT_EDGE) {
/* find edge */
find_nearest_uv_edge(scene, ima, em, co, &hit);
uv_find_nearest_edge(scene, ima, em, co, &hit);
if(hit.efa == NULL) {
BLI_array_free(hitv);
BLI_array_free(hituv);
@@ -1973,7 +2016,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop)
hitlen = hit.efa->len;
}
else if(selectmode == UV_SELECT_ISLAND) {
find_nearest_uv_vert(scene, ima, em, co, NULL, &hit);
uv_find_nearest_vert(scene, ima, em, co, NULL, &hit);
if(hit.efa==NULL) {
BLI_array_free(hitv);
@@ -2257,7 +2300,7 @@ static int select_linked_internal(bContext *C, wmOperator *op, wmEvent *event, i
RNA_float_get_array(op->ptr, "location", co);
}
find_nearest_uv_vert(scene, ima, em, co, NULL, &hit);
uv_find_nearest_vert(scene, ima, em, co, NULL, &hit);
hit_p= &hit;
}
@@ -3457,6 +3500,183 @@ static void UV_OT_tile_set(wmOperatorType *ot)
RNA_def_int_vector(ot->srna, "tile", 2, NULL, 0, INT_MAX, "Tile", "Tile coordinate", 0, 10);
}
static int seams_from_islands_exec(bContext *C, wmOperator *op)
{
UvVertMap *vmap;
Object *ob = CTX_data_edit_object(C);
Mesh *me= (Mesh*)ob->data;
BMEditMesh *em;
BMEdge *editedge;
float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
char mark_seams = RNA_boolean_get(op->ptr, "mark_seams");
char mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
BMesh *bm;
BMIter iter;
em = me->edit_btmesh;
bm = em->bm;
if(!EDBM_texFaceCheck(em)) {
return OPERATOR_CANCELLED;
}
/* This code sets editvert->tmp.l to the index. This will be useful later on. */
EDBM_init_index_arrays(em, 0, 0, 1);
vmap = EDBM_make_uv_vert_map(em, 0, 0, limit);
BM_ITER(editedge, &iter, bm, BM_EDGES_OF_MESH, NULL) {
/* flags to determine if we uv is separated from first editface match */
char separated1 = 0, separated2;
/* set to denote edge must be flagged as seam */
char faces_separated = 0;
/* flag to keep track if uv1 is disconnected from first editface match */
char v1coincident = 1;
/* For use with v1coincident. v1coincident will change only if we've had commonFaces */
int commonFaces = 0;
BMFace *efa1, *efa2;
UvMapVert *mv1, *mvinit1, *mv2, *mvinit2, *mviter;
/* mv2cache stores the first of the list of coincident uv's for later comparison
* mv2sep holds the last separator and is copied to mv2cache when a hit is first found */
UvMapVert *mv2cache = NULL, *mv2sep = NULL;
mvinit1 = vmap->vert[BM_GetIndex(editedge->v1)];
if(mark_seams)
BM_ClearHFlag(editedge, BM_SEAM);
for(mv1 = mvinit1; mv1 && !faces_separated; mv1 = mv1->next) {
if(mv1->separate && commonFaces)
v1coincident = 0;
separated2 = 0;
efa1 = EDBM_get_face_for_index(em, mv1->f);
mvinit2 = vmap->vert[BM_GetIndex(editedge->v2)];
for(mv2 = mvinit2; mv2; mv2 = mv2->next) {
if(mv2->separate)
mv2sep = mv2;
efa2 = EDBM_get_face_for_index(em, mv2->f);
if(efa1 == efa2) {
/* if v1 is not coincident no point in comparing */
if(v1coincident) {
/* have we found previously anything? */
if(mv2cache) {
/* flag seam unless proved to be coincident with previous hit */
separated2 = 1;
for(mviter = mv2cache; mviter; mviter = mviter->next) {
if(mviter->separate && mviter != mv2cache)
break;
/* coincident with previous hit, do not flag seam */
if(mviter == mv2)
separated2 = 0;
}
}
/* First hit case, store the hit in the cache */
else {
mv2cache = mv2sep;
commonFaces = 1;
}
}
else
separated1 = 1;
if(separated1 || separated2) {
faces_separated = 1;
break;
}
}
}
}
if(faces_separated) {
if(mark_seams)
BM_SetHFlag(editedge, BM_SEAM);
if(mark_sharp)
BM_SetHFlag(editedge, BM_SHARP);
}
}
me->drawflag |= ME_DRAWSEAMS;
EDBM_free_uv_vert_map(vmap);
EDBM_free_index_arrays(em);
DAG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
return OPERATOR_FINISHED;
}
static void UV_OT_seams_from_islands(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Seams From Islands";
ot->description= "Set mesh seams according to island setup in the UV editor";
ot->idname= "UV_OT_seams_from_islands";
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* api callbacks */
ot->exec= seams_from_islands_exec;
ot->poll= ED_operator_uvedit;
RNA_def_boolean(ot->srna, "mark_seams", 1, "Mark Seams", "Mark boundary edges as seams");
RNA_def_boolean(ot->srna, "mark_sharp", 0, "Mark Sharp", "Mark boundary edges as sharp");
}
static int mark_seam_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
Mesh *me= (Mesh*)ob->data;
BMEditMesh *em= me->edit_btmesh;
BMesh *bm = em->bm;
BMFace *efa;
BMLoop *loop;
BMIter iter, liter;
BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
BM_ITER(loop, &liter, bm, BM_LOOPS_OF_FACE, efa) {
if(uvedit_edge_selected(em, scene, loop)) {
BM_SetHFlag(loop, BM_SEAM);
}
}
}
me->drawflag |= ME_DRAWSEAMS;
if(scene->toolsettings->edge_mode_live_unwrap)
ED_unwrap_lscm(scene, ob, FALSE);
DAG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, me);
return OPERATOR_FINISHED;
}
static void UV_OT_mark_seam(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Mark Seams";
ot->description= "Mark selected UV edges as seams";
ot->idname= "UV_OT_mark_seam";
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* api callbacks */
ot->exec= mark_seam_exec;
ot->poll= ED_operator_uvedit;
}
/* ************************** registration **********************************/
void ED_operatortypes_uvedit(void)
@@ -3475,7 +3695,11 @@ void ED_operatortypes_uvedit(void)
WM_operatortype_append(UV_OT_snap_selected);
WM_operatortype_append(UV_OT_align);
#if 0 /* BMESH_TODO */
WM_operatortype_append(UV_OT_stitch);
#endif
WM_operatortype_append(UV_OT_seams_from_islands);
WM_operatortype_append(UV_OT_mark_seam);
WM_operatortype_append(UV_OT_weld);
WM_operatortype_append(UV_OT_pin);
@@ -3502,7 +3726,14 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf)
wmKeyMapItem *kmi;
keymap= WM_keymap_find(keyconf, "UV Editor", 0, 0);
keymap->poll= ED_operator_uvedit;
keymap->poll= ED_operator_uvedit_can_uv_sculpt;
/* Uv sculpt toggle */
kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", QKEY, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_uv_sculpt");
/* Mark edge seam */
WM_keymap_add_item(keymap, "UV_OT_mark_seam", EKEY, KM_PRESS, KM_CTRL, 0);
/* pick selection */
RNA_boolean_set(WM_keymap_add_item(keymap, "UV_OT_select", SELECTMOUSE, KM_PRESS, 0, 0)->ptr, "extend", FALSE);

View File

@@ -91,7 +91,7 @@ typedef struct PVert {
} u;
struct PEdge *edge;
float *co;
float co[3];
float uv[2];
unsigned char flag;
@@ -655,11 +655,15 @@ static void p_face_backup_uvs(PFace *f)
{
PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
if (e1->orig_uv && e2->orig_uv && e3->orig_uv) {
if (e1->orig_uv) {
e1->old_uv[0] = e1->orig_uv[0];
e1->old_uv[1] = e1->orig_uv[1];
}
if (e2->orig_uv) {
e2->old_uv[0] = e2->orig_uv[0];
e2->old_uv[1] = e2->orig_uv[1];
}
if (e3->orig_uv) {
e3->old_uv[0] = e3->orig_uv[0];
e3->old_uv[1] = e3->orig_uv[1];
}
@@ -669,11 +673,15 @@ static void p_face_restore_uvs(PFace *f)
{
PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
if (e1->orig_uv && e2->orig_uv && e3->orig_uv) {
if (e1->orig_uv) {
e1->orig_uv[0] = e1->old_uv[0];
e1->orig_uv[1] = e1->old_uv[1];
}
if (e2->orig_uv) {
e2->orig_uv[0] = e2->old_uv[0];
e2->orig_uv[1] = e2->old_uv[1];
}
if (e3->orig_uv) {
e3->orig_uv[0] = e3->old_uv[0];
e3->orig_uv[1] = e3->old_uv[1];
}
@@ -684,7 +692,7 @@ static void p_face_restore_uvs(PFace *f)
static PVert *p_vert_add(PHandle *handle, PHashKey key, float *co, PEdge *e)
{
PVert *v = (PVert*)BLI_memarena_alloc(handle->arena, sizeof *v);
v->co = co;
copy_v3_v3(v->co, co);
v->u.key = key;
v->edge = e;
v->flag = 0;
@@ -708,7 +716,7 @@ static PVert *p_vert_copy(PChart *chart, PVert *v)
{
PVert *nv = (PVert*)BLI_memarena_alloc(chart->handle->arena, sizeof *nv);
nv->co = v->co;
copy_v3_v3(nv->co, v->co);
nv->uv[0] = v->uv[0];
nv->uv[1] = v->uv[1];
nv->u.key = v->u.key;

File diff suppressed because it is too large Load Diff

View File

@@ -40,6 +40,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_modifier_types.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -50,12 +51,15 @@
#include "BLI_rand.h"
#include "BLI_string.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_subsurf.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_depsgraph.h"
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_report.h"
#include "BKE_tessmesh.h"
#include "BLI_math.h"
@@ -318,6 +322,215 @@ static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em,
return handle;
}
#if 0 /* BMESH_TODO */
static void texface_from_original_index(EditFace *editFace, MTFace *texFace, int index, float **uv, ParamBool *pin, ParamBool *select, Scene *scene)
{
int i, nverts = (editFace->v4)? 4: 3;
*uv = NULL;
*pin = 0;
*select = 1;
if(index == ORIGINDEX_NONE)
return;
for(i = 0; i < nverts; i++) {
if((*(&editFace->v1 + i))->tmp.t == index) {
*uv = texFace->uv[i];
*pin = ((texFace->unwrap & TF_PIN_MASK(i)) != 0);
*select = (uvedit_uv_selected(scene, editFace, texFace, i) != 0);
}
}
}
/* unwrap handle initialization for subsurf aware-unwrapper. The many modifications required to make the original function(see above)
* work justified the existence of a new function. */
static ParamHandle *construct_param_handle_subsurfed(Scene *scene, EditMesh *editMesh, short fill, short sel, short correct_aspect)
{
ParamHandle *handle;
/* index pointers */
MFace *face;
MEdge *edge;
EditVert *editVert;
MTFace *texface;
EditFace *editFace, **editFaceTmp;
EditEdge *editEdge, **editEdgeTmp;
int i;
/* modifier initialization data, will control what type of subdivision will happen*/
SubsurfModifierData smd = {{0}};
/* Used to hold subsurfed Mesh */
DerivedMesh *derivedMesh, *initialDerived;
/* holds original indices for subsurfed mesh */
int *origVertIndices, *origFaceIndices, *origEdgeIndices;
/* Holds vertices of subsurfed mesh */
MVert *subsurfedVerts;
MEdge *subsurfedEdges;
MFace *subsurfedFaces;
MTFace *subsurfedTexfaces;
/* number of vertices and faces for subsurfed mesh*/
int numOfEdges, numOfFaces;
/* holds a map to editfaces for every subsurfed MFace. These will be used to get hidden/ selected flags etc. */
EditFace **faceMap;
/* Mini container to hold all EditFaces so that they may be indexed easily and fast. */
EditFace **editFaceArray;
/* similar to the above, we need a way to map edges to their original ones */
EditEdge **edgeMap;
EditEdge **editEdgeArray;
handle = param_construct_begin();
if(correct_aspect) {
EditFace *eface = EM_get_actFace(editMesh, 1);
if(eface) {
float aspx, aspy;
texface= CustomData_em_get(&editMesh->fdata, eface->data, CD_MTFACE);
ED_image_uv_aspect(texface->tpage, &aspx, &aspy);
if(aspx!=aspy)
param_aspect_ratio(handle, aspx, aspy);
}
}
/* number of subdivisions to perform */
smd.levels = scene->toolsettings->uv_subsurf_level;
smd.subdivType = ME_CC_SUBSURF;
initialDerived = CDDM_from_editmesh(editMesh, NULL);
derivedMesh = subsurf_make_derived_from_derived(initialDerived, &smd,
0, NULL, 0, 0, 1);
initialDerived->release(initialDerived);
/* get the derived data */
subsurfedVerts = derivedMesh->getVertArray(derivedMesh);
subsurfedEdges = derivedMesh->getEdgeArray(derivedMesh);
subsurfedFaces = derivedMesh->getFaceArray(derivedMesh);
origVertIndices = derivedMesh->getVertDataArray(derivedMesh, CD_ORIGINDEX);
origEdgeIndices = derivedMesh->getEdgeDataArray(derivedMesh, CD_ORIGINDEX);
origFaceIndices = derivedMesh->getFaceDataArray(derivedMesh, CD_ORIGINDEX);
subsurfedTexfaces = derivedMesh->getFaceDataArray(derivedMesh, CD_MTFACE);
numOfEdges = derivedMesh->getNumEdges(derivedMesh);
numOfFaces = derivedMesh->getNumFaces(derivedMesh);
faceMap = MEM_mallocN(numOfFaces*sizeof(EditFace *), "unwrap_edit_face_map");
editFaceArray = MEM_mallocN(editMesh->totface*sizeof(EditFace *), "unwrap_editFaceArray");
/* fill edit face array with edit faces */
for(editFace = editMesh->faces.first, editFaceTmp = editFaceArray; editFace; editFace= editFace->next, editFaceTmp++)
*editFaceTmp = editFace;
/* map subsurfed faces to original editFaces */
for(i = 0; i < numOfFaces; i++)
faceMap[i] = editFaceArray[origFaceIndices[i]];
MEM_freeN(editFaceArray);
edgeMap = MEM_mallocN(numOfEdges*sizeof(EditEdge *), "unwrap_edit_edge_map");
editEdgeArray = MEM_mallocN(editMesh->totedge*sizeof(EditEdge *), "unwrap_editEdgeArray");
/* fill edit edge array with edit edges */
for(editEdge = editMesh->edges.first, editEdgeTmp = editEdgeArray; editEdge; editEdge= editEdge->next, editEdgeTmp++)
*editEdgeTmp = editEdge;
/* map subsurfed edges to original editEdges */
for(i = 0; i < numOfEdges; i++) {
/* not all edges correspond to an old edge */
edgeMap[i] = (origEdgeIndices[i] != -1)?
editEdgeArray[origEdgeIndices[i]] : NULL;
}
MEM_freeN(editEdgeArray);
/* we need the editvert indices too */
for(editVert = editMesh->verts.first, i=0; editVert; editVert = editVert->next, i++)
editVert->tmp.t = i;
/* Prepare and feed faces to the solver */
for(i = 0; i < numOfFaces; i++) {
ParamKey key, vkeys[4];
ParamBool pin[4], select[4];
float *co[4];
float *uv[4];
EditFace *origFace = faceMap[i];
MTFace *origtexface = (MTFace *)CustomData_em_get(&editMesh->fdata, origFace->data, CD_MTFACE);
face = subsurfedFaces+i;
if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
if(origFace->h)
continue;
}
else {
if((origFace->h) || (sel && (origFace->f & SELECT)==0))
continue;
}
/* Now we feed the rest of the data from the subsurfed faces */
texface= subsurfedTexfaces+i;
/* We will not check for v4 here. Subsurfed mfaces always have 4 vertices. */
key = (ParamKey)face;
vkeys[0] = (ParamKey)face->v1;
vkeys[1] = (ParamKey)face->v2;
vkeys[2] = (ParamKey)face->v3;
vkeys[3] = (ParamKey)face->v4;
co[0] = subsurfedVerts[face->v1].co;
co[1] = subsurfedVerts[face->v2].co;
co[2] = subsurfedVerts[face->v3].co;
co[3] = subsurfedVerts[face->v4].co;
/* This is where all the magic is done. If the vertex exists in the, we pass the original uv pointer to the solver, thus
* flushing the solution to the edit mesh. */
texface_from_original_index(origFace, origtexface, origVertIndices[face->v1], &uv[0], &pin[0], &select[0], scene);
texface_from_original_index(origFace, origtexface, origVertIndices[face->v2], &uv[1], &pin[1], &select[1], scene);
texface_from_original_index(origFace, origtexface, origVertIndices[face->v3], &uv[2], &pin[2], &select[2], scene);
texface_from_original_index(origFace, origtexface, origVertIndices[face->v4], &uv[3], &pin[3], &select[3], scene);
param_face_add(handle, key, 4, vkeys, co, uv, pin, select);
}
/* these are calculated from original mesh too */
for(edge = subsurfedEdges, i = 0; i < numOfEdges; i++, edge++) {
if((edgeMap[i] != NULL) && edgeMap[i]->seam) {
ParamKey vkeys[2];
vkeys[0] = (ParamKey)edge->v1;
vkeys[1] = (ParamKey)edge->v2;
param_edge_set_seam(handle, vkeys);
}
}
param_construct_end(handle, fill, 0);
/* cleanup */
MEM_freeN(faceMap);
MEM_freeN(edgeMap);
derivedMesh->release(derivedMesh);
return handle;
}
#else
static ParamHandle *construct_param_handle_subsurfed(Scene *scene, BMEditMesh *editMesh, short fill, short sel, short correct_aspect)
{
(void)scene;
(void)editMesh;
(void)fill;
(void)sel;
(void)correct_aspect;
return NULL;
}
#endif /* BMESH_TODO */
/* ******************** Minimize Stretch operator **************** */
typedef struct MinStretch {
@@ -619,11 +832,15 @@ void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
short abf = scene->toolsettings->unwrapper == 0;
short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
short use_subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
if(!ED_uvedit_test(obedit)) {
return;
}
if(use_subsurf)
liveHandle = construct_param_handle_subsurfed(scene, em, fillholes, 0, 1);
else
liveHandle = construct_param_handle(scene, em, 0, fillholes, 0, 1);
param_lscm_begin(liveHandle, PARAM_TRUE, abf);
@@ -937,9 +1154,12 @@ void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
const short fill_holes= scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
const short correct_aspect= !(scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT);
short implicit= 0;
const short use_subsurf = scene->toolsettings->uvcalc_flag & UVCALC_USESUBSURF;
handle= construct_param_handle(scene, em, implicit, fill_holes, sel, correct_aspect);
if(use_subsurf)
handle = construct_param_handle_subsurfed(scene, em, fill_holes, sel, correct_aspect);
else
handle= construct_param_handle(scene, em, 0, fill_holes, sel, correct_aspect);
param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
param_lscm_solve(handle);
@@ -960,6 +1180,9 @@ static int unwrap_exec(bContext *C, wmOperator *op)
int method = RNA_enum_get(op->ptr, "method");
int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
int correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
int use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data");
int subsurf_level = RNA_int_get(op->ptr, "uv_subsurf_level");
float obsize[3], unitsize[3] = {1.0f, 1.0f, 1.0f};
short implicit= 0;
if(!uvedit_have_selection(scene, em, implicit)) {
@@ -971,15 +1194,24 @@ static int unwrap_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
mat4_to_size(obsize, obedit->obmat);
if(!compare_v3v3(obsize, unitsize, 1e-4f))
BKE_report(op->reports, RPT_INFO, "Object scale is not 1.0. Unwrap will operate on a non-scaled version of the mesh.");
/* remember last method for live unwrap */
scene->toolsettings->unwrapper = method;
scene->toolsettings->uv_subsurf_level = subsurf_level;
if(fill_holes) scene->toolsettings->uvcalc_flag |= UVCALC_FILLHOLES;
else scene->toolsettings->uvcalc_flag &= ~UVCALC_FILLHOLES;
if(correct_aspect) scene->toolsettings->uvcalc_flag &= ~UVCALC_NO_ASPECT_CORRECT;
else scene->toolsettings->uvcalc_flag |= UVCALC_NO_ASPECT_CORRECT;
if(use_subsurf) scene->toolsettings->uvcalc_flag |= UVCALC_USESUBSURF;
else scene->toolsettings->uvcalc_flag &= ~UVCALC_USESUBSURF;
/* execute unwrap */
ED_unwrap_lscm(scene, obedit, TRUE);
@@ -1013,6 +1245,8 @@ void UV_OT_unwrap(wmOperatorType *ot)
"Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry");
RNA_def_boolean(ot->srna, "correct_aspect", 1, "Correct Aspect",
"Map UVs taking image aspect ratio into account");
RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Data", "Map UV's taking vertex position after subsurf into account");
RNA_def_int(ot->srna, "uv_subsurf_level", 1, 1, 6, "SubSurf Target", "Number of times to subdivide before calculating UV's", 1, 6);
}
/**************** Project From View operator **************/

View File

@@ -410,9 +410,12 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
ImBuf *ibuf = NULL;
unsigned int *bind = NULL;
int rectw, recth, tpx=0, tpy=0, y;
unsigned int *rectrow, *tilerectrow;
unsigned int *tilerect= NULL, *scalerect= NULL, *rect= NULL;
float *ftilerect= NULL, *fscalerect = NULL, *frect = NULL;
float *srgb_frect = NULL;
short texwindx, texwindy, texwinsx, texwinsy;
/* flag to determine whether high resolution format is used */
int use_high_bit_depth = FALSE, do_color_management = FALSE;
/* initialize tile mode and number of repeats */
GTS.ima = ima;
@@ -462,9 +465,20 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
if(ibuf==NULL)
return 0;
/* ensure we have a char buffer and not only float */
if ((ibuf->rect==NULL) && ibuf->rect_float)
if(ibuf->rect_float) {
if(U.use_16bit_textures) {
/* use high precision textures. This is relatively harmless because OpenGL gives us
a high precision format only if it is available */
use_high_bit_depth = TRUE;
}
/* TODO unneeded when float images are correctly treated as linear always */
if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
do_color_management = TRUE;
if(ibuf->rect==NULL)
IMB_rect_from_float(ibuf);
}
/* currently, tpage refresh is used by ima sequences */
if(ima->tpageflag & IMA_TPAGE_REFRESH) {
@@ -498,6 +512,18 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
tpx= texwindx;
tpy= texwindy;
if(use_high_bit_depth) {
if(do_color_management) {
srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(float)*4, "floar_buf_col_cor");
IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
ibuf->channels, IB_PROFILE_SRGB, ibuf->profile, 0,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
frect= srgb_frect + texwinsy*ibuf->x + texwinsx;
}
else
frect= ibuf->rect_float + texwinsy*ibuf->x + texwinsx;
}
else
rect= ibuf->rect + texwinsy*ibuf->x + texwinsx;
}
}
@@ -509,6 +535,16 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
tpx= ibuf->x;
tpy= ibuf->y;
rect= ibuf->rect;
if(use_high_bit_depth) {
if(do_color_management) {
frect = srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(*srgb_frect)*4, "floar_buf_col_cor");
IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
ibuf->channels, IB_PROFILE_SRGB, ibuf->profile, 0,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
else
frect= ibuf->rect_float;
}
}
}
@@ -523,6 +559,23 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
/* for tiles, copy only part of image into buffer */
if (GTS.tilemode) {
if(use_high_bit_depth) {
float *frectrow, *ftilerectrow;
ftilerect= MEM_mallocN(rectw*recth*sizeof(*ftilerect), "tilerect");
for (y=0; y<recth; y++) {
frectrow= &frect[y*ibuf->x];
ftilerectrow= &ftilerect[y*rectw];
memcpy(ftilerectrow, frectrow, tpx*sizeof(*frectrow));
}
frect= ftilerect;
}
else {
unsigned int *rectrow, *tilerectrow;
tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
for (y=0; y<recth; y++) {
@@ -534,27 +587,47 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
rect= tilerect;
}
}
/* scale if not a power of two */
/* scale if not a power of two. this is not strictly necessary for newer
GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures */
if (!is_pow2_limit(rectw) || !is_pow2_limit(recth)) {
rectw= smaller_pow2_limit(rectw);
recth= smaller_pow2_limit(recth);
if(use_high_bit_depth) {
fscalerect= MEM_mallocN(rectw*recth*sizeof(*fscalerect)*4, "fscalerect");
gluScaleImage(GL_RGBA, tpx, tpy, GL_FLOAT, frect, rectw, recth, GL_FLOAT, fscalerect);
/* frect will refer to ibuf->rect_float when not color converting. We don't want to free that */
if(do_color_management)
MEM_freeN(frect);
frect = fscalerect;
}
else {
scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect");
gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
rect= scalerect;
}
}
/* create image */
glGenTextures(1, (GLuint *)bind);
glBindTexture( GL_TEXTURE_2D, *bind);
if (!(gpu_get_mipmap() && mipmap)) {
if(use_high_bit_depth)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
}
else {
if(use_high_bit_depth)
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA16, rectw, recth, GL_RGBA, GL_FLOAT, frect);
else
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
@@ -570,9 +643,14 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
/* clean up */
if (tilerect)
MEM_freeN(tilerect);
if (ftilerect)
MEM_freeN(ftilerect);
if (scalerect)
MEM_freeN(scalerect);
if (fscalerect)
MEM_freeN(fscalerect);
if (srgb_frect)
MEM_freeN(srgb_frect);
return *bind;
}
@@ -692,24 +770,22 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap)
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels);
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows);
if (ibuf->rect_float){
/*This case needs a whole new buffer*/
if(ibuf->rect==NULL) {
IMB_rect_from_float(ibuf);
}
else {
/* Do partial drawing. 'buffer' holds only the changed part. Needed for color corrected result */
float *buffer = (float *)MEM_mallocN(w*h*sizeof(float)*4, "temp_texpaint_float_buf");
/* if color correction is needed, we must update the part that needs updating. */
if(ibuf->rect_float && (!U.use_16bit_textures || (ibuf->profile == IB_PROFILE_LINEAR_RGB))) {
float *buffer = MEM_mallocN(w*h*sizeof(float)*4, "temp_texpaint_float_buf");
IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h);
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
GL_FLOAT, buffer);
MEM_freeN(buffer);
if(ima->tpageflag & IMA_MIPMAP_COMPLETE)
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
return;
}
}
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
@@ -717,6 +793,10 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap)
glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
if(ibuf->rect_float)
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
GL_FLOAT, ibuf->rect_float);
else
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
GL_UNSIGNED_BYTE, ibuf->rect);

View File

@@ -671,7 +671,17 @@ typedef struct GameData {
#define GAME_MAT_MULTITEX 1
#define GAME_MAT_GLSL 2
/* *************************************************************** */
/* UV Paint */
#define UV_SCULPT_LOCK_BORDERS 1
#define UV_SCULPT_ALL_ISLANDS 2
#define UV_SCULPT_TOOL_PINCH 1
#define UV_SCULPT_TOOL_RELAX 2
#define UV_SCULPT_TOOL_GRAB 3
#define UV_SCULPT_TOOL_RELAX_LAPLACIAN 1
#define UV_SCULPT_TOOL_RELAX_HC 2
/* Markers */
typedef struct TimeMarker {
@@ -780,6 +790,9 @@ typedef struct Sculpt {
int pad;
} Sculpt;
typedef struct UvSculpt {
Paint paint;
} UvSculpt;
/* ------------------------------------------- */
/* Vertex Paint */
@@ -855,6 +868,7 @@ typedef struct ToolSettings {
VPaint *vpaint; /* vertex paint */
VPaint *wpaint; /* weight paint */
Sculpt *sculpt;
UvSculpt *uvsculpt; /* uv smooth */
/* Vertex groups */
float vgroup_weight;
@@ -894,7 +908,7 @@ typedef struct ToolSettings {
short uvcalc_mapalign;
short uvcalc_flag;
short uv_flag, uv_selectmode;
short uv_pad;
short uv_subsurf_level;
/* Grease Pencil */
short gpencil_flags;
@@ -966,10 +980,14 @@ typedef struct ToolSettings {
char auto_normalize; /*auto normalizing mode in wpaint*/
char multipaint; /* paint multiple bones in wpaint */
/* UV painting */
int use_uv_sculpt;
int uv_sculpt_settings;
int uv_sculpt_tool;
int uv_relax_method;
/* XXX: these sculpt_paint_* fields are deprecated, use the
unified_paint_settings field instead! */
short sculpt_paint_settings DNA_DEPRECATED;
short pad1;
short sculpt_paint_settings DNA_DEPRECATED; short pad1;
int sculpt_paint_unified_size DNA_DEPRECATED;
float sculpt_paint_unified_unprojected_radius DNA_DEPRECATED;
float sculpt_paint_unified_alpha DNA_DEPRECATED;
@@ -1421,6 +1439,7 @@ typedef enum SculptFlags {
#define UVCALC_FILLHOLES 1
#define UVCALC_NO_ASPECT_CORRECT 2 /* would call this UVCALC_ASPECT_CORRECT, except it should be default with old file */
#define UVCALC_TRANSFORM_CORRECT 4 /* adjust UV's while transforming to avoid distortion */
#define UVCALC_USESUBSURF 8 /* Use mesh data after subsurf to compute UVs*/
/* toolsettings->uv_flag */
#define UV_SYNC_SELECTION 1

View File

@@ -252,7 +252,12 @@ typedef struct ThemeSpace {
char hpad[7];
char preview_back[4];
char preview_stitch_face[4];
char preview_stitch_edge[4];
char preview_stitch_vert[4];
char preview_stitch_stitchable[4];
char preview_stitch_unstitchable[4];
char preview_stitch_active[4];
} ThemeSpace;
@@ -391,7 +396,7 @@ typedef struct UserDef {
short widget_unit; /* defaults to 20 for 72 DPI setting */
short anisotropic_filter;
/*short pad[3]; */
short use_16bit_textures, pad8;
float ndof_sensitivity; /* overall sensitivity of 3D mouse */
int ndof_flag; /* flags for 3D mouse */
@@ -403,7 +408,7 @@ typedef struct UserDef {
short autokey_mode; /* autokeying mode */
short autokey_flag; /* flags for autokeying */
short text_render, pad9[3]; /*options for text rendering*/
short text_render, pad9; /*options for text rendering*/
struct ColorBand coba_weight; /* from texture.h */

View File

@@ -421,6 +421,7 @@ extern StructRNA RNA_Scopes;
extern StructRNA RNA_Screen;
extern StructRNA RNA_ScrewModifier;
extern StructRNA RNA_Sculpt;
extern StructRNA RNA_SelectedUvElement;
extern StructRNA RNA_Sensor;
extern StructRNA RNA_Sequence;
extern StructRNA RNA_SequenceColorBalance;

View File

@@ -65,6 +65,18 @@
#include "BLI_threads.h"
EnumPropertyItem uv_sculpt_relaxation_items[] = {
{UV_SCULPT_TOOL_RELAX_LAPLACIAN, "LAPLACIAN", 0, "Laplacian", "Use Laplacian method for relaxation"},
{UV_SCULPT_TOOL_RELAX_HC, "HC", 0, "HC", "Use HC method for relaxation"},
{0, NULL, 0, NULL, NULL}};
EnumPropertyItem uv_sculpt_tool_items[] = {
{UV_SCULPT_TOOL_PINCH, "PINCH", 0, "Pinch", "Pinch UVs"},
{UV_SCULPT_TOOL_RELAX, "RELAX", 0, "Relax", "Relax UVs"},
{UV_SCULPT_TOOL_GRAB, "GRAB", 0, "Grab", "Grab UVs"},
{0, NULL, 0, NULL, NULL}};
EnumPropertyItem snap_target_items[] = {
{SCE_SNAP_TARGET_CLOSEST, "CLOSEST", 0, "Closest", "Snap closest point onto target"},
{SCE_SNAP_TARGET_CENTER, "CENTER", 0, "Center", "Snap center onto target"},
@@ -269,9 +281,15 @@ EnumPropertyItem image_color_depth_items[] = {
#include "ED_view3d.h"
#include "ED_mesh.h"
#include "ED_keyframing.h"
#include "ED_image.h"
#include "RE_engine.h"
static void rna_SpaceImageEditor_uv_sculpt_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
{
ED_space_image_uv_sculpt_update(bmain->wm.first, scene->toolsettings);
}
static int rna_Scene_object_bases_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
{
Scene *scene= (Scene*)ptr->data;
@@ -1431,10 +1449,38 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "imapaint");
RNA_def_property_ui_text(prop, "Image Paint", "");
prop= RNA_def_property(srna, "uv_sculpt", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "uvsculpt");
RNA_def_property_ui_text(prop, "UV Sculpt", "");
prop= RNA_def_property(srna, "particle_edit", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "particle");
RNA_def_property_ui_text(prop, "Particle Edit", "");
prop= RNA_def_property(srna, "use_uv_sculpt", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_uv_sculpt", 1);
RNA_def_property_ui_text(prop, "UV Sculpt", "Enable brush for uv sculpting");
RNA_def_property_ui_icon(prop, ICON_TPAINT_HLT, 0);
RNA_def_property_update(prop, NC_SPACE|ND_SPACE_IMAGE, "rna_SpaceImageEditor_uv_sculpt_update");
prop= RNA_def_property(srna, "uv_sculpt_lock_borders", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uv_sculpt_settings", UV_SCULPT_LOCK_BORDERS);
RNA_def_property_ui_text(prop, "Lock Borders", "Disables editing of boundary edges");
prop= RNA_def_property(srna, "uv_sculpt_all_islands", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uv_sculpt_settings", UV_SCULPT_ALL_ISLANDS);
RNA_def_property_ui_text(prop, "Sculpt All Islands", "Brush operates on all islands");
prop= RNA_def_property(srna, "uv_sculpt_tool", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "uv_sculpt_tool");
RNA_def_property_enum_items(prop, uv_sculpt_tool_items);
RNA_def_property_ui_text(prop, "UV Sculpt Tools", "Select Tools for the UV sculpt brushes");
prop= RNA_def_property(srna, "uv_relax_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "uv_relax_method");
RNA_def_property_enum_items(prop, uv_sculpt_relaxation_items);
RNA_def_property_ui_text(prop, "Relaxation Method", "Algorithm used for UV relaxation");
/* Transform */
prop= RNA_def_property(srna, "proportional_edit", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "proportional");
@@ -3844,6 +3890,28 @@ static void rna_def_scene_keying_sets_all(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_update(prop, NC_SCENE|ND_KEYINGSET, NULL);
}
/* Runtime property, used to remember uv indices, used only in UV stitch for now.
*/
static void rna_def_selected_uv_element(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna= RNA_def_struct(brna, "SelectedUvElement", "PropertyGroup");
RNA_def_struct_ui_text(srna, "Selected Uv Element", "");
/* store the index to the UV element selected */
prop= RNA_def_property(srna, "element_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_ui_text(prop, "Element Index", "");
prop= RNA_def_property(srna, "face_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_ui_text(prop, "Face Index", "");
}
void RNA_def_scene(BlenderRNA *brna)
{
StructRNA *srna;
@@ -4177,6 +4245,7 @@ void RNA_def_scene(BlenderRNA *brna)
rna_def_scene_game_data(brna);
rna_def_scene_render_layer(brna);
rna_def_transform_orientation(brna);
rna_def_selected_uv_element(brna);
/* Scene API */
RNA_api_scene(srna);

View File

@@ -289,6 +289,16 @@ static void rna_def_sculpt(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Sculpt_update");
}
static void rna_def_uv_sculpt(BlenderRNA *brna)
{
StructRNA *srna;
srna= RNA_def_struct(brna, "UvSculpt", "Paint");
RNA_def_struct_ui_text(srna, "UV Sculpting", "");
}
/* use for weight paint too */
static void rna_def_vertex_paint(BlenderRNA *brna)
{
@@ -548,6 +558,7 @@ void RNA_def_sculpt_paint(BlenderRNA *brna)
{
rna_def_paint(brna);
rna_def_sculpt(brna);
rna_def_uv_sculpt(brna);
rna_def_vertex_paint(brna);
rna_def_image_paint(brna);
rna_def_particle_edit(brna);

View File

@@ -37,6 +37,7 @@
#include "DNA_userdef_types.h"
#include "DNA_brush_types.h"
#include "DNA_view3d_types.h"
#include "DNA_scene_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -147,6 +148,12 @@ static void rna_userdef_gl_texture_limit_update(Main *bmain, Scene *scene, Point
rna_userdef_update(bmain, scene, ptr);
}
static void rna_userdef_gl_use_16bit_textures(Main *bmain, Scene *scene, PointerRNA *ptr)
{
GPU_free_images();
rna_userdef_update(bmain, scene, ptr);
}
static void rna_userdef_select_mouse_set(PointerRNA *ptr,int value)
{
UserDef *userdef = (UserDef*)ptr->data;
@@ -1623,6 +1630,42 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Scope region background color", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop= RNA_def_property(srna, "preview_stitch_face", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "preview_stitch_face");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Stitch preview face color", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop= RNA_def_property(srna, "preview_stitch_edge", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "preview_stitch_edge");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Stitch preview edge color", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop= RNA_def_property(srna, "preview_stitch_vert", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "preview_stitch_vert");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Stitch preview vertex color", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop= RNA_def_property(srna, "preview_stitch_stitchable", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "preview_stitch_stitchable");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Stitch preview stitchable color", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop= RNA_def_property(srna, "preview_stitch_unstitchable", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "preview_stitch_unstitchable");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Stitch preview unstitchable color", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop= RNA_def_property(srna, "preview_stitch_active", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "preview_stitch_active");
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Stitch preview active island", "");
RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
@@ -2900,6 +2943,11 @@ static void rna_def_userdef_system(BlenderRNA *brna)
"Scale textures for the 3D View (looks nicer but uses more memory and slows image reloading)");
RNA_def_property_update(prop, 0, "rna_userdef_mipmap_update");
prop= RNA_def_property(srna, "use_16bit_textures", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_16bit_textures", 1);
RNA_def_property_ui_text(prop, "16 Bit Float Textures", "Use 16 bit per component texture for float images");
RNA_def_property_update(prop, 0, "rna_userdef_gl_use_16bit_textures");
prop= RNA_def_property(srna, "use_vertex_buffer_objects", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_VBO);
RNA_def_property_ui_text(prop, "VBOs", "Use Vertex Buffer Objects (or Vertex Arrays, if unsupported) for viewport rendering");

View File

@@ -1213,7 +1213,14 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
km = WM_keymap_find_all(C, "Pose", 0, 0);
}
else if (strstr(opname, "SCULPT_OT")) {
switch(CTX_data_mode_enum(C)) {
case OB_MODE_SCULPT:
km = WM_keymap_find_all(C, "Sculpt", 0, 0);
break;
case OB_MODE_EDIT:
km = WM_keymap_find_all(C, "UV Sculpt", 0, 0);
break;
}
}
else if (strstr(opname, "MBALL_OT")) {
km = WM_keymap_find_all(C, "Metaball", 0, 0);

View File

@@ -232,6 +232,8 @@ int ED_space_image_show_paint(struct SpaceImage *sima){return 0;}
void ED_space_image_paint_update(struct wmWindowManager *wm, struct ToolSettings *settings){}
void ED_space_image_set(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit, struct Image *ima){}
struct ImBuf *ED_space_image_buffer(struct SpaceImage *sima){return (struct ImBuf *) NULL;}
void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct ToolSettings *settings){}
void ED_screen_set_scene(struct bContext *C, struct Scene *scene){}
void ED_space_clip_set(struct bContext *C, struct SpaceClip *sc, struct MovieClip *clip){}

View File

@@ -31,11 +31,12 @@
import math
USE_QUICK_RENDER = False
IS_BMESH = hasattr(__import__("bpy").types, "LoopColors")
# -----------------------------------------------------------------------------
# utility funcs
def render_gl(context, filepath, shade):
def ctx_viewport_shade(context, shade):
@@ -61,15 +62,16 @@ def render_gl(context, filepath, shade):
ctx_viewport_shade(context, shade)
#~ # stop to inspect!
#~ if filepath == "test_cube_shell_solidify_subsurf_wp_wire":
#~ assert(0)
#~ else:
#~ return
bpy.ops.render.opengl(write_still=True,
view_context=True)
# stop to inspect!
#~ if filepath == "test_cube_like_subsurf_single_wp_wire":
#~ assert(0)
def render_gl_all_modes(context, obj, filepath=""):
assert(obj != None)
@@ -201,6 +203,10 @@ def defaults_object(obj):
mesh.show_normal_vertex = True
# lame!
if IS_BMESH:
for poly in mesh.polygons:
poly.use_smooth = True
else:
for face in mesh.faces:
face.use_smooth = True
@@ -213,6 +219,18 @@ def defaults_modifier(mod):
# -----------------------------------------------------------------------------
# models (utils)
if IS_BMESH:
def mesh_bmesh_poly_elems(poly, elems):
vert_start = poly.loop_start
vert_total = poly.loop_total
return elems[vert_start:vert_start + vert_total]
def mesh_bmesh_poly_vertices(poly):
return [loop.vertex_index
for loop in mesh_bmesh_poly_elems(poly, poly.id_data.loops)]
def mesh_bounds(mesh):
xmin = ymin = zmin = +100000000.0
xmax = ymax = zmax = -100000000.0
@@ -231,23 +249,67 @@ def mesh_bounds(mesh):
def mesh_uv_add(obj):
uvs = ((0.0, 0.0),
(0.0, 1.0),
(1.0, 1.0),
(1.0, 0.0))
uv_lay = obj.data.uv_textures.new()
if IS_BMESH:
# XXX, odd that we need to do this. until uvs and texface
# are separated we will need to keep it
uv_loops = obj.data.uv_loop_layers[-1]
uv_list = uv_loops.data[:]
for poly in obj.data.polygons:
poly_uvs = mesh_bmesh_poly_elems(poly, uv_list)
for i, c in enumerate(poly_uvs):
c.uv = uvs[i % 4]
else:
for uv in uv_lay.data:
uv.uv1 = 0.0, 0.0
uv.uv2 = 0.0, 1.0
uv.uv3 = 1.0, 1.0
uv.uv4 = 1.0, 0.0
uv.uv1 = uvs[0]
uv.uv2 = uvs[1]
uv.uv3 = uvs[2]
uv.uv4 = uvs[3]
return uv_lay
def mesh_vcol_add(obj, mode=0):
colors = ((0.0, 0.0, 0.0), # black
(1.0, 0.0, 0.0), # red
(0.0, 1.0, 0.0), # green
(0.0, 0.0, 1.0), # blue
(1.0, 1.0, 0.0), # yellow
(0.0, 1.0, 1.0), # cyan
(1.0, 0.0, 1.0), # magenta
(1.0, 1.0, 1.0), # white
)
def colors_get(i):
return colors[i % len(colors)]
vcol_lay = obj.data.vertex_colors.new()
for col in vcol_lay.data:
col.color1 = 1.0, 0.0, 0.0
col.color2 = 0.0, 1.0, 0.0
col.color3 = 0.0, 0.0, 1.0
col.color4 = 0.0, 0.0, 0.0
mesh = obj.data
if IS_BMESH:
col_list = vcol_lay.data[:]
for poly in mesh.polygons:
face_verts = mesh_bmesh_poly_vertices(poly)
poly_cols = mesh_bmesh_poly_elems(poly, col_list)
for i, c in enumerate(poly_cols):
c.color = colors[i % 4]
else:
for i, col in enumerate(vcol_lay.data):
face_verts = mesh.faces[i].vertices
col.color1 = colors_get(face_verts[0])
col.color2 = colors_get(face_verts[1])
col.color3 = colors_get(face_verts[2])
if len(face_verts) == 4:
col.color4 = colors_get(face_verts[3])
return vcol_lay
@@ -371,6 +433,12 @@ def modifier_hook_add(scene, obj, use_vgroup=True):
else:
for v in mesh.vertices:
v.select = False
if IS_BMESH:
face_verts = mesh_bmesh_poly_vertices(mesh.polygons[0])
else:
face_verts = mesh.faces[0].vertices[:]
for i in mesh.faces[0].vertices:
mesh.vertices[i].select = True
@@ -406,7 +474,11 @@ def modifier_build_add(scene, obj):
defaults_modifier(mod)
# ensure we display some faces
if IS_BMESH:
totface = len(obj.data.polygons)
else:
totface = len(obj.data.faces)
mod.frame_start = totface // 2
mod.frame_duration = totface