1
1

Compare commits

...

137 Commits

Author SHA1 Message Date
Phil Gosch
2b1ec9c18f Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2017-09-29 22:52:29 +02:00
Phil Gosch
5cdd4388ff Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2017-09-27 13:29:26 +02:00
Phil Gosch
99c3d1106e Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2017-07-11 19:51:35 +02:00
Phil Gosch
2dae9a1596 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2017-03-18 15:26:08 +01:00
Phil Gosch
eb3dab8553 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2017-03-07 20:14:58 +01:00
Phil Gosch
d49a667707 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2017-01-27 08:58:44 +01:00
Phil Gosch
e65b6321f4 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-12-14 17:43:56 +01:00
Phil Gosch
e3c00a6ead Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-11-04 08:27:46 +01:00
Phil Gosch
50fb0ead39 Code Refactor: Creating utility function for updating boundary hulls 2016-10-31 11:01:01 +01:00
Phil Gosch
5eb53cc607 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-10-31 10:27:36 +01:00
Phil Gosch
c58a276a4f Small fix for binary depth search 2016-10-11 16:48:56 +02:00
Phil Gosch
55e60b3a76 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-10-11 14:29:27 +02:00
Phil Gosch
ea2331a3dc Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-10-10 10:47:40 +02:00
Phil Gosch
50aa491f4e Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-10-04 08:48:37 +02:00
Phil Gosch
f3f2de8d01 First part of solution evaluation rewrite 2016-10-04 08:47:48 +02:00
Phil Gosch
120feb30f7 Wrap uv chart rotation up in a nice utility function 2016-09-05 15:57:19 +02:00
Phil Gosch
1e2f2ce404 Make inner fit polygon work with aspect ratios != 1 2016-09-05 15:54:45 +02:00
Phil Gosch
4c3aed02b9 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-09-05 13:29:21 +02:00
Phil Gosch
1899762962 Fix warnings for unused functions and discarding 'const' 2016-08-23 16:11:19 +02:00
Phil Gosch
3d3e5ae3fd Lots of fixes for warnings 2016-08-23 15:33:54 +02:00
Phil Gosch
7783ab10b9 Compile fix. Also fixed a few "unused variable" warnings 2016-08-23 14:09:27 +02:00
Phil Gosch
969448019e Make convex packing default setting for irregular packing operator for now 2016-08-23 11:32:31 +02:00
Phil Gosch
72edbc46ac WIP packing: concave support for iterative solution search 2016-08-20 00:42:40 +02:00
Phil Gosch
88388b5bca Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-08-19 18:45:28 +02:00
Phil Gosch
f7755d6077 WIP Packing: working concave support.
Functionality is there, still needs optimizations and initial upscaling for best results.
Cleanup commit coming, this will also re-enable iterative computations
2016-08-19 18:42:03 +02:00
Phil Gosch
e8a902d103 WIP packing: continue working on concave boundaries support 2016-08-17 15:51:39 +02:00
Phil Gosch
070ab46267 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-08-16 13:24:40 +02:00
Phil Gosch
74df8db173 Small fix. Also store number of decomposed hulls, handy to have available during later computations 2016-08-16 13:22:42 +02:00
Phil Gosch
b7224e1392 Quick fix for Select Overlapping UVs operator 2016-08-15 18:15:26 +02:00
Phil Gosch
a36a49c4e8 Add new packing to keymap and UV menu 2016-08-15 15:05:55 +02:00
Phil Gosch
3dd291fdb6 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-08-12 17:35:24 +02:00
Phil Gosch
a5bdf2e2e6 WIP Packing: Concave hull decomposition 2016-08-12 17:34:28 +02:00
Phil Gosch
80f71daeb3 WIP packing: initial chart boundary computation 2016-08-11 17:00:58 +02:00
Phil Gosch
c5a2380363 WIP packing: continuing implementation of concave hull support 2016-08-11 12:04:13 +02:00
Phil Gosch
7ad5b81a1c Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-08-11 09:38:15 +02:00
Phil Gosch
45ed0ee455 Added initial "Use concave hulls" option to operator 2016-08-09 01:39:48 +02:00
Phil Gosch
51bfcb7f81 Added point inside triangle check function for concave shape decomposition 2016-08-09 00:15:16 +02:00
Phil Gosch
1b7b90bd8c Small tweak for margin computation 2016-08-09 00:13:43 +02:00
Phil Gosch
245850dc74 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-08-09 00:12:11 +02:00
Phil Gosch
dfa8f25de8 Move flushing uvs including selection tags to own function
This fixes crashes when unwrapping a mesh for the first time
2016-08-08 02:00:32 +02:00
Phil Gosch
f9564ef035 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-08-04 20:12:52 +02:00
Phil Gosch
c06f8ee5c8 Packing: Support for margin 2016-08-04 20:12:08 +02:00
Phil Gosch
2233355b98 Fixed a few annoying bugs, packing solution computation works again now, SA + margin fixes coming with next commits 2016-08-04 10:08:34 +02:00
Phil Gosch
54d1b151e4 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-08-02 14:09:35 +02:00
Phil Gosch
93af992814 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-08-02 14:06:14 +02:00
Phil Gosch
0eea6b1556 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-07-29 14:46:45 +02:00
Phil Gosch
1829199887 Refactor of code, taking into account margin and storing the convex hull
Warning: Intermediate commit, this currently breaks correct packing solution computation
2016-07-29 14:45:46 +02:00
Phil Gosch
d468e30190 Updated Convex Hull data structure 2016-07-29 10:31:19 +02:00
Phil Gosch
59ca7f55bc Added option to run "average islands scale" before packing.
(user request from ba)
2016-07-28 10:14:00 +02:00
Phil Gosch
366bc79e2a Margin computation
Still need to quickly refactor PConvexHull to actually use margins
2016-07-26 11:23:34 +02:00
Phil Gosch
595bb24637 And a quick fix for last commit.
Reminder for myself to double check before commiting!
2016-07-25 15:27:40 +02:00
Phil Gosch
7d69a4f270 Small optimization to last commit (thx nexyon for the hint) 2016-07-25 15:24:31 +02:00
Phil Gosch
6dfd2454d1 Chart placement: Slide possible placement positions along edge of chosen NFP point to include every possible placement solution 2016-07-25 14:05:53 +02:00
Phil Gosch
7979573bdc Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-07-22 17:04:33 +02:00
Phil Gosch
ae9f30ee9a Use #defines for cfr computation and revert to random point sampling for now
Seems like the random approach works better for now (and is bug free), but I keep the code for cfr computation around, will be needed once concave hulls are implemented
This commit also fixes intersections with rotated charts
2016-07-22 17:03:06 +02:00
Phil Gosch
923e9d1758 WIP Collision Free Region computation 2016-07-22 14:13:07 +02:00
Phil Gosch
379a57348b WIP Simulated Annealing
Iterations now only recompute placement of one random chart according to the main reference paper
Also includes stubs for margin computation
2016-07-21 18:32:39 +02:00
Phil Gosch
9015e4f1f8 Added (initial) random rotation for uv islands
This also introduces a new user-controllable operator parameter "rotation steps"
2016-07-20 17:57:05 +02:00
Phil Gosch
d70d5ccf0f WIP Simulated Annealing
Store/Restore last best solution
2016-07-20 01:36:54 +02:00
Phil Gosch
39592039be WIP Simulated Annealing
Stubs for storing the best solution and initial scaling of charts
2016-07-19 19:48:54 +02:00
Phil Gosch
536508f433 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-07-19 11:15:37 +02:00
Phil Gosch
a65eef7e95 WIP simulated annealing
Implemented local stop condition: start Cooling Schedule if more than local_iter_max (currently 50) "frozen state solutions" occur
Forzen state solution: A packing solution with no significant improvement to the current best solution
2016-07-19 11:14:24 +02:00
Phil Gosch
842ad16b70 Fix for overlapping UV computation 2016-07-19 10:18:26 +02:00
9e5635b8a2 Compilefix for conflicting types 2016-07-18 19:46:59 +02:00
Phil Gosch
95e2685020 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-07-18 17:29:19 +02:00
Phil Gosch
97c2b665ad WIP: Simulated Annealing
Basics of the simulated annealing approach to iteratively find the optimal packing solution
2016-07-18 17:28:13 +02:00
Phil Gosch
2c47c627b9 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-07-16 14:08:36 +02:00
Phil Gosch
22327e57d7 Reworked binary depth search for non fitting charts
This produces much better results now. Still potential for optimization
2016-07-16 14:07:09 +02:00
Phil Gosch
783e3fe564 Fix for compile error 2016-07-15 15:20:09 +02:00
Phil Gosch
bd9978519b Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-07-15 13:17:45 +02:00
Phil Gosch
2b504a9335 Cleanup commit 2016-07-15 13:16:29 +02:00
Phil Gosch
d0cfbc44fe Changes/bugfixes for NFP reference vertex assignment
This commit makes all of my testcases work!

It also makes the ref vert offset code obsolete, but I'll commit it anyway (commented out) in case I may need it later
2016-07-15 12:36:12 +02:00
Phil Gosch
8bccac7ce5 Alternative/more robust way to offset/place NFP
This fixes some of my testfiles
2016-07-14 17:16:43 +02:00
Phil Gosch
465e381827 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-07-14 12:04:23 +02:00
Phil Gosch
e9986e9140 Refactoring of NFP code
This fixes some bugs, memory leaks and crashes

Note: Added IFP corners as possible placement positions for now, mainly for testing purposes
2016-07-14 12:03:38 +02:00
Phil Gosch
a2f4d70de9 bugfix for NFP computation
Also introduces some shiny new debug prints.
2016-07-11 17:22:34 +02:00
Phil Gosch
c0b420beb8 Prevent infinite loops and make "scale around origin" it's own function 2016-07-11 12:06:36 +02:00
Phil Gosch
177848e73c Depth limited binary search to determine the scale factor of items which don't fit 2016-07-11 10:53:32 +02:00
Phil Gosch
4c2ead486b Added hack-ish check for point being inside other NFP until union algorithm is implemented 2016-07-09 23:56:41 +02:00
Phil Gosch
a9280bea45 Added check for point being inside IFP, also fixed a bug with rng 2016-07-09 12:16:04 +02:00
Phil Gosch
6380451f4b Bugfix for No Fit Polygon placement 2016-07-09 11:12:06 +02:00
Phil Gosch
0869346c78 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-07-08 16:54:54 +02:00
Phil Gosch
2e690c3f18 WIP: Packing computation
Refactored code, bugfixes and cleanup: Moved area sorting outside NFP computation so it's only done once, actually assign area to charts, deleted commented out code
Use random NFP for placements, still misses checks for being inside IFP or other NFPs

While NFP computation works, there's still a bug with reference vert offset of NFP which causes incorrect placement
2016-07-08 16:52:55 +02:00
Phil Gosch
dcc8560102 WIP: Packing computation
More functionality and hooking up of functions
Contains even more debug prints and commented code
2016-07-07 17:40:54 +02:00
Phil Gosch
3986f88873 Inner Fit Polygon used for placing charts
Hooked up the IFP to packing solution computation, fixed some bugs and tested it using bottom-left heuristic.
If you start the irregular packing operator now all UV islands are placed in the bottom left corner of the UV space.

Still unoptimized and containing lots of debug prints!
2016-07-06 21:06:32 +02:00
Phil Gosch
e017975225 Sort UV islands by area for packing (largest->smallest) 2016-07-06 11:49:49 +02:00
Phil Gosch
cdde7cf132 Outline of packing solution computation
Uses placeholder functions for now, implementing the individual parts is next
2016-07-05 22:37:55 +02:00
Phil Gosch
e456ed0708 Find and store reference vertex in PConvexHull
Ref vert is the vertex with the highest Y value, lowes y value if winding direction is reversed (ccw)

Also includes minor refactor of a few related functions
2016-07-05 17:56:47 +02:00
Phil Gosch
f69163f093 Remove PVert* array from PNoFitPolygon
Vertex positions are saved as a separate array, save memory
2016-07-05 13:02:18 +02:00
Phil Gosch
c80c28a4da Inner fit polygon computation
Could be cleaner by having ConvexHull store relative bounds width/height, but should do for now
2016-07-05 12:57:28 +02:00
Phil Gosch
b5f330378c Fixing a typo which caused compile error 2016-07-05 10:06:22 +02:00
Phil Gosch
d3f89408c7 Select overlapping UVs operator
Found via Select->Select all by trait->Overlapping UVs menu entry, selects all UV charts which overlap/intersect
Operator has an "Extend" option to extend the current selection.

I also turned rectangle/bounds intersection test into a seperate function which can be reused
2016-07-04 14:54:52 +02:00
Phil Gosch
36dc52c4d8 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-07-03 15:19:39 +02:00
Phil Gosch
d0e5c78095 Packing: No Fit Polygon computation
Still contains lots of debug prints and unoptimized code, but functionality is there
2016-07-03 15:15:33 +02:00
Phil Gosch
e9bd9d5efe Intermediate commit of no-fit-polygon implementation, more to come
Contains lot's of debug prints
2016-06-30 12:17:09 +02:00
Phil Gosch
9519afdec7 Working intersection test
Wrote my own intersection function for line segments, includes taking care of float precision issues (especially important when checking for parallel lines)
2016-06-28 13:05:48 +02:00
Phil Gosch
0838ca63d3 Intersection test for charts
Seems like I need to write my own line intersection check...
2016-06-27 16:59:37 +02:00
Phil Gosch
4eca61a627 Added convex hull to chart data structures
The convex hull is part of the new "PChartIrregularPack" union which will hold useful data during packing

I also re-enabled the line intersection code that was already there, I have to investigate if it is fine to use it or if I need to write my own
2016-06-27 14:37:21 +02:00
Phil Gosch
2c0fbe86fd Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-06-24 16:45:13 +02:00
Phil Gosch
aac346662d Some groundwork for packing improvements
Implemented a modal operator for packing, actual implementation of the algorithm left as "ToDo"
2016-06-22 18:29:03 +02:00
Phil Gosch
6a9b37499a Added temoprary Debug/Test UV operator
This is very handy for testing isolated functions which are needed with packing
Will be removed once it's not needed anymore
2016-06-21 15:34:28 +02:00
Phil Gosch
1e13733b44 Implemented a function to compute the area used by UV charts
This will be handy when calculating the used/wasted space during packing
2016-06-21 15:07:15 +02:00
Phil Gosch
ec48ea9141 Very minor wording change for menu entries 2016-06-21 01:20:19 +02:00
Phil Gosch
a6bfa1c306 Add menu entries for de/select mesh operators 2016-06-20 16:36:56 +02:00
Phil Gosch
3a4a5cc985 Add back the old hide/reveal functionality as seperate operators.
They can be accessed with Ctrl+H for "deselect 3d mesh" (Shift for unselected) and Ctrl+Alt+H for "select 3D mesh".

ToDo: Decide on final naming together with stakeholder artists
2016-06-20 11:17:59 +02:00
Phil Gosch
a671816e57 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-06-19 19:32:29 +02:00
Phil Gosch
22a8a72e6b Fix for recent commits: Fix an error, silence warnings, clean up unused code 2016-06-15 14:32:27 +02:00
Phil Gosch
28db90f9a0 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-06-15 11:47:22 +02:00
Phil Gosch
11501865b8 Reveal hidden UVs for all unwrap modes 2016-06-15 11:23:30 +02:00
Phil Gosch
39e21b2a98 Make unwrap ops reveal hidden UVs since they're taken into account anyway 2016-06-15 10:41:56 +02:00
Phil Gosch
f9185c646f Proper Hiding: Make selection operators ignore hidden elements 2016-06-14 15:53:16 +02:00
Phil Gosch
8650a733fc Implemented "real" hiding of UV elements
Previously it wasn't possible to hide elements without altering the BMesh selection state

ToDo: Make UV operators ignore hidden elements
2016-06-14 11:32:29 +02:00
Phil Gosch
61c39a6ed4 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-06-13 14:28:24 +02:00
Phil Gosch
a9bf839f22 Clean-Up commit
* Remove debug prints
* Remove Warnings
* Correct code style (whitespace, formating, line length, etc.) according to check_style_c.py
2016-06-11 00:30:35 +02:00
Phil Gosch
c8c62bb8b6 Fix for missing parameter 2016-06-10 16:00:41 +02:00
Phil Gosch
106293c16d Made incremental snapping intervalls smaller for UV editor
Before the intervall was set to 0.125 which effectively resulted in 8 positions across the UV space (per axis).
I halved that value, holding shift enables an even finer movement.
2016-06-10 14:12:48 +02:00
Phil Gosch
a2bb48080d Added "Scale to bounds" operator to scale selected islands to UV boundaries
Options:
* Keep aspect ratio: If checked the aspect ratio of the selected uv islands is preserved
* Individual: If checked the individual uv islands are all scaled to fit the bounds, otherwise the selections are scaled as a whole

Note: Menu locations/shortcuts are to be discussed with users and not to be seen as final
2016-06-09 16:50:49 +02:00
Phil Gosch
2f15dcfa55 Quick fix for missed parameter 2016-06-09 16:20:24 +02:00
Phil Gosch
4290d75d19 Changed the row of bool arguments for construct_param_handle() to an int flag argument
While doing this I added an "all_faces" check to include all faces in parametrizer even if implicit argument is set (needed for shortest path computation).
2016-06-08 15:57:00 +02:00
Phil Gosch
79de3b88f9 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-06-07 18:20:12 +02:00
Phil Gosch
2d7ce3a69d Added "Topological distance" option to Select Shortest Path operator
Similar to the editmesh operator: "Find the minimum number of steps, ignoring spatial distance"
2016-06-07 14:37:26 +02:00
Phil Gosch
76036cd130 Fix for "face stepping" behaviour of path calculation
Since parametrizer operates on triangles, diagonal edges of quads have to be tagged and not taken into calculation of shortest path
2016-06-07 14:01:30 +02:00
Phil Gosch
a9d0ba4dc2 Rename UV_OT_shortest_path to UV_OT_select_shortest_path
Should have been commited with the UI menu entry commit...
2016-06-06 19:57:25 +02:00
Phil Gosch
0ca6fe7e52 Adding PEDGE_DIAG tag to diagonal edges of quads (parametrizer data structures are triangle only) 2016-06-06 19:56:02 +02:00
Phil Gosch
d755e8323d WIP: Select Shortest Path: Add UI menu entry for operator
UV Editor: Select -> Select Shortest Path
2016-06-06 19:39:53 +02:00
Phil Gosch
4e5693761f WIP: Select Shortest Path: Correctly set selection tags for edges of found verts of path 2016-06-04 18:43:46 +02:00
Phil Gosch
087ede5762 WIP: Select Shortest Path: Fixes to path computation
Also contains a few debug prints which are handy for now. Needs a cleanup commit later anyway
2016-06-04 17:55:00 +02:00
Phil Gosch
b592ca632f Fixing memory leak in path selection code 2016-06-03 13:42:59 +02:00
Phil Gosch
eed6abb27d WIP: Select Shortest Path: Directly set the MLOOPUV_*SEL selection tags
To get the edges tagged for selection from the parametrizer data structures we need to directly set the flag of MLoopUV
2016-06-03 11:28:58 +02:00
Phil Gosch
a732f96919 Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-06-02 22:22:33 +02:00
Phil Gosch
c67be0b14f Wip: Select Shortest Path: Tagging of found path edges for selection
Selection flags of MLOOPUV should be set in p_flush_uvs(), needs a closer look
2016-06-02 21:39:36 +02:00
Phil Gosch
ecc37c77f8 WIP: Select shortest path - Computing the shortest path using regular Dijkstra algorithm 2016-06-02 11:44:55 +02:00
Phil Gosch
b7b04095c0 WIP: Select shortest path - Validate selection
Validation of the current selection, makes sure 2 matching elements are selected for path computation
2016-06-01 10:24:46 +02:00
Phil Gosch
2829ab799f Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools 2016-05-25 13:38:51 +02:00
Phil Gosch
d2d0f8a051 Fix for bug in optional packing with unwrap operator
Center and scale were off if aspect ratio != 1
2016-05-25 11:16:41 +02:00
Phil Gosch
ce1670be25 WIP: Added "select shortest path" operator for UVs
Main functionality still missing, calls mesh-tool for selecting shortest path if Sync Selection is checked
2016-05-24 16:27:42 +02:00
Phil Gosch
afa59d100a Added "Pack islands" option to Unwrap operator, to give artists the possibility to not automatically pack after unwrapping 2016-05-23 14:25:44 +02:00
17 changed files with 3121 additions and 112 deletions

View File

@@ -217,6 +217,8 @@ def extend(obj, operator, EXTEND_MODE):
def main(context, operator):
obj = context.active_object
bpy.ops.uv.reveal()
extend(obj, operator, operator.properties.mode)
@@ -252,4 +254,4 @@ class FollowActiveQuads(Operator):
classes = (
FollowActiveQuads,
)
)

View File

@@ -557,7 +557,9 @@ def lightmap_uvpack(meshes,
def unwrap(operator, context, **kwargs):
is_editmode = (context.object.mode == 'EDIT')
if is_editmode:
bpy.ops.uv.reveal()
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
PREF_ACT_ONLY = kwargs.pop("PREF_ACT_ONLY")
@@ -672,4 +674,4 @@ class LightMapPack(Operator):
classes = (
LightMapPack,
)
)

View File

@@ -750,6 +750,7 @@ def main(context,
is_editmode = (context.active_object.mode == 'EDIT')
if is_editmode:
bpy.ops.uv.reveal()
obList = [ob for ob in [context.active_object] if ob and ob.type == 'MESH']
else:
obList = [ob for ob in context.selected_editable_objects if ob and ob.type == 'MESH']

View File

@@ -130,6 +130,12 @@ class IMAGE_MT_view(Menu):
layout.operator("screen.screen_full_area")
layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
class IMAGE_MT_uvs_select_by_trait(Menu):
bl_label = "Select All by Trait"
def draw(self, context):
layout = self.layout
layout.operator("uv.select_overlapping")
class IMAGE_MT_select(Menu):
bl_label = "Select"
@@ -150,7 +156,10 @@ class IMAGE_MT_select(Menu):
layout.operator("uv.select_pinned")
layout.operator("uv.select_linked").extend = False
layout.operator("uv.select_shortest_path")
layout.separator()
layout.menu("IMAGE_MT_uvs_select_by_trait")
layout.separator()
layout.operator("uv.select_less", text="Less")
@@ -259,6 +268,16 @@ class IMAGE_MT_uvs_showhide(Menu):
layout.operator("uv.hide", text="Hide Selected").unselected = False
layout.operator("uv.hide", text="Hide Unselected").unselected = True
class IMAGE_MT_uvs_deselect_mesh(Menu):
bl_label = "De/Select 3D Mesh"
def draw(self, context):
layout = self.layout
layout.operator("uv.select_mesh")
layout.operator("uv.deselect_mesh", text="Deselect 3D Mesh (Selected)").unselected = False
layout.operator("uv.deselect_mesh", text="Deselect 3D Mesh (Unselected)").unselected = True
class IMAGE_MT_uvs_proportional(Menu):
bl_label = "Proportional Editing"
@@ -357,6 +376,7 @@ class IMAGE_MT_uvs(Menu):
layout.separator()
layout.operator("uv.irregular_pack_islands")
layout.operator("uv.pack_islands")
layout.operator("uv.average_islands_scale")
layout.operator("uv.minimize_stretch")
@@ -365,6 +385,7 @@ class IMAGE_MT_uvs(Menu):
layout.operator("uv.mark_seam", text="Clear Seam").clear = True
layout.operator("uv.seams_from_islands")
layout.operator("mesh.faces_mirror_uv")
layout.operator("uv.scale_to_bounds")
layout.separator()
@@ -380,6 +401,9 @@ class IMAGE_MT_uvs(Menu):
layout.separator()
layout.menu("IMAGE_MT_uvs_showhide")
layout.menu("IMAGE_MT_uvs_deselect_mesh")
class IMAGE_MT_uvs_select_mode(Menu):

View File

@@ -401,6 +401,8 @@ void accumulate_vertex_normals_poly(
float **vertnos, const float polyno[3],
const float **vertcos, float vdiffs[][3], const int nverts);
void edge_normal_v2_v2v2(float r[2], const float a[2], const float b[2], const bool left);
/********************************* Tangents **********************************/
void tangent_from_uv(

View File

@@ -4014,6 +4014,23 @@ void accumulate_vertex_normals_poly(float **vertnos, const float polyno[3],
}
}
/* Calculates the 2d normal for an edge ab.
* if left is true calculates the left normal (viewed in winding direction) */
void edge_normal_v2_v2v2(float r[2], const float a[2], const float b[2], const bool left)
{
float dx = b[0] - a[0];
float dy = b[1] - a[1];
if (left) {
r[0] = -dy;
r[1] = dx;
}
else {
r[0] = dy;
r[1] = -dx;
}
}
/********************************* Tangents **********************************/
void tangent_from_uv(

View File

@@ -128,6 +128,9 @@ void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag);
bool BMBVH_EdgeVisible(struct BMBVHTree *tree, struct BMEdge *e,
struct ARegion *ar, struct View3D *v3d, struct Object *obedit);
/* editmesh_path.c*/
int EDBM_shortest_path_select(struct bContext *C, struct wmOperator *op);
/* editmesh_select.c */
void EDBM_select_mirrored(
struct BMEditMesh *em, const int axis, const bool extend,

View File

@@ -59,6 +59,8 @@ void ED_object_assign_active_image(struct Main *bmain, struct Object *ob, int ma
bool ED_uvedit_test(struct Object *obedit);
void ED_uvedit_reveal(struct BMEditMesh *em);
/* visibility and selection */
bool uvedit_face_visible_test(struct Scene *scene, struct Image *ima, struct BMFace *efa, struct MTexPoly *tf);
bool uvedit_face_select_test(struct Scene *scene, struct BMFace *efa,
@@ -106,6 +108,14 @@ void ED_uvedit_unwrap_cube_project(struct Object *ob, struct BMesh *bm, float cu
/* single call up unwrap using scene settings, used for edge tag unwrapping */
void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel);
/* select by trait */
void ED_uvedit_overlapping_select(struct Scene *scene, struct Object *ob, struct BMesh *bm, const bool extend);
/* select shortest path */
bool ED_uvedit_shortest_path_select(struct Scene *scene, struct Object *ob, struct BMesh *bm, bool topo_dist);
/* scale to bounds */
void ED_uvedit_scale_to_bounds(struct Scene *scene, struct Object *ob, struct BMesh *bm);
/* uvedit_draw.c */
void ED_image_draw_cursor(struct ARegion *ar, const float cursor[2]);

View File

@@ -779,6 +779,11 @@ static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op)
}
}
int EDBM_shortest_path_select(struct bContext *C, struct wmOperator *op)
{
return edbm_shortest_path_select_exec(C, op);
}
void MESH_OT_shortest_path_select(wmOperatorType *ot)
{
/* identifiers */

View File

@@ -222,7 +222,9 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
glBegin(GL_POLYGON);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
if (!(luv->flag & MLOOPUV_HIDDEN)) {
glVertex2fv(luv->uv);
}
}
glEnd();
}
@@ -260,7 +262,9 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
glBegin(GL_POLYGON);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
if (!(luv->flag & MLOOPUV_HIDDEN)) {
glVertex2fv(luv->uv);
}
}
glEnd();
}
@@ -323,10 +327,12 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
glBegin(GL_POLYGON);
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
a = fabsf(uvang[i] - ang[i]) / (float)M_PI;
weight_to_rgb(col, 1.0f - pow2f(1.0f - a));
glColor3fv(col);
glVertex2fv(luv->uv);
if (!(luv->flag & MLOOPUV_HIDDEN)) {
a = fabsf(uvang[i] - ang[i]) / (float)M_PI;
weight_to_rgb(col, 1.0f - pow2f(1.0f - a));
glColor3fv(col);
glVertex2fv(luv->uv);
}
}
glEnd();
}
@@ -359,7 +365,9 @@ static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset)
glBegin(GL_LINE_LOOP);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
if (!(luv->flag & MLOOPUV_HIDDEN)) {
glVertex2fv(luv->uv);
}
}
glEnd();
}
@@ -372,7 +380,7 @@ static void draw_uvs_lineloop_mpoly(Mesh *me, MPoly *mpoly)
glBegin(GL_LINE_LOOP);
mloopuv = &me->mloopuv[mpoly->loopstart];
for (i = mpoly->totloop; i != 0; i--, mloopuv++) {
glVertex2fv(mloopuv->uv);
glVertex2fv(mloopuv->uv); /* We don't check MLOOPUV_HIDDEN here since we always want to see other UVs */
}
glEnd();
}
@@ -537,7 +545,9 @@ static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const i
unsigned int j;
for (j = 0; j < 3; j++) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(em->looptris[i][j], cd_loop_uv_offset);
glVertex2fv(luv->uv);
if (!(luv->flag & MLOOPUV_HIDDEN)) {
glVertex2fv(luv->uv);
}
}
i++;
} while (i != em->tottri && (f == em->looptris[i][0]->f));
@@ -813,7 +823,9 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2);
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
if (!(luv->flag & MLOOPUV_HIDDEN)) {
glVertex2fv(luv->uv);
}
}
glEnd();
}
@@ -831,9 +843,13 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
lastsel = sel;
}
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
glVertex2fv(luv->uv);
if (!(luv->flag & MLOOPUV_HIDDEN)) {
glVertex2fv(luv->uv);
}
luv = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
glVertex2fv(luv->uv);
if (!(luv->flag & MLOOPUV_HIDDEN)) {
glVertex2fv(luv->uv);
}
}
glEnd();
}
@@ -874,9 +890,13 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
uv_poly_center(efa, cent, cd_loop_uv_offset);
glVertex2fv(cent);
if (uv_poly_visible(efa, cd_loop_uv_offset)) {
uv_poly_center(efa, cent, cd_loop_uv_offset);
glVertex2fv(cent);
}
}
}
@@ -887,9 +907,13 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
uv_poly_center(efa, cent, cd_loop_uv_offset);
glVertex2fv(cent);
if (uv_poly_visible(efa, cd_loop_uv_offset)) {
uv_poly_center(efa, cent, cd_loop_uv_offset);
glVertex2fv(cent);
}
}
}
@@ -911,7 +935,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (!uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
if (!uvedit_uv_select_test(scene, l, cd_loop_uv_offset) && !(luv->flag & MLOOPUV_HIDDEN))
glVertex2fv(luv->uv);
}
}
@@ -930,7 +954,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (luv->flag & MLOOPUV_PINNED)
if (luv->flag & MLOOPUV_PINNED && !(luv->flag & MLOOPUV_HIDDEN))
glVertex2fv(luv->uv);
}
}
@@ -948,7 +972,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset) && !(luv->flag & MLOOPUV_HIDDEN))
glVertex2fv(luv->uv);
}
}

View File

@@ -48,6 +48,7 @@ bool uvedit_face_visible_nolocal(struct Scene *scene, struct BMFace *efa);
/* geometric utilities */
void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len);
void uv_poly_center(struct BMFace *f, float r_cent[2], const int cd_loop_uv_offset);
bool uv_poly_visible(struct BMFace *f, const int cd_loop_uv_offset);
/* find nearest */
@@ -59,6 +60,14 @@ typedef struct NearestHit {
int lindex; /* index of loop within face */
} NearestHit;
enum {
HANDLE_IMPLICIT = (1 << 0),
HANDLE_FILL = (1 << 1),
HANDLE_SELECTED = (1 << 2),
HANDLE_CORRECT_ASPECT = (1 << 3),
HANDLE_ALL_FACES = (1 << 4)
};
void uv_find_nearest_vert(struct Scene *scene, struct Image *ima, struct BMEditMesh *em,
const float co[2], const float penalty[2], struct NearestHit *hit);
void uv_find_nearest_edge(struct Scene *scene, struct Image *ima, struct BMEditMesh *em,
@@ -76,9 +85,13 @@ void UV_OT_cylinder_project(struct wmOperatorType *ot);
void UV_OT_project_from_view(struct wmOperatorType *ot);
void UV_OT_minimize_stretch(struct wmOperatorType *ot);
void UV_OT_pack_islands(struct wmOperatorType *ot);
void UV_OT_irregular_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);
/* XXX (SaphireS): Remove */
void UV_OT_test(struct wmOperatorType *ot);
#endif /* __UVEDIT_INTERN_H__ */

View File

@@ -407,7 +407,9 @@ bool uvedit_face_select_enable(Scene *scene, BMEditMesh *em, BMFace *efa, const
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
if (!(luv->flag & MLOOPUV_HIDDEN)) {
luv->flag |= MLOOPUV_VERTSEL;
}
}
return true;
@@ -505,8 +507,12 @@ void uvedit_edge_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l, const bo
luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
luv1->flag |= MLOOPUV_VERTSEL;
luv2->flag |= MLOOPUV_VERTSEL;
if (!(luv1->flag & MLOOPUV_HIDDEN)) {
luv1->flag |= MLOOPUV_VERTSEL;
}
if (!(luv2->flag & MLOOPUV_HIDDEN)) {
luv2->flag |= MLOOPUV_VERTSEL;
}
}
}
@@ -582,7 +588,9 @@ void uvedit_uv_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l,
}
else {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
if (!(luv->flag & MLOOPUV_HIDDEN)) {
luv->flag |= MLOOPUV_VERTSEL;
}
}
}
@@ -631,6 +639,24 @@ void uv_poly_center(BMFace *f, float r_cent[2], const int cd_loop_uv_offset)
mul_v2_fl(r_cent, 1.0f / (float)f->len);
}
bool uv_poly_visible(BMFace *f, const int cd_loop_uv_offset)
{
BMLoop *l;
MLoopUV *luv;
BMIter liter;
bool visible = false;
BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (!(luv->flag & MLOOPUV_HIDDEN)) {
visible = true;
break;
}
}
return visible;
}
void uv_poly_copy_aspect(float uv_orig[][2], float uv[][2], float aspx, float aspy, int len)
{
int i;
@@ -1477,6 +1503,246 @@ static void UV_OT_select_less(wmOperatorType *ot)
ot->poll = ED_operator_uvedit_space_image;
}
/*********************** shortest path ***********************/
static int uv_shortest_path_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
Image *ima = CTX_data_edit_image(C);
ToolSettings *ts = scene->toolsettings;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
BMFace *efa;
BMEdge *e;
BMIter iter, liter;
BMLoop *l;
MLoopUV *luv_src = NULL, *luv_dst = NULL;
BMElem *elem_src = NULL, *elem_dst = NULL;
int elem_sel = 0;
const bool topological_distance = RNA_boolean_get(op->ptr, "topological_distance");
if (ts->uv_flag & UV_SYNC_SELECTION) {
return EDBM_shortest_path_select(C, op);
}
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
/* -------- Check for 2 selected elements of same type on the same UV island ---------- */
/* Note: Only vertex path computation implemented for now, but Edge/Face checks already there*/
if (ts->uv_selectmode & UV_SELECT_FACE) {
/* clear tags */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
}
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (uvedit_face_visible_test(scene, ima, efa, tf)) {
if (uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) {
elem_sel++;
if (elem_src == NULL) {
elem_src = (BMElem *)efa;
}
else if ((elem_dst == NULL)) {
elem_dst = (BMElem *)efa;
}
}
}
}
}
else if (ts->uv_selectmode & UV_SELECT_EDGE) {
/* clear tags */
BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
BM_elem_flag_disable(e, BM_ELEM_TAG);
}
BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
if (uvedit_edge_select_test(scene, e->l, cd_loop_uv_offset)) {
elem_sel++;
if (elem_src == NULL) {
elem_src = (BMElem *)e;
}
else if ((elem_dst == NULL)) {
elem_dst = (BMElem *)e;
}
}
}
}
else if (ts->uv_selectmode & UV_SELECT_VERTEX) {
/* clear tags */
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_elem_flag_disable(l, BM_ELEM_TAG);
}
}
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (uvedit_face_visible_test(scene, ima, efa, tf)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if ((luv->flag & MLOOPUV_VERTSEL) != 0) {
if (luv_src == NULL) {
luv_src = luv;
elem_sel++;
}
else if ((luv_dst == NULL) && (!compare_v2v2(luv->uv, luv_src->uv, 0.000003f))) {
luv_dst = luv;
elem_sel++;
}
else if ((!compare_v2v2(luv->uv, luv_src->uv, 0.000003f)) &&
(!compare_v2v2(luv->uv, luv_dst->uv, 0.000003f))) {
elem_sel++;
}
}
}
}
}
}
if (elem_sel != 2 || !(ts->uv_selectmode & UV_SELECT_VERTEX)) {
/* Not exactly 2 elements of same typ selected */
BKE_report(op->reports, RPT_WARNING,
"Path selection requires exactly two vertices of the same island to be selected");
return OPERATOR_CANCELLED;
}
/* -------- Now select shortest path between the 2 found elements ---------- */
if (ED_uvedit_shortest_path_select(scene, obedit, bm, topological_distance)) {
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
}
else {
/* No path found because the selected elements aren't part of the same uv island */
BKE_report(op->reports, RPT_WARNING,
"Path selection requires exactly two vertices of the same island to be selected");
return OPERATOR_CANCELLED;
}
}
static void UV_OT_select_shortest_path(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Select Shortest Vertex Path";
ot->description = "Select the shortest path between the current selected vertices";
ot->idname = "UV_OT_select_shortest_path";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* api callbacks */
ot->exec = uv_shortest_path_exec;
ot->poll = ED_operator_uvedit;
/* properties */
RNA_def_boolean(ot->srna, "topological_distance", 0, "Topological Distance",
"Find the minimum number of steps, ignoring spatial distance");
}
/* ******************** scale to bounds operator **************** */
static int uv_scale_to_bounds_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
Image *ima = CTX_data_edit_image(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MTexPoly *tf;
float dx, dy, min[2], max[2];
const bool keep_aspect = RNA_boolean_get(op->ptr, "keep_aspect_ratio");
const bool individual = RNA_boolean_get(op->ptr, "individual_islands");
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
if (individual) {
ED_uvedit_scale_to_bounds(scene, obedit, bm);
return OPERATOR_FINISHED;
}
INIT_MINMAX2(min, max);
BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf) || !uvedit_face_select_test(scene, efa, cd_loop_uv_offset))
continue;
BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
minmax_v2v2_v2(min, max, luv->uv);
}
}
/* rescale UV to be in 1/1 */
dx = (max[0] - min[0]);
dy = (max[1] - min[1]);
if (dx > 0.0f)
dx = 1.0f / dx;
if (dy > 0.0f)
dy = 1.0f / dy;
if (keep_aspect) {
if (dx >= dy) dx = dy;
else if (dy > dx) dy = dx;
}
BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) {
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf) || !uvedit_face_select_test(scene, efa, cd_loop_uv_offset))
continue;
BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->uv[0] = (luv->uv[0] - min[0]) * dx;
luv->uv[1] = (luv->uv[1] - min[1]) * dy;
}
}
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
}
static void UV_OT_scale_to_bounds(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Scale To Bounds";
ot->description = "Scale the selection to fit UV boundaries";
ot->idname = "UV_OT_scale_to_bounds";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* api callbacks */
ot->exec = uv_scale_to_bounds_exec;
ot->poll = ED_operator_uvedit;
/* properties */
RNA_def_boolean(ot->srna, "keep_aspect_ratio", 1, "Keep Aspect Ratio", "Keep the current aspect ratio of the selection");
RNA_def_boolean(ot->srna, "individual_islands", 0, "Individual", "Scale individual islands or the selection as a whole");
}
/* ******************** align operator **************** */
static void uv_weld_align(bContext *C, int tool)
@@ -1990,13 +2256,19 @@ static void uv_select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int
switch (action) {
case SEL_SELECT:
luv->flag |= MLOOPUV_VERTSEL;
if (!(luv->flag & MLOOPUV_HIDDEN)) { /* Skip hidden loops */
luv->flag |= MLOOPUV_VERTSEL;
}
break;
case SEL_DESELECT:
luv->flag &= ~MLOOPUV_VERTSEL;
if (!(luv->flag & MLOOPUV_HIDDEN)) {
luv->flag &= ~MLOOPUV_VERTSEL;
}
break;
case SEL_INVERT:
luv->flag ^= MLOOPUV_VERTSEL;
if (!(luv->flag & MLOOPUV_HIDDEN)) {
luv->flag ^= MLOOPUV_VERTSEL;
}
break;
}
}
@@ -3628,13 +3900,138 @@ static void UV_OT_select_pinned(wmOperatorType *ot)
/********************** hide operator *********************/
static int uv_hide_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C);
Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
MTexPoly *tf;
const bool swap = RNA_boolean_get(op->ptr, "unselected");
Image *ima = sima ? sima->image : NULL;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
if (ts->uv_flag & UV_SYNC_SELECTION) {
EDBM_mesh_hide(em, swap);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf)) {
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if ((luv->flag & MLOOPUV_VERTSEL && !swap) || (!(luv->flag & MLOOPUV_VERTSEL) && swap)) {
luv->flag |= MLOOPUV_HIDDEN;
luv->flag &= ~MLOOPUV_VERTSEL; /* Deselect after hiding to avoid unwanted behaviour */
}
}
}
BM_select_history_validate(em->bm);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
}
#undef UV_SEL_TEST
static void UV_OT_hide(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Hide Selected";
ot->description = "Hide (un)selected UV vertices";
ot->idname = "UV_OT_hide";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* api callbacks */
ot->exec = uv_hide_exec;
ot->poll = ED_operator_uvmap;
/* props */
RNA_def_boolean(ot->srna, "unselected", 0, "Hide Unselected", "Hide unselected rather than selected");
}
/****************** reveal operator ******************/
void ED_uvedit_reveal(BMEditMesh *em)
{
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag &= ~MLOOPUV_HIDDEN;
}
}
}
}
static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
/* call the mesh function if we are in mesh sync sel */
if (ts->uv_flag & UV_SYNC_SELECTION) {
EDBM_mesh_reveal(em);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
}
ED_uvedit_reveal(em);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
}
static void UV_OT_reveal(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Reveal Hidden";
ot->description = "Reveal all hidden UV vertices";
ot->idname = "UV_OT_reveal";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* api callbacks */
ot->exec = uv_reveal_exec;
ot->poll = ED_operator_uvmap;
}
/********************** Deselect Mesh operator *********************/
/* check if we are selected or unselected based on 'bool_test' arg,
* needed for select swap support */
* needed for select swap support */
#define UV_SEL_TEST(luv, bool_test) ((((luv)->flag & MLOOPUV_VERTSEL) == MLOOPUV_VERTSEL) == bool_test)
/* is every UV vert selected or unselected depending on bool_test */
static bool bm_face_is_all_uv_sel(BMFace *f, bool select_test,
const int cd_loop_uv_offset)
const int cd_loop_uv_offset)
{
BMLoop *l_iter;
BMLoop *l_first;
@@ -3650,7 +4047,7 @@ static bool bm_face_is_all_uv_sel(BMFace *f, bool select_test,
return true;
}
static int uv_hide_exec(bContext *C, wmOperator *op)
static int uv_deselect_mesh_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C);
Object *obedit = CTX_data_edit_object(C);
@@ -3666,7 +4063,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
Image *ima = sima ? sima->image : NULL;
const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY);
if (ts->uv_flag & UV_SYNC_SELECTION) {
@@ -3676,7 +4073,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
int hide = 0;
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
@@ -3685,7 +4082,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (UV_SEL_TEST(luv, !swap)) {
@@ -3696,7 +4093,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
if (hide) {
/* note, a special case for edges could be used,
* for now edges act like verts and get flushed */
* for now edges act like verts and get flushed */
if (use_face_center) {
if (em->selectmode == SCE_SELECT_FACE) {
/* check that every UV is selected */
@@ -3707,7 +4104,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
}
else {
if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (UV_SEL_TEST(luv, !swap)) {
BM_vert_select_set(em->bm, l->v, false);
@@ -3725,7 +4122,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
}
}
else {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (UV_SEL_TEST(luv, !swap)) {
BM_vert_select_set(em->bm, l->v, false);
@@ -3739,7 +4136,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
/* flush vertex selection changes */
if (em->selectmode != SCE_SELECT_FACE)
EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX | SCE_SELECT_EDGE);
BM_select_history_validate(em->bm);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
@@ -3748,25 +4145,26 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
#undef UV_SEL_TEST
static void UV_OT_hide(wmOperatorType *ot)
static void UV_OT_deselect_mesh(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Hide Selected";
ot->description = "Hide (un)selected UV vertices";
ot->idname = "UV_OT_hide";
ot->name = "Deselect 3D Mesh";
ot->description = "Deselect 3D mesh vertices corresponding to (un)selected UV vertices";
ot->idname = "UV_OT_deselect_mesh";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* api callbacks */
ot->exec = uv_hide_exec;
ot->exec = uv_deselect_mesh_exec;
ot->poll = ED_operator_uvedit;
/* props */
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
/* ToDo (SaphireS): Wording ... */
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Deselect unselected rather than selected");
}
/****************** reveal operator ******************/
/********************** Select Mesh operator *********************/
static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
static int uv_select_mesh_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceImage *sima = CTX_wm_space_image(C);
Object *obedit = CTX_data_edit_object(C);
@@ -3780,10 +4178,10 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE);
const int stickymode = sima ? (sima->sticky != SI_STICKY_DISABLE) : 1;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
/* note on tagging, selecting faces needs to be delayed so it doesn't select the verts and
* confuse our checks on selected verts. */
* confuse our checks on selected verts. */
/* call the mesh function if we are in mesh sync sel */
if (ts->uv_flag & UV_SYNC_SELECTION) {
@@ -3794,10 +4192,10 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
}
if (use_face_center) {
if (em->selectmode == SCE_SELECT_FACE) {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
}
@@ -3809,16 +4207,16 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
else {
/* enable adjacent faces to have disconnected UV selections if sticky is disabled */
if (!stickymode) {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
int totsel = 0;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
totsel += BM_elem_flag_test(l->v, BM_ELEM_SELECT);
}
if (!totsel) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
}
@@ -3829,10 +4227,10 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
}
}
else {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
@@ -3846,10 +4244,10 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
}
}
else if (em->selectmode == SCE_SELECT_FACE) {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
}
@@ -3859,10 +4257,10 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
}
}
else {
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ITER_ELEM(l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
@@ -3873,7 +4271,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
}
}
}
/* re-select tagged faces */
BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
@@ -3882,19 +4280,51 @@ static int uv_reveal_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
static void UV_OT_reveal(wmOperatorType *ot)
static void UV_OT_select_mesh(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Reveal Hidden";
ot->description = "Reveal all hidden UV vertices";
ot->idname = "UV_OT_reveal";
ot->name = "Select 3D Mesh";
ot->description = "Select all of the 3D mesh vertices";
ot->idname = "UV_OT_select_mesh";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* api callbacks */
ot->exec = uv_reveal_exec;
ot->exec = uv_select_mesh_exec;
ot->poll = ED_operator_uvedit;
}
/******************** select overlapping operator ********************/
static int UV_OT_select_overlapping_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
const bool extend = RNA_boolean_get(op->ptr, "extend");
ED_uvedit_overlapping_select(scene, obedit, bm, extend);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
static void UV_OT_select_overlapping(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Select Overlapping UVs";
ot->description = "Select all overlapping UV islands";
ot->idname = "UV_OT_select_overlapping";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* api callbacks */
ot->exec = UV_OT_select_overlapping_exec;
ot->poll = ED_operator_uvedit;
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend current selection");
}
/******************** set 3d cursor operator ********************/
static int uv_set_2d_cursor_poll(bContext *C)
@@ -4251,10 +4681,13 @@ void ED_operatortypes_uvedit(void)
WM_operatortype_append(UV_OT_circle_select);
WM_operatortype_append(UV_OT_select_more);
WM_operatortype_append(UV_OT_select_less);
WM_operatortype_append(UV_OT_select_shortest_path);
WM_operatortype_append(UV_OT_select_overlapping);
WM_operatortype_append(UV_OT_snap_cursor);
WM_operatortype_append(UV_OT_snap_selected);
WM_operatortype_append(UV_OT_scale_to_bounds);
WM_operatortype_append(UV_OT_align);
WM_operatortype_append(UV_OT_stitch);
@@ -4271,15 +4704,20 @@ void ED_operatortypes_uvedit(void)
WM_operatortype_append(UV_OT_project_from_view);
WM_operatortype_append(UV_OT_minimize_stretch);
WM_operatortype_append(UV_OT_pack_islands);
WM_operatortype_append(UV_OT_irregular_pack_islands);
WM_operatortype_append(UV_OT_reset);
WM_operatortype_append(UV_OT_sphere_project);
WM_operatortype_append(UV_OT_unwrap);
WM_operatortype_append(UV_OT_reveal);
WM_operatortype_append(UV_OT_hide);
WM_operatortype_append(UV_OT_deselect_mesh);
WM_operatortype_append(UV_OT_select_mesh);
WM_operatortype_append(UV_OT_cursor_set);
WM_operatortype_append(UV_OT_tile_set);
WM_operatortype_append(UV_OT_test);
}
void ED_keymap_uvedit(wmKeyConfig *keyconf)
@@ -4347,6 +4785,7 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "UV_OT_unwrap", EKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "UV_OT_minimize_stretch", VKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "UV_OT_pack_islands", PKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "UV_OT_irregular_pack_islands", PKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
WM_keymap_add_item(keymap, "UV_OT_average_islands_scale", AKEY, KM_PRESS, KM_CTRL, 0);
/* hide */
@@ -4355,8 +4794,18 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "UV_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "unselected", true);
/* reveal */
WM_keymap_add_item(keymap, "UV_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0);
/* deselect 3d mesh */
kmi = WM_keymap_add_item(keymap, "UV_OT_deselect_mesh", HKEY, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "unselected", false);
kmi = WM_keymap_add_item(keymap, "UV_OT_deselect_mesh", HKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "unselected", true);
/* select 3d mesh */
WM_keymap_add_item(keymap, "UV_OT_select_mesh", HKEY, KM_PRESS, KM_ALT | KM_CTRL, 0);
/* cursor */
WM_keymap_add_item(keymap, "UV_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "UV_OT_tile_set", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0);

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,4 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -63,7 +64,8 @@ void param_face_add(ParamHandle *handle,
float *uv[4],
ParamBool *pin,
ParamBool *select,
float face_normal[3]);
float face_normal[3],
int **flag);
void param_edge_set_seam(ParamHandle *handle,
ParamKey *vkeys);
@@ -101,6 +103,15 @@ void param_smooth_area(ParamHandle *handle);
void param_pack(ParamHandle *handle, float margin, bool do_rotate);
/* Packing 2.0 */
void param_irregular_pack_begin(ParamHandle *handle, float *w_area, float margin, int rot_step, bool concave);
void param_irregular_pack_iter(ParamHandle *handle, float *w_area, unsigned int seed, int rot_step, float margin);
void param_irregular_pack_end(ParamHandle *handle);
void param_accept_placement_all(ParamHandle *handle);
//void param_accept_placement(PChart *chart);
void param_restore_placement(ParamHandle *handle, float margin);
/* Average area for all charts */
void param_average(ParamHandle *handle);
@@ -109,11 +120,26 @@ void param_average(ParamHandle *handle);
void param_scale(ParamHandle *handle, float x, float y);
/* Scale to bounds */
void param_scale_bounds(ParamHandle *handle);
/* Select shortest Path */
void param_shortest_path(ParamHandle *handle, bool *p_found, bool topological_distance);
/* Select Overlapping */
void param_select_overlapping(ParamHandle *handle, const bool extend);
/* Flushing */
void param_flush(ParamHandle *handle);
void param_flush_sel(ParamHandle *handle);
void param_flush_restore(ParamHandle *handle);
/* XXX (SaphireS): Remove */
void param_test(ParamHandle *handle);
#ifdef __cplusplus
}

View File

@@ -46,6 +46,7 @@
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_uvproject.h"
#include "BLI_string.h"
@@ -82,6 +83,20 @@
#include "uvedit_intern.h"
#include "uvedit_parametrizer.h"
static int set_handle_params(bool implicit, bool fill_holes, bool selected, bool correct_aspect, bool all_faces)
{
int hparams = 0;
/* Set flags fpr handle_params */
if (implicit) hparams |= HANDLE_IMPLICIT;
if (fill_holes) hparams |= HANDLE_FILL;
if (selected) hparams |= HANDLE_SELECTED;
if (correct_aspect) hparams |= HANDLE_CORRECT_ASPECT;
if (all_faces) hparams |= HANDLE_ALL_FACES;
return hparams;
}
static void modifier_unwrap_state(Object *obedit, Scene *scene, bool *r_use_subsurf)
{
ModifierData *md;
@@ -235,6 +250,7 @@ static void construct_param_handle_face_add(ParamHandle *handle, Scene *scene,
ParamBool *select = BLI_array_alloca(select, efa->len);
float **co = BLI_array_alloca(co, efa->len);
float **uv = BLI_array_alloca(uv, efa->len);
int **flag = BLI_array_alloca(flag, efa->len);
int i;
BMIter liter;
@@ -251,15 +267,14 @@ static void construct_param_handle_face_add(ParamHandle *handle, Scene *scene,
co[i] = l->v->co;
uv[i] = luv->uv;
pin[i] = (luv->flag & MLOOPUV_PINNED) != 0;
flag[i] = &(luv->flag);
select[i] = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
}
param_face_add(handle, key, i, vkeys, co, uv, pin, select, efa->no);
param_face_add(handle, key, i, vkeys, co, uv, pin, select, efa->no, flag);
}
static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMesh *bm,
const bool implicit, const bool fill, const bool sel,
const bool correct_aspect)
static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMesh *bm, const int handle_params)
{
ParamHandle *handle;
BMFace *efa;
@@ -268,6 +283,12 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMesh *bm,
BMIter iter, liter;
int i;
const bool implicit = handle_params & HANDLE_IMPLICIT;
const bool fill = handle_params & HANDLE_FILL;
const bool sel = handle_params & HANDLE_SELECTED;
const bool correct_aspect = handle_params & HANDLE_CORRECT_ASPECT;
const bool all_faces = handle_params & HANDLE_ALL_FACES;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
handle = param_construct_begin();
@@ -290,7 +311,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMesh *bm,
continue;
}
if (implicit) {
if (implicit && !all_faces) {
bool is_loopsel = false;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -325,7 +346,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMesh *bm,
static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select,
Scene *scene, const int cd_loop_uv_offset)
int *flag, Scene *scene, const int cd_loop_uv_offset)
{
BMLoop *l;
BMIter liter;
@@ -334,6 +355,7 @@ static void texface_from_original_index(BMFace *efa, int index, float **uv, Para
*uv = NULL;
*pin = 0;
*select = 1;
*flag = 0;
if (index == ORIGINDEX_NONE)
return;
@@ -344,6 +366,7 @@ static void texface_from_original_index(BMFace *efa, int index, float **uv, Para
*uv = luv->uv;
*pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0;
*select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
*flag = luv->flag;
break;
}
}
@@ -445,6 +468,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
ParamBool pin[4], select[4];
float *co[4];
float *uv[4];
int flag[4];
BMFace *origFace = faceMap[i];
if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
@@ -473,12 +497,12 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B
/* 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, origVertIndices[mloop[0].v], &uv[0], &pin[0], &select[0], scene, cd_loop_uv_offset);
texface_from_original_index(origFace, origVertIndices[mloop[1].v], &uv[1], &pin[1], &select[1], scene, cd_loop_uv_offset);
texface_from_original_index(origFace, origVertIndices[mloop[2].v], &uv[2], &pin[2], &select[2], scene, cd_loop_uv_offset);
texface_from_original_index(origFace, origVertIndices[mloop[3].v], &uv[3], &pin[3], &select[3], scene, cd_loop_uv_offset);
texface_from_original_index(origFace, origVertIndices[mloop[0].v], &uv[0], &pin[0], &select[0], &flag[0], scene, cd_loop_uv_offset);
texface_from_original_index(origFace, origVertIndices[mloop[1].v], &uv[1], &pin[1], &select[1], &flag[1], scene, cd_loop_uv_offset);
texface_from_original_index(origFace, origVertIndices[mloop[2].v], &uv[2], &pin[2], &select[2], &flag[2], scene, cd_loop_uv_offset);
texface_from_original_index(origFace, origVertIndices[mloop[3].v], &uv[3], &pin[3], &select[3], &flag[3], scene, cd_loop_uv_offset);
param_face_add(handle, key, 4, vkeys, co, uv, pin, select, NULL);
param_face_add(handle, key, 4, vkeys, co, uv, pin, select, NULL, flag);
}
/* these are calculated from original mesh too */
@@ -527,6 +551,8 @@ static bool minimize_stretch_init(bContext *C, wmOperator *op)
return false;
}
int hparams = set_handle_params(implicit, fill_holes, true, true, false);
ms = MEM_callocN(sizeof(MinStretch), "MinStretch");
ms->scene = scene;
ms->obedit = obedit;
@@ -534,7 +560,7 @@ static bool minimize_stretch_init(bContext *C, wmOperator *op)
ms->blend = RNA_float_get(op->ptr, "blend");
ms->iterations = RNA_int_get(op->ptr, "iterations");
ms->i = 0;
ms->handle = construct_param_handle(scene, obedit, em->bm, implicit, fill_holes, 1, 1);
ms->handle = construct_param_handle(scene, obedit, em->bm, hparams);
ms->lasttime = PIL_check_seconds_timer();
param_stretch_begin(ms->handle);
@@ -712,12 +738,48 @@ void UV_OT_minimize_stretch(wmOperatorType *ot)
RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations", "Number of iterations to run, 0 is unlimited when run interactively", 0, 100);
}
/* ******************** Select Shortest Path operator **************** */
bool ED_uvedit_shortest_path_select(Scene *scene, Object *ob, BMesh *bm, bool topo_dist)
{
ParamHandle *handle;
bool path_found = false;
int hparams = set_handle_params(true, false, false, true, true);
handle = construct_param_handle(scene, ob, bm, hparams);
param_shortest_path(handle, &path_found, topo_dist);
param_flush_sel(handle);
param_delete(handle);
return path_found;
}
/* ******************** Select Overlapping UVs operator **************** */
void ED_uvedit_overlapping_select(Scene *scene, Object *ob, BMesh *bm, const bool extend)
{
ParamHandle *handle;
int hparams = set_handle_params(true, false, false, true, true);
handle = construct_param_handle(scene, ob, bm, hparams);
param_select_overlapping(handle, extend);
param_flush_sel(handle);
param_delete(handle);
}
/* ******************** Scale To Bounds operator **************** */
void ED_uvedit_scale_to_bounds(Scene *scene, Object *ob, BMesh *bm)
{
ParamHandle *handle;
int hparams = set_handle_params(true, false, true, true, false);
handle = construct_param_handle(scene, ob, bm, hparams);
param_scale_bounds(handle);
param_flush(handle);
param_delete(handle);
}
/* ******************** Pack Islands operator **************** */
void ED_uvedit_pack_islands(Scene *scene, Object *ob, BMesh *bm, bool selected, bool correct_aspect, bool do_rotate)
{
ParamHandle *handle;
handle = construct_param_handle(scene, ob, bm, true, false, selected, correct_aspect);
int hparams = set_handle_params(true, false, selected, correct_aspect, false);
handle = construct_param_handle(scene, ob, bm, hparams);
param_pack(handle, scene->toolsettings->uvcalc_margin, do_rotate);
param_flush(handle);
param_delete(handle);
@@ -765,6 +827,344 @@ void UV_OT_pack_islands(wmOperatorType *ot)
RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
}
/* ******************** Pack Islands operator 2.0 **************** */
typedef struct SimulatedAnnealing {
RNG *rng;
int seed;
float theta;
float f;
float r;
float temperature;
int rot_steps;
} SimulatedAnnealing;
typedef struct PackIslands {
Scene *scene;
Object *obedit;
BMEditMesh *em;
ParamHandle *handle;
double lasttime;
int iter_global, iter_local, iter_max;
wmTimer *timer;
float wasted_area_last, margin;
bool use_concave;
SimulatedAnnealing *sa;
} PackIslands;
static bool irregular_pack_islands_init(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
PackIslands *pi;
SimulatedAnnealing *simann;
unsigned int seed = 31415926;
float wasted_area;
bool average_scale = RNA_boolean_get(op->ptr, "average_islands_scale");
/* Keep for now, needed when making packing work with current selection */
/*if (!uvedit_have_selection(scene, em, implicit)) {
return false;
}*/
int hparams = set_handle_params(true, false, false, false, true);
pi = MEM_callocN(sizeof(PackIslands), "PackIslands");
pi->scene = scene;
pi->obedit = obedit;
pi->em = em;
pi->iter_max = RNA_int_get(op->ptr, "iterations");
pi->iter_global = 0;
pi->iter_local = 0;
pi->margin = RNA_float_get(op->ptr, "margin") / 2.0f; /* Only apply half the margin per chart */
pi->use_concave = RNA_boolean_get(op->ptr, "concave");
pi->handle = construct_param_handle(scene, obedit, em->bm, hparams);
pi->lasttime = PIL_check_seconds_timer();
simann = MEM_callocN(sizeof(SimulatedAnnealing), "SimulatedAnnealing");
simann->rng = BLI_rng_new(seed);
simann->seed = seed;
simann->theta = 0.0f;
simann->f = 0.0f;
simann->r = 0.0f;
simann->temperature = 1.0f;
simann->rot_steps = RNA_int_get(op->ptr, "rotation_steps");
pi->sa = simann;
if (average_scale)
param_average(pi->handle);
param_irregular_pack_begin(pi->handle,
&wasted_area,
pi->margin,
pi->sa->rot_steps,
pi->use_concave /* SA */);
param_accept_placement_all(pi->handle);
pi->wasted_area_last = wasted_area;
printf("wasted area currently: %f\n", wasted_area);
op->customdata = pi;
DAG_id_tag_update(pi->obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, pi->obedit->data);
return true;
}
static void irregular_pack_islands_iteration(bContext *C, wmOperator *op, bool interactive)
{
PackIslands *pi = op->customdata;
ScrArea *sa = CTX_wm_area(C);
float wasted_area = 0.0f, dE, r1, r2;
float a = 0.95f;
/* ToDo Saphires: Find optimal parameter */
float k = 0.5f; /* Stefan-Boltzman constant-like parameter */
int local_iter_max = 50;
pi->iter_global++;
/* Cooling Schedule */
if (pi->iter_local >= local_iter_max) {
pi->sa->temperature = pi->sa->temperature * a;
pi->iter_local = 0;
}
/* Find neighboring solution */
/*ToDo Saphires: Pass SA parameters */
param_irregular_pack_iter(pi->handle,
&wasted_area,
pi->iter_global,
pi->sa->rot_steps,
pi->margin /* SA */);
/* delta Energy */
dE = wasted_area - pi->wasted_area_last;
printf("wasted area currently: %f, wasted area last: %f\n", wasted_area, pi->wasted_area_last);
if (dE < 0) {
/* Current solution is new best solution, keep placement */
param_accept_placement_all(pi->handle);
pi->wasted_area_last = wasted_area;
printf("dE < 0\n");
}
else {
r1 = BLI_rng_get_float(pi->sa->rng);
r2 = (float)exp(-dE/(k * pi->sa->temperature));
if (0 /*r1 < r2*/) {
/* Current solution is new best solution, keep placement */
param_accept_placement_all(pi->handle);
pi->wasted_area_last = wasted_area;
printf("r1 < r2\n");
}
else {
/* no better solution found, "frozen state solution" */
printf("frozen state, revert\n");
param_restore_placement(pi->handle, pi->margin);
pi->iter_local++;
}
}
/* RNA_int_set(op->ptr, "iterations", pi->iter_global); */ /* ToDo SaphireS */
if (interactive /*&& (PIL_check_seconds_timer() - pi->lasttime > 0.5)*/) {
char str[UI_MAX_DRAW_STR];
param_flush(pi->handle);
if (sa) {
BLI_snprintf(str, sizeof(str),
IFACE_("Pack Islands (irregular). Iteration: %i, Wasted UV Area (Best Solution): %f"), pi->iter_global, pi->wasted_area_last);
ED_area_headerprint(sa, str);
}
pi->lasttime = PIL_check_seconds_timer();
DAG_id_tag_update(pi->obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, pi->obedit->data);
printf("done iteration\n");
}
}
static void irregular_pack_islands_exit(bContext *C, wmOperator *op, bool cancel)
{
PackIslands *pi = op->customdata;
ScrArea *sa = CTX_wm_area(C);
if (sa)
ED_area_headerprint(sa, NULL);
if (pi->timer)
WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), pi->timer);
if (cancel) {
param_flush_restore(pi->handle); /* Restore original UVs */
}
else {
//param_restore_packing_solution(pi->handle); /* Restore best solution*/
param_flush(pi->handle); /* Keep new UVs */
}
param_irregular_pack_end(pi->handle);
param_delete(pi->handle);
BLI_rng_free(pi->sa->rng);
MEM_freeN(pi->sa);
DAG_id_tag_update(pi->obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, pi->obedit->data);
MEM_freeN(pi);
op->customdata = NULL;
}
static int irregular_pack_islands_exec(bContext *C, wmOperator *op)
{
int i, iterations;
if (!irregular_pack_islands_init(C, op))
return OPERATOR_CANCELLED;
iterations = RNA_int_get(op->ptr, "iterations");
for (i = 0; i < iterations; i++)
irregular_pack_islands_iteration(C, op, false);
irregular_pack_islands_exit(C, op, false);
return OPERATOR_FINISHED;
}
static int irregular_pack_islands_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
PackIslands *pi;
if (!irregular_pack_islands_init(C, op))
return OPERATOR_CANCELLED;
irregular_pack_islands_iteration(C, op, true);
pi = op->customdata;
WM_event_add_modal_handler(C, op);
pi->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
return OPERATOR_RUNNING_MODAL;
}
static int irregular_pack_islands_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
PackIslands *pi = op->customdata;
switch (event->type) {
case ESCKEY:
case RIGHTMOUSE:
irregular_pack_islands_exit(C, op, true);
return OPERATOR_CANCELLED;
case RETKEY:
case PADENTER:
case LEFTMOUSE:
irregular_pack_islands_exit(C, op, false);
return OPERATOR_FINISHED;
case TIMER:
if (pi->timer == event->customdata) {
double start = PIL_check_seconds_timer();
do {
irregular_pack_islands_iteration(C, op, true);
} while (PIL_check_seconds_timer() - start < 0.01);
}
break;
}
if (pi->iter_max && pi->iter_global >= pi->iter_max) {
irregular_pack_islands_exit(C, op, false);
return OPERATOR_FINISHED;
}
return OPERATOR_RUNNING_MODAL;
}
static void irregular_pack_islands_cancel(bContext *C, wmOperator *op)
{
irregular_pack_islands_exit(C, op, true);
}
void UV_OT_irregular_pack_islands(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Pack Islands (irregular)";
ot->idname = "UV_OT_irregular_pack_islands";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
ot->description = "New and improved packing taking into account irregular uv shapes";
/* api callbacks */
ot->exec = irregular_pack_islands_exec;
ot->invoke = irregular_pack_islands_invoke;
ot->modal = irregular_pack_islands_modal;
ot->cancel = irregular_pack_islands_cancel;
ot->poll = ED_operator_uvedit;
/* properties */
RNA_def_boolean(ot->srna, "concave", false, "Use concave boundaries", "Use concave boundaries (slower but better results)");
RNA_def_float(ot->srna, "margin", 0.0f, 0.0f, 1.0f, "Margin", "Border Margin/Padding to apply per UV island", 0.0f, 1.0f);
RNA_def_int(ot->srna, "rotation_steps", 4, 0, 360, "Rotation Steps", "Allowed rotations to try during packing. (2=180<38>, 4=90<39>, etc.)", 0, 360);
RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations", "Number of iterations to run, 0 is unlimited when run interactively", 0, 10000);
RNA_def_boolean(ot->srna, "average_islands_scale", true, "Average Islands Scale", "Average Islands Scale before starting packing");
}
/* ******************** XXX (SaphireS): DEBUG-TEST operator **************** */
/* XXX (SaphireS): Remove */
static void ED_uvedit_test_debug(Scene *scene, Object *ob, BMesh *bm, bool selected, bool correct_aspect)
{
ParamHandle *handle;
int hparams = set_handle_params(true, false, selected, correct_aspect, true);
handle = construct_param_handle(scene, ob, bm, hparams);
param_test(handle);
param_flush(handle);
param_delete(handle);
}
/* XXX (SaphireS): Remove */
static int test_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
/*if (!uvedit_have_selection(scene, em, true)) {
return OPERATOR_CANCELLED;
}*/
ED_uvedit_test_debug(scene, obedit, em->bm, false, true);
DAG_id_tag_update(obedit->data, 0);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
return OPERATOR_FINISHED;
}
/* XXX (SaphireS): Remove */
void UV_OT_test(wmOperatorType *ot)
{
/* identifiers */
ot->name = "DEBUG - TEST";
ot->idname = "UV_OT_test";
ot->description = "Debug operator to test stuff";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* api callbacks */
ot->exec = test_exec;
ot->poll = ED_operator_uvedit;
}
/* ******************** Average Islands Scale operator **************** */
static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
@@ -774,12 +1174,14 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
BMEditMesh *em = BKE_editmesh_from_object(obedit);
ParamHandle *handle;
bool implicit = true;
int hparams = set_handle_params(implicit, false, true, true, false);
if (!uvedit_have_selection(scene, em, implicit)) {
return OPERATOR_CANCELLED;
}
handle = construct_param_handle(scene, obedit, em->bm, implicit, 0, 1, 1);
handle = construct_param_handle(scene, obedit, em->bm, hparams);
param_average(handle);
param_flush(handle);
param_delete(handle);
@@ -817,6 +1219,8 @@ void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
modifier_unwrap_state(obedit, scene, &use_subsurf);
int hparams = set_handle_params(false, fillholes, false, true, false);
if (!ED_uvedit_test(obedit)) {
return;
}
@@ -824,7 +1228,7 @@ void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
if (use_subsurf)
liveHandle = construct_param_handle_subsurfed(scene, obedit, em, fillholes, false, true);
else
liveHandle = construct_param_handle(scene, obedit, em->bm, false, fillholes, false, true);
liveHandle = construct_param_handle(scene, obedit, em->bm, hparams);
param_lscm_begin(liveHandle, PARAM_TRUE, abf);
}
@@ -1146,21 +1550,27 @@ void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
const bool fill_holes = (scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES) != 0;
const bool correct_aspect = (scene->toolsettings->uvcalc_flag & UVCALC_NO_ASPECT_CORRECT) == 0;
const bool pack_islands = (scene->toolsettings->uvcalc_flag & UVCALC_PACKISLANDS) != 0;
bool use_subsurf;
int hparams = set_handle_params(false, fill_holes, sel, correct_aspect, false);
modifier_unwrap_state(obedit, scene, &use_subsurf);
if (use_subsurf)
handle = construct_param_handle_subsurfed(scene, obedit, em, fill_holes, sel, correct_aspect);
else
handle = construct_param_handle(scene, obedit, em->bm, false, fill_holes, sel, correct_aspect);
handle = construct_param_handle(scene, obedit, em->bm, hparams);
param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
param_lscm_solve(handle);
param_lscm_end(handle);
param_average(handle);
param_pack(handle, scene->toolsettings->uvcalc_margin, false);
if (pack_islands)
param_pack(handle, scene->toolsettings->uvcalc_margin, false);
else
param_scale_bounds(handle);
param_flush(handle);
@@ -1175,6 +1585,7 @@ static int unwrap_exec(bContext *C, wmOperator *op)
int method = RNA_enum_get(op->ptr, "method");
const bool fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
const bool correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
const bool pack_islands = RNA_boolean_get(op->ptr, "pack_islands");
const bool use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data");
bool use_subsurf_final;
float obsize[3];
@@ -1189,6 +1600,9 @@ static int unwrap_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* Reveal hidden UVs since they're taken into account*/
ED_uvedit_reveal(em);
mat4_to_size(obsize, obedit->obmat);
if (!(fabsf(obsize[0] - obsize[1]) < 1e-4f && fabsf(obsize[1] - obsize[2]) < 1e-4f))
BKE_report(op->reports, RPT_INFO,
@@ -1215,6 +1629,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 (pack_islands) scene->toolsettings->uvcalc_flag |= UVCALC_PACKISLANDS;
else scene->toolsettings->uvcalc_flag &= ~UVCALC_PACKISLANDS;
if (use_subsurf) scene->toolsettings->uvcalc_flag |= UVCALC_USESUBSURF;
else scene->toolsettings->uvcalc_flag &= ~UVCALC_USESUBSURF;
@@ -1258,6 +1675,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, "pack_islands", 1, "Pack Islands",
"Pack UV islands after unwrapping");
RNA_def_boolean(ot->srna, "use_subsurf_data", 0, "Use Subsurf Modifier",
"Map UVs taking vertex position after Subdivision Surface modifier has been applied");
RNA_def_float_factor(ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
@@ -1303,6 +1722,9 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* Reveal hidden UVs since they're taken into account*/
ED_uvedit_reveal(em);
cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
if (RNA_boolean_get(op->ptr, "orthographic")) {
@@ -1405,6 +1827,9 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
/* Reveal hidden UVs since they're taken into account*/
ED_uvedit_reveal(me->edit_btmesh);
ED_mesh_uv_loop_reset(C, me);
DAG_id_tag_update(obedit->data, 0);
@@ -1491,6 +1916,9 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* Reveal hidden UVs since they're taken into account*/
ED_uvedit_reveal(em);
cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
uv_map_transform(C, op, center, rotmat);
@@ -1570,6 +1998,9 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* Reveal hidden UVs since they're taken into account*/
ED_uvedit_reveal(em);
cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
uv_map_transform(C, op, center, rotmat);
@@ -1676,6 +2107,9 @@ static int cube_project_exec(bContext *C, wmOperator *op)
if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
return OPERATOR_CANCELLED;
}
/* Reveal hidden UVs since they're taken into account*/
ED_uvedit_reveal(em);
ED_uvedit_unwrap_cube_project(obedit, em->bm, cube_size, true);
uv_map_clip_correct(scene, obedit, em, op);

View File

@@ -213,6 +213,7 @@ enum {
MLOOPUV_EDGESEL = (1 << 0),
MLOOPUV_VERTSEL = (1 << 1),
MLOOPUV_PINNED = (1 << 2),
MLOOPUV_HIDDEN = (1 << 3)
};
/**

View File

@@ -2152,6 +2152,7 @@ typedef enum ImagePaintMode {
#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*/
#define UVCALC_PACKISLANDS 16 /* Pack Islands after unwrapping*/
/* toolsettings->uv_flag */
#define UV_SYNC_SELECTION 1