Merge branch 'master' into xr-actions-D9124
This commit is contained in:
commit
0d1b80b5e2
|
@ -19,7 +19,7 @@
|
|||
bl_info = {
|
||||
"name": "BlenderKit Online Asset Library",
|
||||
"author": "Vilem Duha, Petr Dlouhy",
|
||||
"version": (1, 0, 40),
|
||||
"version": (2, 92, 0),
|
||||
"blender": (2, 92, 0),
|
||||
"location": "View3D > Properties > BlenderKit",
|
||||
"description": "Online BlenderKit library (materials, models, brushes and more). Connects to the internet.",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -303,28 +303,33 @@ class FastRateMenu(Operator):
|
|||
message: StringProperty(
|
||||
name="message",
|
||||
description="message",
|
||||
default="Rating asset")
|
||||
default="Rating asset",
|
||||
options={'SKIP_SAVE'})
|
||||
|
||||
asset_id: StringProperty(
|
||||
name="Asset Base Id",
|
||||
description="Unique id of the asset (hidden)",
|
||||
default="")
|
||||
default="",
|
||||
options={'SKIP_SAVE'})
|
||||
|
||||
asset_name: StringProperty(
|
||||
name="Asset Name",
|
||||
description="Name of the asset (hidden)",
|
||||
default="")
|
||||
default="",
|
||||
options={'SKIP_SAVE'})
|
||||
|
||||
asset_type: StringProperty(
|
||||
name="Asset type",
|
||||
description="asset type",
|
||||
default="")
|
||||
default="",
|
||||
options={'SKIP_SAVE'})
|
||||
|
||||
rating_quality: IntProperty(name="Quality",
|
||||
description="quality of the material",
|
||||
default=0,
|
||||
min=-1, max=10,
|
||||
update=update_ratings_quality)
|
||||
# update=update_ratings_quality,
|
||||
options={'SKIP_SAVE'})
|
||||
|
||||
# the following enum is only to ease interaction - enums support 'drag over' and enable to draw the stars easily.
|
||||
rating_quality_ui: EnumProperty(name='rating_quality_ui',
|
||||
|
@ -332,12 +337,14 @@ class FastRateMenu(Operator):
|
|||
description='Rating stars 0 - 10',
|
||||
default=0,
|
||||
update=update_quality_ui,
|
||||
)
|
||||
options={'SKIP_SAVE'})
|
||||
|
||||
rating_work_hours: FloatProperty(name="Work Hours",
|
||||
description="How many hours did this work take?",
|
||||
default=0.00,
|
||||
min=0.0, max=300, update=update_ratings_work_hours
|
||||
min=0.0, max=300,
|
||||
# update=update_ratings_work_hours,
|
||||
options={'SKIP_SAVE'}
|
||||
)
|
||||
|
||||
high_rating_warning = "This is a high rating, please be sure to give such rating only to amazing assets"
|
||||
|
@ -363,7 +370,8 @@ class FastRateMenu(Operator):
|
|||
('200', '200', high_rating_warning),
|
||||
('250', '250', high_rating_warning),
|
||||
],
|
||||
default='0', update=update_ratings_work_hours_ui
|
||||
default='0', update=update_ratings_work_hours_ui,
|
||||
options = {'SKIP_SAVE'}
|
||||
)
|
||||
|
||||
rating_work_hours_ui_1_5: EnumProperty(name="Work Hours",
|
||||
|
@ -377,7 +385,9 @@ class FastRateMenu(Operator):
|
|||
('4', '4', ''),
|
||||
('5', '5', '')
|
||||
],
|
||||
default='0', update=update_ratings_work_hours_ui_1_5
|
||||
default='0',
|
||||
update=update_ratings_work_hours_ui_1_5,
|
||||
options = {'SKIP_SAVE'}
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -15,7 +15,7 @@
|
|||
bl_info = {
|
||||
'name': 'glTF 2.0 format',
|
||||
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
|
||||
"version": (1, 6, 4),
|
||||
"version": (1, 6, 8),
|
||||
'blender': (2, 91, 0),
|
||||
'location': 'File > Import-Export',
|
||||
'description': 'Import-Export as glTF 2.0',
|
||||
|
@ -196,7 +196,7 @@ class ExportGLTF2_Base:
|
|||
description='Compression level (0 = most speed, 6 = most compression, higher values currently not supported)',
|
||||
default=6,
|
||||
min=0,
|
||||
max=6
|
||||
max=10
|
||||
)
|
||||
|
||||
export_draco_position_quantization: IntProperty(
|
||||
|
@ -263,6 +263,22 @@ class ExportGLTF2_Base:
|
|||
default=True
|
||||
)
|
||||
|
||||
use_mesh_edges: BoolProperty(
|
||||
name='Loose Edges',
|
||||
description=(
|
||||
'Export loose edges as lines, using the material from the first material slot'
|
||||
),
|
||||
default=False,
|
||||
)
|
||||
|
||||
use_mesh_vertices: BoolProperty(
|
||||
name='Loose Points',
|
||||
description=(
|
||||
'Export loose points as glTF points, using the material from the first material slot'
|
||||
),
|
||||
default=False,
|
||||
)
|
||||
|
||||
export_cameras: BoolProperty(
|
||||
name='Cameras',
|
||||
description='Export cameras',
|
||||
|
@ -440,14 +456,22 @@ class ExportGLTF2_Base:
|
|||
except Exception:
|
||||
pass
|
||||
|
||||
self.has_active_extenions = len(extension_panel_unregister_functors) > 0
|
||||
self.has_active_extensions = len(extension_panel_unregister_functors) > 0
|
||||
return ExportHelper.invoke(self, context, event)
|
||||
|
||||
def save_settings(self, context):
|
||||
# find all export_ props
|
||||
# find all props to save
|
||||
exceptional = [
|
||||
# options that don't start with 'export_'
|
||||
'use_selection',
|
||||
'use_mesh_edges',
|
||||
'use_mesh_vertices',
|
||||
]
|
||||
all_props = self.properties
|
||||
export_props = {x: getattr(self, x) for x in dir(all_props)
|
||||
if (x.startswith("export_") or x == "use_selection") and all_props.get(x) is not None}
|
||||
export_props = {
|
||||
x: getattr(self, x) for x in dir(all_props)
|
||||
if (x.startswith("export_") or x in exceptional) and all_props.get(x) is not None
|
||||
}
|
||||
|
||||
context.scene[self.scene_key] = export_props
|
||||
|
||||
|
@ -479,6 +503,8 @@ class ExportGLTF2_Base:
|
|||
export_settings['gltf_texcoords'] = self.export_texcoords
|
||||
export_settings['gltf_normals'] = self.export_normals
|
||||
export_settings['gltf_tangents'] = self.export_tangents and self.export_normals
|
||||
export_settings['gltf_loose_edges'] = self.use_mesh_edges
|
||||
export_settings['gltf_loose_points'] = self.use_mesh_vertices
|
||||
|
||||
if self.is_draco_available:
|
||||
export_settings['gltf_draco_mesh_compression'] = self.export_draco_mesh_compression_enable
|
||||
|
@ -692,6 +718,11 @@ class GLTF_PT_export_geometry(bpy.types.Panel):
|
|||
col.active = operator.export_normals
|
||||
col.prop(operator, 'export_tangents')
|
||||
layout.prop(operator, 'export_colors')
|
||||
|
||||
col = layout.column()
|
||||
col.prop(operator, 'use_mesh_edges')
|
||||
col.prop(operator, 'use_mesh_vertices')
|
||||
|
||||
layout.prop(operator, 'export_materials')
|
||||
col = layout.column()
|
||||
col.active = operator.export_materials == "EXPORT"
|
||||
|
@ -881,7 +912,7 @@ class GLTF_PT_export_user_extensions(bpy.types.Panel):
|
|||
sfile = context.space_data
|
||||
operator = sfile.active_operator
|
||||
|
||||
return operator.bl_idname == "EXPORT_SCENE_OT_gltf" and operator.has_active_extenions
|
||||
return operator.bl_idname == "EXPORT_SCENE_OT_gltf" and operator.has_active_extensions
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -283,6 +283,90 @@ def extract_primitives(glTF, blender_mesh, library, blender_object, blender_vert
|
|||
'material': material_idx,
|
||||
})
|
||||
|
||||
if export_settings['gltf_loose_edges']:
|
||||
# Find loose edges
|
||||
loose_edges = [e for e in blender_mesh.edges if e.is_loose]
|
||||
blender_idxs = [vi for e in loose_edges for vi in e.vertices]
|
||||
|
||||
if blender_idxs:
|
||||
# Export one glTF vert per unique Blender vert in a loose edge
|
||||
blender_idxs = np.array(blender_idxs, dtype=np.uint32)
|
||||
blender_idxs, indices = np.unique(blender_idxs, return_inverse=True)
|
||||
|
||||
attributes = {}
|
||||
|
||||
attributes['POSITION'] = locs[blender_idxs]
|
||||
|
||||
for morph_i, vs in enumerate(morph_locs):
|
||||
attributes['MORPH_POSITION_%d' % morph_i] = vs[blender_idxs]
|
||||
|
||||
if skin:
|
||||
joints = [[] for _ in range(num_joint_sets)]
|
||||
weights = [[] for _ in range(num_joint_sets)]
|
||||
|
||||
for vi in blender_idxs:
|
||||
bones = vert_bones[vi]
|
||||
for j in range(0, 4 * num_joint_sets):
|
||||
if j < len(bones):
|
||||
joint, weight = bones[j]
|
||||
else:
|
||||
joint, weight = 0, 0.0
|
||||
joints[j//4].append(joint)
|
||||
weights[j//4].append(weight)
|
||||
|
||||
for i, (js, ws) in enumerate(zip(joints, weights)):
|
||||
attributes['JOINTS_%d' % i] = js
|
||||
attributes['WEIGHTS_%d' % i] = ws
|
||||
|
||||
primitives.append({
|
||||
'attributes': attributes,
|
||||
'indices': indices,
|
||||
'mode': 1, # LINES
|
||||
'material': 0,
|
||||
})
|
||||
|
||||
if export_settings['gltf_loose_points']:
|
||||
# Find loose points
|
||||
verts_in_edge = set(vi for e in blender_mesh.edges for vi in e.vertices)
|
||||
blender_idxs = [
|
||||
vi for vi, _ in enumerate(blender_mesh.vertices)
|
||||
if vi not in verts_in_edge
|
||||
]
|
||||
|
||||
if blender_idxs:
|
||||
blender_idxs = np.array(blender_idxs, dtype=np.uint32)
|
||||
|
||||
attributes = {}
|
||||
|
||||
attributes['POSITION'] = locs[blender_idxs]
|
||||
|
||||
for morph_i, vs in enumerate(morph_locs):
|
||||
attributes['MORPH_POSITION_%d' % morph_i] = vs[blender_idxs]
|
||||
|
||||
if skin:
|
||||
joints = [[] for _ in range(num_joint_sets)]
|
||||
weights = [[] for _ in range(num_joint_sets)]
|
||||
|
||||
for vi in blender_idxs:
|
||||
bones = vert_bones[vi]
|
||||
for j in range(0, 4 * num_joint_sets):
|
||||
if j < len(bones):
|
||||
joint, weight = bones[j]
|
||||
else:
|
||||
joint, weight = 0, 0.0
|
||||
joints[j//4].append(joint)
|
||||
weights[j//4].append(weight)
|
||||
|
||||
for i, (js, ws) in enumerate(zip(joints, weights)):
|
||||
attributes['JOINTS_%d' % i] = js
|
||||
attributes['WEIGHTS_%d' % i] = ws
|
||||
|
||||
primitives.append({
|
||||
'attributes': attributes,
|
||||
'mode': 0, # POINTS
|
||||
'material': 0,
|
||||
})
|
||||
|
||||
print_console('INFO', 'Primitives created: %d' % len(primitives))
|
||||
|
||||
return primitives
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -56,7 +56,10 @@ def gather_animation_sampler(channels: typing.Tuple[bpy.types.FCurve],
|
|||
bake_channel,
|
||||
driver_obj,
|
||||
export_settings)
|
||||
|
||||
if blender_object.parent is not None:
|
||||
matrix_parent_inverse = blender_object.matrix_parent_inverse.copy().freeze()
|
||||
else:
|
||||
matrix_parent_inverse = mathutils.Matrix.Identity(4).freeze()
|
||||
|
||||
sampler = gltf2_io.AnimationSampler(
|
||||
extensions=__gather_extensions(channels, blender_object_if_armature, export_settings, bake_bone, bake_channel),
|
||||
|
@ -64,7 +67,8 @@ def gather_animation_sampler(channels: typing.Tuple[bpy.types.FCurve],
|
|||
input=__gather_input(channels, blender_object_if_armature, non_keyed_values,
|
||||
bake_bone, bake_channel, bake_range_start, bake_range_end, action_name, driver_obj, export_settings),
|
||||
interpolation=__gather_interpolation(channels, blender_object_if_armature, export_settings, bake_bone, bake_channel),
|
||||
output=__gather_output(channels, blender_object.matrix_parent_inverse.copy().freeze(),
|
||||
output=__gather_output(channels,
|
||||
matrix_parent_inverse,
|
||||
blender_object_if_armature,
|
||||
non_keyed_values,
|
||||
bake_bone,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -54,7 +54,7 @@ def gather_primitives(
|
|||
material_idx = internal_primitive['material']
|
||||
material = None
|
||||
|
||||
if export_settings['gltf_materials'] == "EXPORT":
|
||||
if export_settings['gltf_materials'] == "EXPORT" and material_idx is not None:
|
||||
blender_material = None
|
||||
if material_names:
|
||||
i = material_idx if material_idx < len(material_names) else -1
|
||||
|
@ -73,7 +73,7 @@ def gather_primitives(
|
|||
extras=None,
|
||||
indices=internal_primitive['indices'],
|
||||
material=material,
|
||||
mode=None,
|
||||
mode=internal_primitive['mode'],
|
||||
targets=internal_primitive['targets']
|
||||
)
|
||||
primitives.append(primitive)
|
||||
|
@ -101,7 +101,8 @@ def __gather_cache_primitives(
|
|||
primitive = {
|
||||
"attributes": __gather_attributes(internal_primitive, blender_mesh, modifiers, export_settings),
|
||||
"indices": __gather_indices(internal_primitive, blender_mesh, modifiers, export_settings),
|
||||
"material": internal_primitive['material'],
|
||||
"mode": internal_primitive.get('mode'),
|
||||
"material": internal_primitive.get('material'),
|
||||
"targets": __gather_targets(internal_primitive, blender_mesh, modifiers, export_settings)
|
||||
}
|
||||
primitives.append(primitive)
|
||||
|
@ -109,7 +110,9 @@ def __gather_cache_primitives(
|
|||
return primitives
|
||||
|
||||
def __gather_indices(blender_primitive, blender_mesh, modifiers, export_settings):
|
||||
indices = blender_primitive['indices']
|
||||
indices = blender_primitive.get('indices')
|
||||
if indices is None:
|
||||
return None
|
||||
|
||||
# NOTE: Values used by some graphics APIs as "primitive restart" values are disallowed.
|
||||
# Specifically, the values 65535 (in UINT16) and 4294967295 (in UINT32) cannot be used as indices.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -85,6 +85,10 @@ def __encode_primitive(primitive, dll, export_settings):
|
|||
attributes = primitive.attributes
|
||||
indices = primitive.indices
|
||||
|
||||
# Only do TRIANGLES primitives
|
||||
if primitive.mode not in [None, 4]:
|
||||
return
|
||||
|
||||
if 'POSITION' not in attributes:
|
||||
print_console('WARNING', 'Draco encoder: Primitive without positions encountered. Skipping.')
|
||||
return
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2018-2019 The glTF-Blender-IO authors.
|
||||
# Copyright 2018-2021 The glTF-Blender-IO authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
|
||||
bl_info = {
|
||||
|
@ -29,7 +29,7 @@ bl_info = {
|
|||
"author": "Nutti, Mifth, Jace Priester, kgeogeo, mem, imdjs"
|
||||
"Keith (Wahooney) Boshoff, McBuff, MaxRobinot, "
|
||||
"Alexander Milovsky, Dusan Stevanovic, MatthiasThDs",
|
||||
"version": (6, 4, 0),
|
||||
"version": (6, 5, 0),
|
||||
"blender": (2, 80, 0),
|
||||
"location": "See Add-ons Preferences",
|
||||
"description": "UV Toolset. See Add-ons Preferences for details",
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
from collections import defaultdict
|
||||
from pprint import pprint
|
||||
|
@ -333,7 +333,7 @@ def get_uvimg_editor_board_size(area):
|
|||
return (255.0, 255.0)
|
||||
|
||||
|
||||
def calc_polygon_2d_area(points):
|
||||
def calc_tris_2d_area(points):
|
||||
area = 0.0
|
||||
for i, p1 in enumerate(points):
|
||||
p2 = points[(i + 1) % len(points)]
|
||||
|
@ -345,7 +345,7 @@ def calc_polygon_2d_area(points):
|
|||
return fabs(0.5 * area)
|
||||
|
||||
|
||||
def calc_polygon_3d_area(points):
|
||||
def calc_tris_3d_area(points):
|
||||
area = 0.0
|
||||
for i, p1 in enumerate(points):
|
||||
p2 = points[(i + 1) % len(points)]
|
||||
|
@ -395,6 +395,23 @@ def get_faces_list(bm, method, only_selected):
|
|||
return faces_list
|
||||
|
||||
|
||||
def measure_all_faces_mesh_area(bm):
|
||||
if compat.check_version(2, 80, 0) >= 0:
|
||||
triangle_loops = bm.calc_loop_triangles()
|
||||
else:
|
||||
triangle_loops = bm.calc_tessface()
|
||||
|
||||
areas = {face: 0.0 for face in bm.faces}
|
||||
|
||||
for loops in triangle_loops:
|
||||
face = loops[0].face
|
||||
area = areas[face]
|
||||
area += calc_tris_3d_area([l.vert.co for l in loops])
|
||||
areas[face] = area
|
||||
|
||||
return areas
|
||||
|
||||
|
||||
def measure_mesh_area(obj, calc_method, only_selected):
|
||||
bm = bmesh.from_edit_mesh(obj.data)
|
||||
if check_version(2, 73, 0) >= 0:
|
||||
|
@ -406,17 +423,18 @@ def measure_mesh_area(obj, calc_method, only_selected):
|
|||
|
||||
areas = []
|
||||
for faces in faces_list:
|
||||
areas.append(measure_mesh_area_from_faces(faces))
|
||||
areas.append(measure_mesh_area_from_faces(bm, faces))
|
||||
|
||||
return areas
|
||||
|
||||
|
||||
def measure_mesh_area_from_faces(faces):
|
||||
def measure_mesh_area_from_faces(bm, faces):
|
||||
face_areas = measure_all_faces_mesh_area(bm)
|
||||
|
||||
mesh_area = 0.0
|
||||
for f in faces:
|
||||
verts = [l.vert.co for l in f.loops]
|
||||
f_mesh_area = calc_polygon_3d_area(verts)
|
||||
mesh_area = mesh_area + f_mesh_area
|
||||
if f in face_areas:
|
||||
mesh_area += face_areas[f]
|
||||
|
||||
return mesh_area
|
||||
|
||||
|
@ -486,12 +504,34 @@ def find_images(obj, face=None, tex_layer=None):
|
|||
return images
|
||||
|
||||
|
||||
def measure_uv_area_from_faces(obj, faces, uv_layer, tex_layer,
|
||||
def measure_all_faces_uv_area(bm, uv_layer):
|
||||
if compat.check_version(2, 80, 0) >= 0:
|
||||
triangle_loops = bm.calc_loop_triangles()
|
||||
else:
|
||||
triangle_loops = bm.calc_tessface()
|
||||
|
||||
areas = {face: 0.0 for face in bm.faces}
|
||||
|
||||
for loops in triangle_loops:
|
||||
face = loops[0].face
|
||||
area = areas[face]
|
||||
area += calc_tris_2d_area([l[uv_layer].uv for l in loops])
|
||||
areas[face] = area
|
||||
|
||||
return areas
|
||||
|
||||
|
||||
def measure_uv_area_from_faces(obj, bm, faces, uv_layer, tex_layer,
|
||||
tex_selection_method, tex_size):
|
||||
|
||||
face_areas = measure_all_faces_uv_area(bm, uv_layer)
|
||||
|
||||
uv_area = 0.0
|
||||
for f in faces:
|
||||
uvs = [l[uv_layer].uv for l in f.loops]
|
||||
f_uv_area = calc_polygon_2d_area(uvs)
|
||||
if f not in face_areas:
|
||||
continue
|
||||
|
||||
f_uv_area = face_areas[f]
|
||||
|
||||
# user specified
|
||||
if tex_selection_method == 'USER_SPECIFIED' and tex_size is not None:
|
||||
|
@ -547,8 +587,8 @@ def measure_uv_area_from_faces(obj, faces, uv_layer, tex_layer,
|
|||
return uv_area
|
||||
|
||||
|
||||
def measure_uv_area(obj, calc_method, tex_selection_method, tex_size,
|
||||
only_selected):
|
||||
def measure_uv_area(obj, calc_method, tex_selection_method,
|
||||
tex_size, only_selected):
|
||||
bm = bmesh.from_edit_mesh(obj.data)
|
||||
if check_version(2, 73, 0) >= 0:
|
||||
bm.verts.ensure_lookup_table()
|
||||
|
@ -565,7 +605,8 @@ def measure_uv_area(obj, calc_method, tex_selection_method, tex_size,
|
|||
uv_areas = []
|
||||
for faces in faces_list:
|
||||
uv_area = measure_uv_area_from_faces(
|
||||
obj, faces, uv_layer, tex_layer, tex_selection_method, tex_size)
|
||||
obj, bm, faces, uv_layer, tex_layer,
|
||||
tex_selection_method, tex_size)
|
||||
if uv_area is None:
|
||||
return None
|
||||
uv_areas.append(uv_area)
|
||||
|
@ -946,7 +987,8 @@ class RingBuffer:
|
|||
|
||||
# clip: reference polygon
|
||||
# subject: tested polygon
|
||||
def __do_weiler_atherton_cliping(clip_uvs, subject_uvs, mode):
|
||||
def __do_weiler_atherton_cliping(clip_uvs, subject_uvs, mode,
|
||||
same_polygon_threshold):
|
||||
|
||||
clip_uvs = RingBuffer(clip_uvs)
|
||||
if __is_polygon_flipped(clip_uvs):
|
||||
|
@ -961,7 +1003,7 @@ def __do_weiler_atherton_cliping(clip_uvs, subject_uvs, mode):
|
|||
debug_print(subject_uvs)
|
||||
|
||||
# check if clip and subject is overlapped completely
|
||||
if __is_polygon_same(clip_uvs, subject_uvs):
|
||||
if __is_polygon_same(clip_uvs, subject_uvs, same_polygon_threshold):
|
||||
polygons = [subject_uvs.as_list()]
|
||||
debug_print("===== Polygons Overlapped Completely =====")
|
||||
debug_print(polygons)
|
||||
|
@ -1193,26 +1235,31 @@ def get_uv_editable_objects(context):
|
|||
return objs
|
||||
|
||||
|
||||
def get_overlapped_uv_info(bm_list, faces_list, uv_layer_list, mode):
|
||||
def get_overlapped_uv_info(bm_list, faces_list, uv_layer_list,
|
||||
mode, same_polygon_threshold=0.0000001):
|
||||
# at first, check island overlapped
|
||||
isl = []
|
||||
for bm, uv_layer, faces in zip(bm_list, uv_layer_list, faces_list):
|
||||
info = get_island_info_from_faces(bm, faces, uv_layer)
|
||||
isl.extend([(i, uv_layer) for i in info])
|
||||
isl.extend([(i, uv_layer, bm) for i in info])
|
||||
|
||||
overlapped_isl_pairs = []
|
||||
overlapped_uv_layer_pairs = []
|
||||
for i, (i1, uv_layer_1) in enumerate(isl):
|
||||
for i2, uv_layer_2 in isl[i + 1:]:
|
||||
overlapped_bm_paris = []
|
||||
for i, (i1, uv_layer_1, bm_1) in enumerate(isl):
|
||||
for i2, uv_layer_2, bm_2 in isl[i + 1:]:
|
||||
if (i1["max"].x < i2["min"].x) or (i2["max"].x < i1["min"].x) or \
|
||||
(i1["max"].y < i2["min"].y) or (i2["max"].y < i1["min"].y):
|
||||
continue
|
||||
overlapped_isl_pairs.append([i1, i2])
|
||||
overlapped_uv_layer_pairs.append([uv_layer_1, uv_layer_2])
|
||||
overlapped_bm_paris.append([bm_1, bm_2])
|
||||
|
||||
# next, check polygon overlapped
|
||||
overlapped_uvs = []
|
||||
for oip, uvlp in zip(overlapped_isl_pairs, overlapped_uv_layer_pairs):
|
||||
for oip, uvlp, bmp in zip(overlapped_isl_pairs,
|
||||
overlapped_uv_layer_pairs,
|
||||
overlapped_bm_paris):
|
||||
for clip in oip[0]["faces"]:
|
||||
f_clip = clip["face"]
|
||||
clip_uvs = [l[uvlp[0]].uv.copy() for l in f_clip.loops]
|
||||
|
@ -1228,11 +1275,13 @@ def get_overlapped_uv_info(bm_list, faces_list, uv_layer_list, mode):
|
|||
|
||||
subject_uvs = [l[uvlp[1]].uv.copy() for l in f_subject.loops]
|
||||
# slow operation, apply Weiler-Atherton cliping algorithm
|
||||
result, polygons = __do_weiler_atherton_cliping(clip_uvs,
|
||||
subject_uvs,
|
||||
mode)
|
||||
result, polygons = \
|
||||
__do_weiler_atherton_cliping(clip_uvs, subject_uvs,
|
||||
mode, same_polygon_threshold)
|
||||
if result:
|
||||
overlapped_uvs.append({"clip_face": f_clip,
|
||||
overlapped_uvs.append({"clip_bmesh": bmp[0],
|
||||
"subject_bmesh": bmp[1],
|
||||
"clip_face": f_clip,
|
||||
"subject_face": f_subject,
|
||||
"clip_uv_layer": uvlp[0],
|
||||
"subject_uv_layer": uvlp[1],
|
||||
|
@ -1242,14 +1291,15 @@ def get_overlapped_uv_info(bm_list, faces_list, uv_layer_list, mode):
|
|||
return overlapped_uvs
|
||||
|
||||
|
||||
def get_flipped_uv_info(faces_list, uv_layer_list):
|
||||
def get_flipped_uv_info(bm_list, faces_list, uv_layer_list):
|
||||
flipped_uvs = []
|
||||
for faces, uv_layer in zip(faces_list, uv_layer_list):
|
||||
for bm, faces, uv_layer in zip(bm_list, faces_list, uv_layer_list):
|
||||
for f in faces:
|
||||
polygon = RingBuffer([l[uv_layer].uv.copy() for l in f.loops])
|
||||
if __is_polygon_flipped(polygon):
|
||||
uvs = [l[uv_layer].uv.copy() for l in f.loops]
|
||||
flipped_uvs.append({"face": f,
|
||||
flipped_uvs.append({"bmesh": bm,
|
||||
"face": f,
|
||||
"uv_layer": uv_layer,
|
||||
"uvs": uvs,
|
||||
"polygons": [polygon.as_list()]})
|
||||
|
@ -1257,7 +1307,7 @@ def get_flipped_uv_info(faces_list, uv_layer_list):
|
|||
return flipped_uvs
|
||||
|
||||
|
||||
def __is_polygon_same(points1, points2):
|
||||
def __is_polygon_same(points1, points2, threshold):
|
||||
if len(points1) != len(points2):
|
||||
return False
|
||||
|
||||
|
@ -1267,7 +1317,7 @@ def __is_polygon_same(points1, points2):
|
|||
for p1 in pts1:
|
||||
for p2 in pts2:
|
||||
diff = p2 - p1
|
||||
if diff.length < 0.0000001:
|
||||
if diff.length < threshold:
|
||||
pts2.remove(p2)
|
||||
break
|
||||
else:
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
if "bpy" in locals():
|
||||
import importlib
|
||||
|
|
|
@ -159,6 +159,11 @@ def glEnd():
|
|||
#shader = gpu.shader.from_builtin('2D_IMAGE')
|
||||
vert_shader, frag_shader = _get_transparency_shader()
|
||||
shader = gpu.types.GPUShader(vert_shader, frag_shader)
|
||||
elif inst.get_dims() == 3:
|
||||
if len(tex_coords) == 0:
|
||||
shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
|
||||
else:
|
||||
raise NotImplemented("Texture is not supported in get_dims() == 3")
|
||||
else:
|
||||
raise NotImplemented("get_dims() != 2")
|
||||
|
||||
|
@ -223,6 +228,12 @@ def glVertex2f(x, y):
|
|||
inst.set_dims(2)
|
||||
|
||||
|
||||
def glVertex3f(x, y, z):
|
||||
inst = InternalData.get_instance()
|
||||
inst.add_vert([x, y, z])
|
||||
inst.set_dims(3)
|
||||
|
||||
|
||||
def glTexCoord2f(u, v):
|
||||
inst = InternalData.get_instance()
|
||||
inst.add_tex_coord([u, v])
|
||||
|
@ -234,6 +245,7 @@ GL_INT = bgl.GL_INT
|
|||
GL_SCISSOR_BOX = bgl.GL_SCISSOR_BOX
|
||||
GL_TEXTURE_2D = bgl.GL_TEXTURE_2D
|
||||
GL_TEXTURE0 = bgl.GL_TEXTURE0
|
||||
GL_DEPTH_TEST = bgl.GL_DEPTH_TEST
|
||||
|
||||
GL_TEXTURE_MIN_FILTER = 0
|
||||
GL_TEXTURE_MAG_FILTER = 0
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
if "bpy" in locals():
|
||||
import importlib
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "imdjs, Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import math
|
||||
from math import atan2, tan, sin, cos
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import bpy
|
||||
from mathutils import Vector
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Dusan Stevanovic, Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
|
||||
import math
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>, Jace Priester"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import bmesh
|
||||
import bpy.utils
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import bmesh
|
||||
import bpy
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "imdjs, Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import math
|
||||
from math import atan2, sin, cos
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import bpy
|
||||
import bmesh
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Keith (Wahooney) Boshoff, Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import bpy
|
||||
from bpy.props import (
|
||||
|
@ -30,7 +30,7 @@ from bpy.props import (
|
|||
BoolProperty,
|
||||
)
|
||||
import bmesh
|
||||
from mathutils import Vector
|
||||
from mathutils import Vector, Euler
|
||||
|
||||
from ..utils.bl_class_registry import BlClassRegistry
|
||||
from ..utils.property_class_registry import PropertyClassRegistry
|
||||
|
@ -65,15 +65,15 @@ def _is_vector_similar(v1, v2, error):
|
|||
return within_err_x and within_err_y and within_err_z
|
||||
|
||||
|
||||
def _mirror_uvs(uv_layer, src, dst, axis, error):
|
||||
def _mirror_uvs(uv_layer, src, dst, axis, error, transformed):
|
||||
"""
|
||||
Copy UV coordinates from one UV face to another
|
||||
"""
|
||||
for sl in src.loops:
|
||||
suv = sl[uv_layer].uv.copy()
|
||||
svco = sl.vert.co.copy()
|
||||
svco = transformed[sl.vert].copy()
|
||||
for dl in dst.loops:
|
||||
dvco = dl.vert.co.copy()
|
||||
dvco = transformed[dl.vert].copy()
|
||||
if axis == 'X':
|
||||
dvco.x = -dvco.x
|
||||
elif axis == 'Y':
|
||||
|
@ -85,13 +85,14 @@ def _mirror_uvs(uv_layer, src, dst, axis, error):
|
|||
dl[uv_layer].uv = suv.copy()
|
||||
|
||||
|
||||
def _get_face_center(face):
|
||||
def _get_face_center(face, transformed):
|
||||
"""
|
||||
Get center coordinate of the face
|
||||
"""
|
||||
center = Vector((0.0, 0.0, 0.0))
|
||||
for v in face.verts:
|
||||
center = center + v.co
|
||||
tv = transformed[v]
|
||||
center = center + tv
|
||||
|
||||
return center / len(face.verts)
|
||||
|
||||
|
@ -117,11 +118,22 @@ class _Properties:
|
|||
description="Mirror Axis",
|
||||
default='X'
|
||||
)
|
||||
scene.muv_mirror_uv_origin = EnumProperty(
|
||||
items=(
|
||||
('WORLD', "World", "World"),
|
||||
("GLOBAL", "Global", "Global"),
|
||||
('LOCAL', "Local", "Local"),
|
||||
),
|
||||
name="Origin",
|
||||
description="Origin of the mirror operation",
|
||||
default='LOCAL'
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def del_props(cls, scene):
|
||||
del scene.muv_mirror_uv_enabled
|
||||
del scene.muv_mirror_uv_axis
|
||||
del scene.muv_mirror_uv_origin
|
||||
|
||||
|
||||
@BlClassRegistry()
|
||||
|
@ -154,6 +166,16 @@ class MUV_OT_MirrorUV(bpy.types.Operator):
|
|||
soft_min=0.0,
|
||||
soft_max=1.0
|
||||
)
|
||||
origin = EnumProperty(
|
||||
items=(
|
||||
('WORLD', "World", "World"),
|
||||
("GLOBAL", "Global", "Global"),
|
||||
('LOCAL', "Local", "Local"),
|
||||
),
|
||||
name="Origin",
|
||||
description="Origin of the mirror operation",
|
||||
default='LOCAL'
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@ -162,6 +184,51 @@ class MUV_OT_MirrorUV(bpy.types.Operator):
|
|||
return True
|
||||
return _is_valid_context(context)
|
||||
|
||||
def _get_world_vertices(self, obj, bm):
|
||||
# Get world orientation matrix.
|
||||
world_orientation_mat = obj.matrix_world
|
||||
|
||||
# Move to local to world.
|
||||
transformed = {}
|
||||
for v in bm.verts:
|
||||
transformed[v] = compat.matmul(world_orientation_mat, v.co)
|
||||
|
||||
return transformed
|
||||
|
||||
def _get_global_vertices(self, obj, bm):
|
||||
# Get world rotation matrix.
|
||||
eular = Euler(obj.rotation_euler)
|
||||
rotation_mat = eular.to_matrix()
|
||||
|
||||
# Get center location of all verticies.
|
||||
center_location = Vector((0.0, 0.0, 0.0))
|
||||
for v in bm.verts:
|
||||
center_location += v.co
|
||||
center_location /= len(bm.verts)
|
||||
|
||||
# Move to local to global.
|
||||
transformed = {}
|
||||
for v in bm.verts:
|
||||
transformed[v] = compat.matmul(rotation_mat, v.co)
|
||||
transformed[v] -= center_location
|
||||
|
||||
return transformed
|
||||
|
||||
def _get_local_vertices(self, _, bm):
|
||||
transformed = {}
|
||||
|
||||
# Get center location of all verticies.
|
||||
center_location = Vector((0.0, 0.0, 0.0))
|
||||
for v in bm.verts:
|
||||
center_location += v.co
|
||||
center_location /= len(bm.verts)
|
||||
|
||||
for v in bm.verts:
|
||||
transformed[v] = v.co.copy()
|
||||
transformed[v] -= center_location
|
||||
|
||||
return transformed
|
||||
|
||||
def execute(self, context):
|
||||
objs = common.get_uv_editable_objects(context)
|
||||
|
||||
|
@ -180,6 +247,13 @@ class MUV_OT_MirrorUV(bpy.types.Operator):
|
|||
return {'CANCELLED'}
|
||||
uv_layer = bm.loops.layers.uv.verify()
|
||||
|
||||
if self.origin == 'WORLD':
|
||||
transformed_verts = self._get_world_vertices(obj, bm)
|
||||
elif self.origin == 'GLOBAL':
|
||||
transformed_verts = self._get_global_vertices(obj, bm)
|
||||
elif self.origin == 'LOCAL':
|
||||
transformed_verts = self._get_local_vertices(obj, bm)
|
||||
|
||||
faces = [f for f in bm.faces if f.select]
|
||||
for f_dst in faces:
|
||||
count = len(f_dst.verts)
|
||||
|
@ -191,8 +265,8 @@ class MUV_OT_MirrorUV(bpy.types.Operator):
|
|||
continue
|
||||
|
||||
# test if the vertices x values are the same sign
|
||||
dst = _get_face_center(f_dst)
|
||||
src = _get_face_center(f_src)
|
||||
dst = _get_face_center(f_dst, transformed_verts)
|
||||
src = _get_face_center(f_src, transformed_verts)
|
||||
if (dst.x > 0 and src.x > 0) or (dst.x < 0 and src.x < 0):
|
||||
continue
|
||||
|
||||
|
@ -207,7 +281,7 @@ class MUV_OT_MirrorUV(bpy.types.Operator):
|
|||
# do mirror UV
|
||||
if _is_vector_similar(dst, src, error):
|
||||
_mirror_uvs(uv_layer, f_src, f_dst,
|
||||
self.axis, self.error)
|
||||
self.axis, self.error, transformed_verts)
|
||||
|
||||
bmesh.update_edit_mesh(obj.data)
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "kgeogeo, mem, Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import bpy
|
||||
from bpy.props import BoolProperty
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
from math import fabs
|
||||
|
||||
|
@ -151,7 +151,7 @@ class _Properties:
|
|||
name="Allowable Center Deviation",
|
||||
description="Allowable center deviation to judge same UV island",
|
||||
min=0.000001,
|
||||
max=0.1,
|
||||
max=10.0,
|
||||
default=(0.001, 0.001),
|
||||
size=2
|
||||
)
|
||||
|
@ -159,7 +159,7 @@ class _Properties:
|
|||
name="Allowable Size Deviation",
|
||||
description="Allowable sizse deviation to judge same UV island",
|
||||
min=0.000001,
|
||||
max=0.1,
|
||||
max=10.0,
|
||||
default=(0.001, 0.001),
|
||||
size=2
|
||||
)
|
||||
|
@ -196,12 +196,13 @@ class MUV_OT_PackUV(bpy.types.Operator):
|
|||
description="Margin used by default pack UV function",
|
||||
min=0,
|
||||
max=1,
|
||||
default=0.001)
|
||||
default=0.001
|
||||
)
|
||||
allowable_center_deviation = FloatVectorProperty(
|
||||
name="Allowable Center Deviation",
|
||||
description="Allowable center deviation to judge same UV island",
|
||||
min=0.000001,
|
||||
max=0.1,
|
||||
max=10.0,
|
||||
default=(0.001, 0.001),
|
||||
size=2
|
||||
)
|
||||
|
@ -209,7 +210,7 @@ class MUV_OT_PackUV(bpy.types.Operator):
|
|||
name="Allowable Size Deviation",
|
||||
description="Allowable sizse deviation to judge same UV island",
|
||||
min=0.000001,
|
||||
max=0.1,
|
||||
max=10.0,
|
||||
default=(0.001, 0.001),
|
||||
size=2
|
||||
)
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import bpy
|
||||
from bpy.props import StringProperty, EnumProperty, BoolProperty
|
||||
|
|
|
@ -20,16 +20,17 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import bpy
|
||||
from bpy.props import BoolProperty
|
||||
from bpy.props import BoolProperty, FloatProperty, EnumProperty
|
||||
import bmesh
|
||||
|
||||
from .. import common
|
||||
from ..utils.bl_class_registry import BlClassRegistry
|
||||
from ..utils.property_class_registry import PropertyClassRegistry
|
||||
from ..utils import compatibility as compat
|
||||
|
||||
|
||||
def _is_valid_context(context):
|
||||
|
@ -61,13 +62,38 @@ class _Properties:
|
|||
description="Select UV is enabled",
|
||||
default=False
|
||||
)
|
||||
scene.muv_select_uv_same_polygon_threshold = FloatProperty(
|
||||
name="Same Polygon Threshold",
|
||||
description="Threshold to distinguish same polygons",
|
||||
default=0.000001,
|
||||
min=0.000001,
|
||||
max=0.01,
|
||||
step=0.00001
|
||||
)
|
||||
scene.muv_select_uv_selection_method = EnumProperty(
|
||||
name="Selection Method",
|
||||
description="How to select faces which have overlapped UVs",
|
||||
items=[
|
||||
('EXTEND', "Extend",
|
||||
"Select faces without unselecting selected faces"),
|
||||
('RESET', "Reset", "Select faces and unselect selected faces"),
|
||||
],
|
||||
default='RESET'
|
||||
)
|
||||
scene.muv_select_uv_sync_mesh_selection = BoolProperty(
|
||||
name="Sync Mesh Selection",
|
||||
description="Select the mesh's faces as well as UV's faces",
|
||||
default=False
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def del_props(cls, scene):
|
||||
del scene.muv_select_uv_enabled
|
||||
del scene.muv_select_uv_same_polygon_threshold
|
||||
|
||||
|
||||
@BlClassRegistry()
|
||||
@compat.make_annotations
|
||||
class MUV_OT_SelectUV_SelectOverlapped(bpy.types.Operator):
|
||||
"""
|
||||
Operation class: Select faces which have overlapped UVs
|
||||
|
@ -78,6 +104,30 @@ class MUV_OT_SelectUV_SelectOverlapped(bpy.types.Operator):
|
|||
bl_description = "Select faces which have overlapped UVs"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
same_polygon_threshold = FloatProperty(
|
||||
name="Same Polygon Threshold",
|
||||
description="Threshold to distinguish same polygons",
|
||||
default=0.000001,
|
||||
min=0.000001,
|
||||
max=0.01,
|
||||
step=0.00001
|
||||
)
|
||||
selection_method = EnumProperty(
|
||||
name="Selection Method",
|
||||
description="How to select faces which have overlapped UVs",
|
||||
items=[
|
||||
('EXTEND', "Extend",
|
||||
"Select faces without unselecting selected faces"),
|
||||
('RESET', "Reset", "Select faces and unselect selected faces"),
|
||||
],
|
||||
default='RESET'
|
||||
)
|
||||
sync_mesh_selection = BoolProperty(
|
||||
name="Sync Mesh Selection",
|
||||
description="Select mesh's faces as well as UV's faces",
|
||||
default=False
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
# we can not get area/space/region from console
|
||||
|
@ -85,6 +135,12 @@ class MUV_OT_SelectUV_SelectOverlapped(bpy.types.Operator):
|
|||
return True
|
||||
return _is_valid_context(context)
|
||||
|
||||
@staticmethod
|
||||
def setup_argument(ops, scene):
|
||||
ops.same_polygon_threshold = scene.muv_select_uv_same_polygon_threshold
|
||||
ops.selection_method = scene.muv_select_uv_selection_method
|
||||
ops.sync_mesh_selection = scene.muv_select_uv_sync_mesh_selection
|
||||
|
||||
def execute(self, context):
|
||||
objs = common.get_uv_editable_objects(context)
|
||||
|
||||
|
@ -105,13 +161,29 @@ class MUV_OT_SelectUV_SelectOverlapped(bpy.types.Operator):
|
|||
uv_layer_list.append(uv_layer)
|
||||
faces_list.append(sel_faces)
|
||||
|
||||
overlapped_info = common.get_overlapped_uv_info(bm_list, faces_list,
|
||||
uv_layer_list, 'FACE')
|
||||
overlapped_info = common.get_overlapped_uv_info(
|
||||
bm_list, faces_list, uv_layer_list, 'FACE',
|
||||
self.same_polygon_threshold)
|
||||
|
||||
if self.selection_method == 'RESET':
|
||||
if context.tool_settings.use_uv_select_sync:
|
||||
for faces in faces_list:
|
||||
for f in faces:
|
||||
f.select = False
|
||||
else:
|
||||
for uv_layer, faces in zip(uv_layer_list, faces_list):
|
||||
for f in faces:
|
||||
if self.sync_mesh_selection:
|
||||
f.select = False
|
||||
for l in f.loops:
|
||||
l[uv_layer].select = False
|
||||
|
||||
for info in overlapped_info:
|
||||
if context.tool_settings.use_uv_select_sync:
|
||||
info["subject_face"].select = True
|
||||
else:
|
||||
if self.sync_mesh_selection:
|
||||
info["subject_face"].select = True
|
||||
for l in info["subject_face"].loops:
|
||||
l[info["subject_uv_layer"]].select = True
|
||||
|
||||
|
@ -122,6 +194,7 @@ class MUV_OT_SelectUV_SelectOverlapped(bpy.types.Operator):
|
|||
|
||||
|
||||
@BlClassRegistry()
|
||||
@compat.make_annotations
|
||||
class MUV_OT_SelectUV_SelectFlipped(bpy.types.Operator):
|
||||
"""
|
||||
Operation class: Select faces which have flipped UVs
|
||||
|
@ -132,6 +205,22 @@ class MUV_OT_SelectUV_SelectFlipped(bpy.types.Operator):
|
|||
bl_description = "Select faces which have flipped UVs"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
selection_method = EnumProperty(
|
||||
name="Selection Method",
|
||||
description="How to select faces which have overlapped UVs",
|
||||
items=[
|
||||
('EXTEND', "Extend",
|
||||
"Select faces without unselecting selected faces"),
|
||||
('RESET', "Reset", "Select faces and unselect selected faces"),
|
||||
],
|
||||
default='RESET'
|
||||
)
|
||||
sync_mesh_selection = BoolProperty(
|
||||
name="Sync Mesh Selection",
|
||||
description="Select mesh's faces as well as UV's faces",
|
||||
default=False
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
# we can not get area/space/region from console
|
||||
|
@ -139,6 +228,11 @@ class MUV_OT_SelectUV_SelectFlipped(bpy.types.Operator):
|
|||
return True
|
||||
return _is_valid_context(context)
|
||||
|
||||
@staticmethod
|
||||
def setup_argument(ops, scene):
|
||||
ops.selection_method = scene.muv_select_uv_selection_method
|
||||
ops.sync_mesh_selection = scene.muv_select_uv_sync_mesh_selection
|
||||
|
||||
def execute(self, context):
|
||||
objs = common.get_uv_editable_objects(context)
|
||||
|
||||
|
@ -159,12 +253,28 @@ class MUV_OT_SelectUV_SelectFlipped(bpy.types.Operator):
|
|||
uv_layer_list.append(uv_layer)
|
||||
faces_list.append(sel_faces)
|
||||
|
||||
flipped_info = common.get_flipped_uv_info(faces_list, uv_layer_list)
|
||||
flipped_info = common.get_flipped_uv_info(
|
||||
bm_list, faces_list, uv_layer_list)
|
||||
|
||||
if self.selection_method == 'RESET':
|
||||
if context.tool_settings.use_uv_select_sync:
|
||||
for faces in faces_list:
|
||||
for f in faces:
|
||||
f.select = False
|
||||
else:
|
||||
for uv_layer, faces in zip(uv_layer_list, faces_list):
|
||||
for f in faces:
|
||||
if self.sync_mesh_selection:
|
||||
f.select = False
|
||||
for l in f.loops:
|
||||
l[uv_layer].select = False
|
||||
|
||||
for info in flipped_info:
|
||||
if context.tool_settings.use_uv_select_sync:
|
||||
info["face"].select = True
|
||||
else:
|
||||
if self.sync_mesh_selection:
|
||||
info["face"].select = True
|
||||
for l in info["face"].loops:
|
||||
l[info["uv_layer"]].select = True
|
||||
|
||||
|
@ -172,3 +282,84 @@ class MUV_OT_SelectUV_SelectFlipped(bpy.types.Operator):
|
|||
bmesh.update_edit_mesh(obj.data)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@BlClassRegistry()
|
||||
class MUV_OT_SelectUV_ZoomSelectedUV(bpy.types.Operator):
|
||||
"""
|
||||
Operation class: Zoom selected UV in View3D space
|
||||
"""
|
||||
|
||||
bl_idname = "uv.muv_select_uv_zoom_selected_uv"
|
||||
bl_label = "Zoom Selected UV"
|
||||
bl_description = "Zoom selected UV in View3D space"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
# we can not get area/space/region from console
|
||||
if common.is_console_mode():
|
||||
return True
|
||||
return _is_valid_context(context)
|
||||
|
||||
def _get_override_context(self, context):
|
||||
for window in context.window_manager.windows:
|
||||
screen = window.screen
|
||||
for area in screen.areas:
|
||||
if area.type == 'VIEW_3D':
|
||||
for region in area.regions:
|
||||
if region.type == 'WINDOW':
|
||||
return {'window': window, 'screen': screen,
|
||||
'area': area, 'region': region}
|
||||
return None
|
||||
|
||||
def execute(self, context):
|
||||
objs = common.get_uv_editable_objects(context)
|
||||
|
||||
bm_list = []
|
||||
uv_layer_list = []
|
||||
verts_list = []
|
||||
for obj in objs:
|
||||
bm = bmesh.from_edit_mesh(obj.data)
|
||||
if common.check_version(2, 73, 0) >= 0:
|
||||
bm.verts.ensure_lookup_table()
|
||||
uv_layer = bm.loops.layers.uv.verify()
|
||||
|
||||
sel_verts = [v for v in bm.verts if v.select]
|
||||
bm_list.append(bm)
|
||||
uv_layer_list.append(uv_layer)
|
||||
verts_list.append(sel_verts)
|
||||
|
||||
# Get all selected UV vertices in UV Editor.
|
||||
sel_uv_verts = []
|
||||
for vlist, uv_layer in zip(verts_list, uv_layer_list):
|
||||
for v in vlist:
|
||||
for l in v.link_loops:
|
||||
if l[uv_layer].select or \
|
||||
context.tool_settings.use_uv_select_sync:
|
||||
sel_uv_verts.append(v)
|
||||
break
|
||||
|
||||
# Select vertices only selected in UV Editor.
|
||||
for bm in bm_list:
|
||||
for v in bm.verts:
|
||||
v.select = False
|
||||
for v in sel_uv_verts:
|
||||
v.select = True
|
||||
for obj in objs:
|
||||
bmesh.update_edit_mesh(obj.data)
|
||||
|
||||
# Zoom.
|
||||
override_context = self._get_override_context(context)
|
||||
if override_context is None:
|
||||
self.report({'WARNING'}, "More than one 'VIEW_3D' area must exist")
|
||||
return {'CANCELLED'}
|
||||
bpy.ops.view3d.view_selected(override_context, use_all_regions=False)
|
||||
|
||||
# Revert selection of verticies.
|
||||
for v in sel_verts:
|
||||
v.select = True
|
||||
for obj in objs:
|
||||
bmesh.update_edit_mesh(obj.data)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "imdjs, Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import bpy
|
||||
from bpy.props import BoolProperty, FloatProperty
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import math
|
||||
from math import atan2, cos, sqrt, sin, fabs
|
||||
|
|
|
@ -20,10 +20,11 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
from collections import namedtuple
|
||||
from math import sin, cos
|
||||
|
||||
import bpy
|
||||
import bmesh
|
||||
|
@ -32,6 +33,7 @@ from bpy.props import (
|
|||
BoolProperty,
|
||||
EnumProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
)
|
||||
import mathutils
|
||||
|
||||
|
@ -56,7 +58,7 @@ def _get_loaded_texture_name(_, __):
|
|||
return items
|
||||
|
||||
|
||||
def _get_canvas(context, magnitude):
|
||||
def _get_canvas(context):
|
||||
"""
|
||||
Get canvas to be renderred texture
|
||||
"""
|
||||
|
@ -88,11 +90,11 @@ def _get_canvas(context, magnitude):
|
|||
len_y = canvas_h
|
||||
else:
|
||||
if sc.muv_texture_projection_apply_tex_aspect:
|
||||
len_x = tex_w * magnitude
|
||||
len_y = tex_h * magnitude
|
||||
len_x = tex_w
|
||||
len_y = tex_h
|
||||
else:
|
||||
len_x = region_w * magnitude
|
||||
len_y = region_h * magnitude
|
||||
len_x = region_w
|
||||
len_y = region_h
|
||||
|
||||
x0 = int(center_x - len_x * 0.5)
|
||||
y0 = int(center_y - len_y * 0.5)
|
||||
|
@ -123,6 +125,35 @@ def _region_to_canvas(rg_vec, canvas):
|
|||
return cv_vec
|
||||
|
||||
|
||||
def _create_affine_matrix(identity, scale, rotate, translate):
|
||||
if identity:
|
||||
return mathutils.Matrix.Identity(3)
|
||||
|
||||
sx = scale[0]
|
||||
sy = scale[1]
|
||||
theta = rotate
|
||||
tx = translate[0]
|
||||
ty = translate[1]
|
||||
|
||||
mat_scale = mathutils.Matrix((
|
||||
(sx, 0.0, 0.0),
|
||||
(0.0, sy, 0.0),
|
||||
(0.0, 0.0, 1.0)
|
||||
))
|
||||
mat_rotate = mathutils.Matrix((
|
||||
(cos(theta), sin(theta), 0.0),
|
||||
(-sin(theta), cos(theta), 0.0),
|
||||
(0.0, 0.0, 1.0)
|
||||
))
|
||||
mat_translate = mathutils.Matrix((
|
||||
(1.0, 0.0, tx),
|
||||
(0.0, 1.0, ty),
|
||||
(0.0, 0.0, 1.0)
|
||||
))
|
||||
|
||||
return compat.matmul(compat.matmul(mat_translate, mat_rotate), mat_scale)
|
||||
|
||||
|
||||
def _is_valid_context(context):
|
||||
objs = common.get_uv_editable_objects(context)
|
||||
if not objs:
|
||||
|
@ -167,12 +198,31 @@ class _Properties:
|
|||
set=set_func,
|
||||
update=update_func
|
||||
)
|
||||
scene.muv_texture_projection_tex_magnitude = FloatProperty(
|
||||
name="Magnitude",
|
||||
description="Texture Magnitude",
|
||||
default=0.5,
|
||||
min=0.0,
|
||||
max=100.0
|
||||
scene.muv_texture_projection_tex_scaling = FloatVectorProperty(
|
||||
name="Scaling",
|
||||
description="Texture Scale",
|
||||
default=(0.5, 0.5),
|
||||
min=-100.0,
|
||||
max=100.0,
|
||||
size=2,
|
||||
subtype='XYZ'
|
||||
)
|
||||
scene.muv_texture_projection_tex_rotation = FloatProperty(
|
||||
name="Rotation",
|
||||
description="Texture Rotate",
|
||||
default=0.0,
|
||||
min=-360.0,
|
||||
max=360.0,
|
||||
subtype='ANGLE'
|
||||
)
|
||||
scene.muv_texture_projection_tex_translation = FloatVectorProperty(
|
||||
name="Translation",
|
||||
description="Texture Translate",
|
||||
default=(0.0, 0.0),
|
||||
min=-2000.0,
|
||||
max=2000.0,
|
||||
size=2,
|
||||
subtype='XYZ'
|
||||
)
|
||||
scene.muv_texture_projection_tex_image = EnumProperty(
|
||||
name="Image",
|
||||
|
@ -188,7 +238,7 @@ class _Properties:
|
|||
)
|
||||
scene.muv_texture_projection_adjust_window = BoolProperty(
|
||||
name="Adjust Window",
|
||||
description="Size of renderered texture is fitted to window",
|
||||
description="Scale of renderered texture is fitted to window",
|
||||
default=True
|
||||
)
|
||||
scene.muv_texture_projection_apply_tex_aspect = BoolProperty(
|
||||
|
@ -205,7 +255,9 @@ class _Properties:
|
|||
@classmethod
|
||||
def del_props(cls, scene):
|
||||
del scene.muv_texture_projection_enabled
|
||||
del scene.muv_texture_projection_tex_magnitude
|
||||
del scene.muv_texture_projection_tex_scaling
|
||||
del scene.muv_texture_projection_tex_rotation
|
||||
del scene.muv_texture_projection_tex_translation
|
||||
del scene.muv_texture_projection_tex_image
|
||||
del scene.muv_texture_projection_tex_transparency
|
||||
del scene.muv_texture_projection_adjust_window
|
||||
|
@ -264,12 +316,33 @@ class MUV_OT_TextureProjection(bpy.types.Operator):
|
|||
img = bpy.data.images[sc.muv_texture_projection_tex_image]
|
||||
|
||||
# setup rendering region
|
||||
rect = _get_canvas(context, sc.muv_texture_projection_tex_magnitude)
|
||||
rect = _get_canvas(context)
|
||||
|
||||
# Apply affine transformation.
|
||||
center = mathutils.Vector((
|
||||
(rect.x1 + rect.x0) / 2.0,
|
||||
(rect.y1 + rect.y0) / 2.0,
|
||||
0.0,
|
||||
))
|
||||
p1 = mathutils.Vector((rect.x0 - center.x, rect.y0 - center.y, 1.0))
|
||||
p2 = mathutils.Vector((rect.x0 - center.x, rect.y1 - center.y, 1.0))
|
||||
p3 = mathutils.Vector((rect.x1 - center.x, rect.y1 - center.y, 1.0))
|
||||
p4 = mathutils.Vector((rect.x1 - center.x, rect.y0 - center.y, 1.0))
|
||||
mat_affine = _create_affine_matrix(
|
||||
sc.muv_texture_projection_adjust_window,
|
||||
sc.muv_texture_projection_tex_scaling,
|
||||
sc.muv_texture_projection_tex_rotation,
|
||||
sc.muv_texture_projection_tex_translation)
|
||||
p1 = compat.matmul(mat_affine, p1) + center
|
||||
p2 = compat.matmul(mat_affine, p2) + center
|
||||
p3 = compat.matmul(mat_affine, p3) + center
|
||||
p4 = compat.matmul(mat_affine, p4) + center
|
||||
|
||||
positions = [
|
||||
[rect.x0, rect.y0],
|
||||
[rect.x0, rect.y1],
|
||||
[rect.x1, rect.y1],
|
||||
[rect.x1, rect.y0]
|
||||
[p1.x, p1.y],
|
||||
[p2.x, p2.y],
|
||||
[p3.x, p3.y],
|
||||
[p4.x, p4.y]
|
||||
]
|
||||
tex_coords = [
|
||||
[0.0, 0.0],
|
||||
|
@ -384,13 +457,30 @@ class MUV_OT_TextureProjection_Project(bpy.types.Operator):
|
|||
for f in sel_faces for l in f.loops
|
||||
]
|
||||
|
||||
# Apply affine transformation.
|
||||
rect = _get_canvas(bpy.context)
|
||||
center = mathutils.Vector((
|
||||
(rect.x1 + rect.x0) / 2.0,
|
||||
(rect.y1 + rect.y0) / 2.0,
|
||||
0.0,
|
||||
))
|
||||
v_screen_transformed = []
|
||||
for v in v_screen:
|
||||
p1 = mathutils.Vector((v.x - center.x, v.y - center.y, 1.0))
|
||||
mat_affine = _create_affine_matrix(
|
||||
sc.muv_texture_projection_adjust_window,
|
||||
sc.muv_texture_projection_tex_scaling,
|
||||
sc.muv_texture_projection_tex_rotation,
|
||||
sc.muv_texture_projection_tex_translation)
|
||||
p1 = compat.matmul(mat_affine.inverted(), p1) + center
|
||||
v_screen_transformed.append(p1)
|
||||
|
||||
# transform screen region to canvas
|
||||
v_canvas = [
|
||||
_region_to_canvas(
|
||||
v,
|
||||
_get_canvas(bpy.context,
|
||||
sc.muv_texture_projection_tex_magnitude)
|
||||
) for v in v_screen
|
||||
rect
|
||||
) for v in v_screen_transformed
|
||||
]
|
||||
|
||||
# assign image
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import bpy
|
||||
from bpy.props import (
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>, Mifth, MaxRobinot"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
__author__ = "Nutti <nutti.metro@gmail.com>"
|
||||
__status__ = "production"
|
||||
__version__ = "6.4"
|
||||
__date__ = "23 Oct 2020"
|
||||
__version__ = "6.5"
|
||||
__date__ = "6 Mar 2021"
|
||||
|
||||
import bpy
|
||||
from bpy.props import (
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue