With Blender 2.63, UVDistribute no longer works. Had a couple of people provide helpful Traces. UVDIstribute: http://projects.blender.org/tracker/?func=detail&atid=467&aid=29981&group_id=153 Date: 2012-05-30 13:41 Sender: Evgen Zaitsev It sounds like a good script, but again with current version of the Blender 2.63 seems it doesn't work. Traceback (most recent call last): File "C:\Users\Zexell\Dropbox\blender_scripts\addons_extern\uvDistribute.py", line 68, in invoke return {self.execute(context)} File "C:\Users\Zexell\Dropbox\blender_scripts\addons_extern\uvDistribute.py", line 74, in execute uvDistribute(self,context.active_object) File "C:\Users\Zexell\Dropbox\blender_scripts\addons_extern\uvDistribute.py", line 110, in uvDistribute uvCount = len(uvTexture.data[i].uv) AttributeError: 'MeshTexturePoly' object has no attribute 'uv' location::-1 2/Jun/2012 21:58 In the script, the method starts with "context" - need to grab ahold of the same equivalent in Blender, in the Python console. **** Need to be in Object Mode mesh = bpy.context.active_object.data uvTexture = mesh.uv_textures[0] uvDataCount = len(uvTexture.data) i = 0 uvCount = len(uvTexture.data[i].uv) -- gives: Traceback (most recent call last): File "", line 1, in AttributeError: 'MeshTexturePoly' object has no attribute 'uv' Having trouble finding where the uv values are located. Clue: http://wiki.blender.org/index.php/Doc:2.6/Manual/Data_System/Data_System http://www.blender.org/documentation/blender_python_api_2_59_0/contents.html Mesh.uv_textures[0] which is a UVTextures UVTextures.active which is a MeshTexturePolyLayer MeshTexturePolyLayer.data, which is a MeshTexturePoly MeshTexturePoly.image which is a Image found: bpy.types.MeshTextureFace.uv, .uv1, 2, 3, 4 sub of: MeshTextureFaceLayer.data sub of Mesh.tessface_uv_textures On this page: http://www.blender.org/documentation/blender_python_api_2_63_7/bpy.types.Mesh.html#bpy.types.Mesh.tessface_uv_textures Has sample code: import bpy me = bpy.context.object.data uv_layer = me.uv_layers.active.data for poly in me.polygons: print("Polygon index: %d, length: %d" % (poly.index, poly.loop_total)) # range is used here to show how the polygons reference loops, # for convenience 'poly.loop_indices' can be used instead. for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total): print(" Vertex: %d" % me.loops[loop_index].vertex_index) print(" UV: %r" % uv_layer[loop_index].uv) Try: mesh = bpy.context.active_object.data uv_layer = mesh.uv_layers.active.data uv_layer[0].uv -- gives Vector((0.8570523262023926, 0.4703197479248047)) mesh.uv_layers.active is bpy.types.MeshUVLoopLayer bpy.types.MeshUVLoopLayer.data is bpy_prop_collection of MeshUVLoop MeshUVLoop.uv is float array of 2 items in [-inf, inf], default (0.0, 0.0) MeshUVLoop.select is boolean, default False (not sure if we can set this) 2/Jun/2012 23:09 This page is important: http://www.blender.org/documentation/blender_python_api_2_63_release/bpy.types.Mesh.html#bpy.types.Mesh.vertices Shows the sample script above, also talks about vertices and UVs. 5/Jun/2012 20:16 Try looking at the "select" values me = bpy.context.object.data uv_layer = me.uv_layers.active.data # Paste the following into the console window for poly in me.polygons: print("Polygon index: %d, length: %d" % (poly.index, poly.loop_total)) # range is used here to show how the polygons reference loops, # for convenience 'poly.loop_indices' can be used instead. for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total): if uv_layer[loop_index].select: print(" Vertex: %d" % me.loops[loop_index].vertex_index) print(" UV: %r" % uv_layer[loop_index].uv) selectVal = ("False", "True")[uv_layer[loop_index].select] print(" select: %r" % selectVal) --- worked! # Now let's try to make a change, maybe by adding .2 to the selected Y coordinates me = bpy.context.object.data uv_layer = me.uv_layers.active.data for poly in me.polygons: print("Polygon index: %d, length: %d" % (poly.index, poly.loop_total)) # range is used here to show how the polygons reference loops, # for convenience 'poly.loop_indices' can be used instead. for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total): if uv_layer[loop_index].select: print(" Vertex: %d" % me.loops[loop_index].vertex_index) print(" UV: %r" % uv_layer[loop_index].uv) selectVal = ("False", "True")[uv_layer[loop_index].select] print(" select: %r" % selectVal) myVec = uv_layer[loop_index].uv myVec[1] = myVec[1] + 0.2 uv_layer[loop_index].uv = myVec print(" -- New Vector %r" % myVec) --- Hmm, this "uv_layer[loop_index].uv = myVec" made Blender blow up, maybe because the me= and uv_layer lines were missing 5/Jun/2012 20:52 # This worked: me = bpy.context.object.data uv_layer = me.uv_layers.active.data selectedCount = 0 for poly in me.polygons: # print("Polygon index: %d, length: %d" % (poly.index, poly.loop_total)) # range is used here to show how the polygons reference loops, # for convenience 'poly.loop_indices' can be used instead. for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total): if uv_layer[loop_index].select: selectedCount += 1 print(" Vertex: %d" % me.loops[loop_index].vertex_index) print(" UV: %r" % uv_layer[loop_index].uv) selectVal = ("False", "True")[uv_layer[loop_index].select] print(" select: %r" % selectVal) myVec = uv_layer[loop_index].uv myVec[1] = myVec[1] + 0.05 uv_layer[loop_index].uv = myVec print(" -- New Vector %r" % myVec) print ("Selected UVs %f" % selectedCount) Using this as a starting point, completed the work: 7/Jun/2012 22:47 In the process, discovered that there was a bug. If points had the same Y coordinate, the UVs would be placed in a incorrect position, because In the following, added "if not y in yOrdDict" because otherwise, we will keep only the highest index, and the quantity of elements is thrown off, throwing off the new position calculation: for y in sortedY: if not y in yOrdDict: yOrdDict[y] = i i = i + 1 ----------- RIght now, everything is working except with my complex test case, if not all of the planes are selected in the 3D window, the UVs are not moved. However the code above moves them. Not sure why. Getting this: 2012-06-09 19:56:41,582 INFO Distinct selected UV point count 724.000000 out of 2075.000000 selected and 485.000000 NOT selected then after processing: 2012-06-09 19:56:42,171 INFO UVs distributed 2075.000000 out of 2075.000000 selected and 485.000000 unselected then I select everything in the 3D window, and I get this: 2012-06-09 19:57:37,618 INFO uv_layer: bpy.data.meshes['Plane.001'].uv_layers["UVMap"].data 2012-06-09 19:57:37,732 INFO Distinct selected UV point count 64.000000 out of 127.000000 selected and 2433.000000 NOT selected then after processing: 2012-06-09 19:57:37,775 INFO UVs distributed 127.000000 out of 127.000000 selected and 2433.000000 unselected 9/Jun/2012 19:48 Hi Dan, Thanks for providing me with your script. One question though, I am getting a error that says I need to select 3uv's. What does that mean. I am select the whole uv map. Thanks, Brian ------------------ Making some diagnostics: me = bpy.context.object.data uv_layer = me.uv_layers.active.data selectedCount = 0 for poly in me.polygons: print("Polygon index: %d, length: %d" % (poly.index, poly.loop_total)) -- ... Polygon index: 637, length: 4 Polygon index: 638, length: 4 Polygon index: 639, length: 4 me = bpy.context.object.data uv_layer = me.uv_layers.active.data selectedCount = 0 unselectedCount = 0 selectedPoly = 0 unselectedPoly = 0 for poly in me.polygons: # print("Polygon index: %d, length: %d" % (poly.index, poly.loop_total)) # range is used here to show how the polygons reference loops, # for convenience 'poly.loop_indices' can be used instead. if poly.select: selectedPoly += 1 else: unselectedPoly += 1 for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total): if uv_layer[loop_index].select: selectedCount += 1 else: unselectedCount += 1 print ("Selected UVs %d, unselected UVs %d, selected poly %d, unselected poly %d" % (selectedCount, unselectedCount, selectedPoly, unselectedPoly)) -------------- Selected UVs 1929, unselected UVs 631, selected poly 159, unselected poly 481 but the selected UVs should be at most a 2-digit number in my example Maybe I can just use the selected polys for obj in bpy.data.objects: print(obj.name) p = bpy.data.objects["Plane"] type(p) -- me = bpy.context.object.data uv_layer = me.uv_layers.active.data selectedCount = 0 unselectedCount = 0 selectedPoly = 0 unselectedPoly = 0 for poly in me.polygons: # print("Polygon index: %d, length: %d" % (poly.index, poly.loop_total)) # range is used here to show how the polygons reference loops, # for convenience 'poly.loop_indices' can be used instead. if poly.select: selectedPoly += 1 else: unselectedPoly += 1 if poly.select: for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total): if uv_layer[loop_index].select: selectedCount += 1 else: unselectedCount += 1 print ("Selected UVs %d, unselected UVs %d, selected poly %d, unselected poly %d" % (selectedCount, unselectedCount, selectedPoly, unselectedPoly)) ---------------------- Fixed problem by putting "if poly.select:" ahead of the loop iteration. Apparently I was incorrectly looping through polygons that weren't selected. Also had to change the code that checks to see if anything is selected. I had copied something looking to see if the "edges" were selected, but this didn't seem to work any more. 15/Jun/2012 8:59 To make revisions and test them: Make changes to UVDistribute.py in Eclipse CPP. In blender, find the "Addon" by using File->User Preferences->Addons->Mesh, click the triangle, and remove it. Then in the same window, use "Install Addon.." and select the UVDistribute.py file. (A shortcut to do this is to click "Documents", then .., then pythonWorkspace/UVRighter/src/uvDistribute.py) Then remember to click the check box on the newly added Addon, so that it will show up in Blender. 15/Jun/2012 9:03 ---------------------------- To test it Create Bezier Curve, pull upwards away from X-axis, bend it into a shallow "hill". Tip it at about 4 degrees so that subsequent wraps overlap. Set origin to 3D cursor, which should be at the global origin. Apply screw modifier, Axis: X, Screw 3, Angle 720, Steps 50, apply This makes a mesh shaped roughly like the handle wrap Go into "UV Editing" view, select all, do Mesh-Unwrap. Should see uneven unwrap displayed. Select a row of vertices (Alt click). Select UVs->Weld/Align->UVDistribute All of the vertices will become evenly distributed 31/Dec/2012 12:34