Node Wrangler: Improved accuracy on Align Nodes operator #104551
@ -23,8 +23,7 @@ bl_info = {
|
||||
"cameras, lamps & animation",
|
||||
"warning": "Images must be in file folder, "
|
||||
"filenames are limited to DOS 8.3 format",
|
||||
"doc_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
|
||||
"Scripts/Import-Export/Autodesk_3DS",
|
||||
"doc_url": "{BLENDER_MANUAL_URL}/addons/import_export/scene_3ds.html",
|
||||
"category": "Import-Export",
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ from the lib3ds project (http://lib3ds.sourceforge.net/) sourcecode.
|
||||
"""
|
||||
|
||||
import bpy
|
||||
import time
|
||||
import math
|
||||
import struct
|
||||
import mathutils
|
||||
@ -332,7 +333,7 @@ class _3ds_rgb_color(object):
|
||||
|
||||
class _3ds_face(object):
|
||||
"""Class representing a face for a 3ds file."""
|
||||
__slots__ = ("vindex", "flag")
|
||||
__slots__ = ("vindex", "flag", )
|
||||
|
||||
def __init__(self, vindex, flag):
|
||||
self.vindex = vindex
|
||||
@ -530,6 +531,10 @@ def make_percent_subchunk(chunk_id, percent):
|
||||
pcti = _3ds_chunk(PCT)
|
||||
pcti.add_variable("percent", _3ds_ushort(int(round(percent * 100, 0))))
|
||||
pct_sub.add_subchunk(pcti)
|
||||
# optional:
|
||||
# pctf = _3ds_chunk(PCTF)
|
||||
# pctf.add_variable("pctfloat", _3ds_float(round(percent, 6)))
|
||||
# pct_sub.add_subchunk(pctf)
|
||||
return pct_sub
|
||||
|
||||
|
||||
@ -557,6 +562,7 @@ def make_material_texture_chunk(chunk_id, texslots, pct):
|
||||
Paint slots are optionally used as image source if no nodes are
|
||||
used. No additional filtering for mapping modes is done, all
|
||||
slots are written "as is"."""
|
||||
|
||||
# Add texture percentage value
|
||||
mat_sub = make_percent_subchunk(chunk_id, pct)
|
||||
has_entry = False
|
||||
@ -572,19 +578,26 @@ def make_material_texture_chunk(chunk_id, texslots, pct):
|
||||
socket = link.from_socket.identifier
|
||||
|
||||
mat_sub_mapflags = _3ds_chunk(MAT_MAP_TILING)
|
||||
"""Control bit flags, where 0x1 activates decaling, 0x2 activates mirror,
|
||||
0x8 activates inversion, 0x10 deactivates tiling, 0x20 activates summed area sampling,
|
||||
0x40 activates alpha source, 0x80 activates tinting, 0x100 ignores alpha, 0x200 activates RGB tint.
|
||||
Bits 0x80, 0x100, and 0x200 are only used with TEXMAP, TEX2MAP, and SPECMAP chunks.
|
||||
0x40, when used with a TEXMAP, TEX2MAP, or SPECMAP chunk must be accompanied with a tint bit,
|
||||
either 0x100 or 0x200, tintcolor will be processed if colorchunks are present"""
|
||||
|
||||
mapflags = 0
|
||||
|
||||
# no perfect mapping for mirror modes - 3DS only has uniform mirror w. repeat=2
|
||||
if texslot.extension == 'EXTEND': # decal flag
|
||||
if texslot.extension == 'EXTEND':
|
||||
mapflags |= 0x1
|
||||
# CLIP maps to 3DS' decal flag
|
||||
if texslot.extension == 'CLIP': # no wrap
|
||||
|
||||
if texslot.extension == 'CLIP':
|
||||
mapflags |= 0x10
|
||||
|
||||
if socket == 'Alpha':
|
||||
mapflags |= 0x40 # summed area sampling 0x20
|
||||
mapflags |= 0x40
|
||||
if texslot.socket_dst.identifier in {'Base Color', 'Specular'}:
|
||||
mapflags |= 0x80 if image.colorspace_settings.name=='Non-Color' else 0x200 # RGB tint
|
||||
mapflags |= 0x80 if image.colorspace_settings.name=='Non-Color' else 0x200
|
||||
|
||||
mat_sub_mapflags.add_variable("mapflags", _3ds_ushort(mapflags))
|
||||
mat_sub.add_subchunk(mat_sub_mapflags)
|
||||
@ -635,6 +648,7 @@ def make_material_chunk(material, image):
|
||||
"""Make a material chunk out of a blender material.
|
||||
Shading method is required for 3ds max, 0 for wireframe.
|
||||
0x1 for flat, 0x2 for gouraud, 0x3 for phong and 0x4 for metal."""
|
||||
|
||||
material_chunk = _3ds_chunk(MATERIAL)
|
||||
name = _3ds_chunk(MATNAME)
|
||||
shading = _3ds_chunk(MATSHADING)
|
||||
@ -727,7 +741,7 @@ def make_material_chunk(material, image):
|
||||
diffuse = []
|
||||
|
||||
for link in wrap.material.node_tree.links:
|
||||
if link.from_node.type == 'TEX_IMAGE' and link.to_node.type == 'MIX_RGB':
|
||||
if link.from_node.type == 'TEX_IMAGE' and link.to_node.type in {'MIX', 'MIX_RGB'}:
|
||||
diffuse = [link.from_node.image]
|
||||
|
||||
if diffuse:
|
||||
@ -987,16 +1001,6 @@ def make_uv_chunk(uv_array):
|
||||
return uv_chunk
|
||||
|
||||
|
||||
'''
|
||||
def make_matrix_4x3_chunk(matrix):
|
||||
matrix_chunk = _3ds_chunk(OBJECT_TRANS_MATRIX)
|
||||
for vec in matrix.col:
|
||||
for f in vec[:3]:
|
||||
matrix_chunk.add_variable("matrix_f", _3ds_float(f))
|
||||
return matrix_chunk
|
||||
'''
|
||||
|
||||
|
||||
def make_mesh_chunk(ob, mesh, matrix, materialDict, translation):
|
||||
"""Make a chunk out of a Blender mesh."""
|
||||
|
||||
@ -1027,14 +1031,12 @@ def make_mesh_chunk(ob, mesh, matrix, materialDict, translation):
|
||||
if uv_array:
|
||||
mesh_chunk.add_subchunk(make_uv_chunk(uv_array))
|
||||
|
||||
# mesh_chunk.add_subchunk(make_matrix_4x3_chunk(matrix))
|
||||
|
||||
# create transformation matrix chunk
|
||||
matrix_chunk = _3ds_chunk(OBJECT_TRANS_MATRIX)
|
||||
obj_matrix = matrix.transposed().to_3x3()
|
||||
|
||||
if ob.parent is None:
|
||||
obj_translate = translation[ob.name]
|
||||
if ob.parent is None or ob.parent.name not in translation:
|
||||
obj_translate = matrix.to_translation()
|
||||
|
||||
else: # Calculate child matrix translation relative to parent
|
||||
obj_translate = translation[ob.name].cross(-1 * translation[ob.parent.name])
|
||||
@ -1185,14 +1187,13 @@ def save(operator,
|
||||
global_matrix=None,
|
||||
):
|
||||
|
||||
import time
|
||||
# from bpy_extras.io_utils import create_derived_objects, free_derived_objects
|
||||
|
||||
"""Save the Blender scene to a 3ds file."""
|
||||
|
||||
# Time the export
|
||||
duration = time.time()
|
||||
# Blender.Window.WaitCursor(1)
|
||||
|
||||
scene = context.scene
|
||||
layer = context.view_layer
|
||||
depsgraph = context.evaluated_depsgraph_get()
|
||||
|
||||
if global_matrix is None:
|
||||
global_matrix = mathutils.Matrix()
|
||||
@ -1200,12 +1201,9 @@ def save(operator,
|
||||
if bpy.ops.object.mode_set.poll():
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
scene = context.scene
|
||||
layer = context.view_layer
|
||||
depsgraph = context.evaluated_depsgraph_get()
|
||||
|
||||
# Initialize the main chunk (primary):
|
||||
primary = _3ds_chunk(PRIMARY)
|
||||
|
||||
# Add version chunk:
|
||||
version_chunk = _3ds_chunk(VERSION)
|
||||
version_chunk.add_variable("version", _3ds_uint(3))
|
||||
@ -1241,16 +1239,16 @@ def save(operator,
|
||||
mesh_objects = []
|
||||
|
||||
if use_selection:
|
||||
objects = [ob for ob in scene.objects if not ob.hide_viewport and ob.select_get(view_layer=layer)]
|
||||
objects = [ob for ob in scene.objects if ob.visible_get(view_layer=layer) and ob.select_get(view_layer=layer)]
|
||||
else:
|
||||
objects = [ob for ob in scene.objects if not ob.hide_viewport]
|
||||
objects = [ob for ob in scene.objects if ob.visible_get(view_layer=layer)]
|
||||
|
||||
empty_objects = [ob for ob in objects if ob.type == 'EMPTY']
|
||||
light_objects = [ob for ob in objects if ob.type == 'LIGHT']
|
||||
camera_objects = [ob for ob in objects if ob.type == 'CAMERA']
|
||||
|
||||
for ob in objects:
|
||||
# get derived objects
|
||||
# free, derived = create_derived_objects(scene, ob)
|
||||
derived_dict = bpy_extras.io_utils.create_derived_objects(depsgraph, [ob])
|
||||
derived = derived_dict.get(ob)
|
||||
|
||||
@ -1302,25 +1300,24 @@ def save(operator,
|
||||
if f.material_index >= ma_ls_len:
|
||||
f.material_index = 0
|
||||
|
||||
# ob_derived_eval.to_mesh_clear()
|
||||
|
||||
# if free:
|
||||
# free_derived_objects(ob)
|
||||
|
||||
# Make material chunks for all materials used in the meshes:
|
||||
for ma_image in materialDict.values():
|
||||
object_info.add_subchunk(make_material_chunk(ma_image[0], ma_image[1]))
|
||||
|
||||
# Collect translation for transformation matrix
|
||||
translation = {}
|
||||
|
||||
# Give all objects a unique ID and build a dictionary from object name to object id:
|
||||
translation = {} # collect translation for transformation matrix
|
||||
# name_to_id = {}
|
||||
|
||||
for ob, data, matrix in mesh_objects:
|
||||
translation[ob.name] = ob.location
|
||||
# name_to_id[ob.name]= len(name_to_id)
|
||||
"""
|
||||
#for ob in empty_objects:
|
||||
|
||||
for ob in empty_objects:
|
||||
translation[ob.name] = ob.location
|
||||
# name_to_id[ob.name]= len(name_to_id)
|
||||
"""
|
||||
|
||||
# Create object chunks for all meshes:
|
||||
i = 0
|
||||
@ -1347,10 +1344,6 @@ def save(operator,
|
||||
kfdata.add_subchunk(make_kf_obj_node(ob, name_to_id))
|
||||
'''
|
||||
|
||||
# if not blender_mesh.users:
|
||||
# bpy.data.meshes.remove(blender_mesh)
|
||||
# blender_mesh.vertices = None
|
||||
|
||||
i += i
|
||||
|
||||
# Create chunks for all empties:
|
||||
@ -1425,9 +1418,9 @@ def save(operator,
|
||||
'''
|
||||
|
||||
# At this point, the chunk hierarchy is completely built.
|
||||
|
||||
# Check the size:
|
||||
primary.get_size()
|
||||
|
||||
# Open the file for writing:
|
||||
file = open(filepath, 'wb')
|
||||
|
||||
@ -1442,7 +1435,6 @@ def save(operator,
|
||||
name_mapping.clear()
|
||||
|
||||
# Debugging only: report the exporting time:
|
||||
# Blender.Window.WaitCursor(0)
|
||||
print("3ds export time: %.2f" % (time.time() - duration))
|
||||
|
||||
# Debugging only: dump the chunk hierarchy:
|
||||
|
Loading…
Reference in New Issue
Block a user