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

@@ -21,8 +21,8 @@
from . import engine
devices = (
("CPU", "CPU", "Use CPU for rendering"),
("GPU", "GPU Compute", "Use GPU compute device for rendering, configured in user preferences"))
("CPU", "CPU", "Use CPU for rendering"),
("GPU", "GPU Compute", "Use GPU compute device for rendering, configured in user preferences"))
feature_set = (
("SUPPORTED", "Supported", "Only use finished and supported features"),

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

@@ -141,7 +141,7 @@ def rna2xml(fw=print_ln,
return number_to_str(s, subsubvalue_type)
else:
return " ".join([str_recursive(si) for si in s])
array_value = " ".join(str_recursive(v) for v in subvalue_rna)
node_attrs.append("%s=\"%s\"" % (prop, array_value))
@@ -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
@@ -127,7 +128,7 @@ class CLIP_OT_track_to_empty(Operator):
for track in tracking_object.tracks:
if CLIP_track_view_selected(sc, track):
self._link_track(context, clip, tracking_object ,track)
self._link_track(context, clip, tracking_object, track)
return {'FINISHED'}

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

@@ -287,7 +287,7 @@ class RENDER_PT_game_player(RenderButtonsPanel, Panel):
col = row.column()
col.prop(gs, "use_desktop")
col.active = gs.show_fullscreen
col = layout.column()
col.label(text="Quality:")
col.prop(gs, "samples")

View File

@@ -418,9 +418,9 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel):
rd = context.scene.render
layout.active = rd.use_stamp
layout.prop(rd, "stamp_font_size", text="Font Size")
row = layout.row()
row.column().prop(rd, "stamp_foreground", slider=True)
row.column().prop(rd, "stamp_background", slider=True)
@@ -433,7 +433,7 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel):
col.prop(rd, "use_stamp_render_time", text="RenderTime")
col.prop(rd, "use_stamp_frame", text="Frame")
col.prop(rd, "use_stamp_scene", text="Scene")
col = split.column()
col.prop(rd, "use_stamp_camera", text="Camera")
col.prop(rd, "use_stamp_lens", text="Lens")

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")
@@ -371,7 +374,7 @@ class CLIP_PT_objects(Panel):
def draw(self, context):
layout = self.layout
sc = context.space_data
tracking = sc.clip.tracking
@@ -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,7 +52,8 @@ 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.prop(uv, "show_other_objects")
layout.separator()
@@ -146,9 +147,11 @@ 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
layout.separator()
if not context.tool_settings.use_uv_sculpt:
layout.separator()
layout.prop(sima, "use_image_paint")
layout.prop(sima, "use_image_paint")
layout.separator()
class IMAGE_MT_image_invert(Menu):
@@ -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

@@ -46,8 +46,8 @@ void free_text (struct Text *text);
void txt_set_undostate (int u);
int txt_get_undostate (void);
struct Text* add_empty_text (const char *name);
int txt_extended_ascii_as_utf8(char **str);
int reopen_text (struct Text *text);
int txt_extended_ascii_as_utf8(char **str);
int reopen_text (struct Text *text);
struct Text* add_text (const char *file, const char *relpath);
struct Text* copy_text (struct Text *ta);
void unlink_text (struct Main *bmain, struct Text *text);
@@ -60,8 +60,8 @@ void txt_order_cursors (struct Text *text);
int txt_find_string (struct Text *text, const char *findstr, int wrap, int match_case);
int txt_has_sel (struct Text *text);
int txt_get_span (struct TextLine *from, struct TextLine *to);
int txt_utf8_offset_to_index(char *str, int offset);
int txt_utf8_index_to_offset(char *str, int index);
int txt_utf8_offset_to_index(char *str, int offset);
int txt_utf8_index_to_offset(char *str, int index);
void txt_move_up (struct Text *text, short sel);
void txt_move_down (struct Text *text, short sel);
void txt_move_left (struct Text *text, short sel);
@@ -162,8 +162,8 @@ int text_check_whitespace(char ch);
* by 4 character length ID + the text
* block itself + the 4 character length
* ID (repeat) and opcode (repeat)) */
#define UNDO_DBLOCK 027 /* Delete block */
#define UNDO_IBLOCK 030 /* Insert block */
#define UNDO_DBLOCK 027 /* Delete block */
#define UNDO_IBLOCK 030 /* Insert block */
/* Misc */
#define UNDO_SWAP 031 /* Swap cursors */

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

@@ -226,7 +226,7 @@ int txt_extended_ascii_as_utf8(char **str)
while ((*str)[i]) {
if((bad_char= BLI_utf8_invalid_byte(*str+i, length)) == -1)
break;
break;
added++;
i+= bad_char + 1;

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 */
@@ -575,7 +611,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
}
}
/* 3. draw active face stippled */
if(activef) {
@@ -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;
ED_space_image_size(sima, &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,8 +805,8 @@ 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,
float co[2], float penalty[2], NearestHit *hit)
void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em,
float co[2], float penalty[2], NearestHit *hit)
{
BMFace *efa;
BMLoop *l;
@@ -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,12 +832,16 @@ 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;
}
liveHandle = construct_param_handle(scene, em, 0, fillholes, 0, 1);
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,8 +1194,14 @@ 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;
@@ -980,6 +1209,9 @@ static int unwrap_exec(bContext *C, wmOperator *op)
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)
IMB_rect_from_float(ibuf);
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,17 +512,39 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
tpx= texwindx;
tpy= texwindy;
rect= ibuf->rect + texwinsy*ibuf->x + texwinsx;
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;
}
}
else {
/* regular image mode */
bind= &ima->bindcode;
if(*bind==0) {
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,26 +559,57 @@ 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) {
tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
if(use_high_bit_depth) {
float *frectrow, *ftilerectrow;
for (y=0; y<recth; y++) {
rectrow= &rect[y*ibuf->x];
tilerectrow= &tilerect[y*rectw];
memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow));
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++) {
rectrow= &rect[y*ibuf->x];
tilerectrow= &tilerect[y*rectw];
memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow));
}
rect= tilerect;
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);
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;
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 */
@@ -550,12 +617,18 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
glBindTexture( GL_TEXTURE_2D, *bind);
if (!(gpu_get_mipmap() && mipmap)) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
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 {
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
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,23 +770,21 @@ 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");
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,
/* 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;
}
MEM_freeN(buffer);
if(ima->tpageflag & IMA_MIPMAP_COMPLETE)
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
return;
}
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
@@ -717,8 +793,12 @@ 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);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
GL_UNSIGNED_BYTE, ibuf->rect);
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);
glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);

View File

@@ -671,10 +671,20 @@ 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 {
typedef struct TimeMarker {
struct TimeMarker *next, *prev;
int frame;
char name[64];
@@ -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")) {
km = WM_keymap_find_all(C, "Sculpt", 0, 0);
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,8 +203,12 @@ def defaults_object(obj):
mesh.show_normal_vertex = True
# lame!
for face in mesh.faces:
face.use_smooth = True
if IS_BMESH:
for poly in mesh.polygons:
poly.use_smooth = True
else:
for face in mesh.faces:
face.use_smooth = True
def defaults_modifier(mod):
@@ -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()
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
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 = 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
@@ -364,13 +426,19 @@ def modifier_hook_add(scene, obj, use_vgroup=True):
# no nice way to add hooks from py api yet
# assume object mode, hook first face!
mesh = obj.data
if use_vgroup:
for v in mesh.vertices:
v.select = 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
totface = len(obj.data.faces)
if IS_BMESH:
totface = len(obj.data.polygons)
else:
totface = len(obj.data.faces)
mod.frame_start = totface // 2
mod.frame_duration = totface