Node Wrangler: Improved accuracy on Align Nodes operator #104551
@ -151,14 +151,6 @@ def unregister():
|
|||||||
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
|
bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
|
||||||
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
|
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
|
||||||
|
|
||||||
# NOTES:
|
|
||||||
# why add 1 extra vertex? and remove it when done? -
|
|
||||||
# "Answer - eekadoodle - would need to re-order UV's without this since face
|
|
||||||
# order isnt always what we give blender, BMesh will solve :D"
|
|
||||||
#
|
|
||||||
# disabled scaling to size, this requires exposing bb (easy) and understanding
|
|
||||||
# how it works (needs some time)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
register()
|
register()
|
||||||
|
@ -13,9 +13,9 @@ import mathutils
|
|||||||
import bpy_extras
|
import bpy_extras
|
||||||
from bpy_extras import node_shader_utils
|
from bpy_extras import node_shader_utils
|
||||||
|
|
||||||
######################################################
|
###################
|
||||||
# Data Structures
|
# Data Structures #
|
||||||
######################################################
|
###################
|
||||||
|
|
||||||
# Some of the chunks that we will export
|
# Some of the chunks that we will export
|
||||||
# ----- Primary Chunk, at the beginning of each file
|
# ----- Primary Chunk, at the beginning of each file
|
||||||
@ -85,7 +85,10 @@ OBJECT_CAMERA = 0x4700 # This lets us know we are reading a camera object
|
|||||||
# >------ Sub defines of LIGHT
|
# >------ Sub defines of LIGHT
|
||||||
LIGHT_MULTIPLIER = 0x465B # The light energy factor
|
LIGHT_MULTIPLIER = 0x465B # The light energy factor
|
||||||
LIGHT_SPOTLIGHT = 0x4610 # The target of a spotlight
|
LIGHT_SPOTLIGHT = 0x4610 # The target of a spotlight
|
||||||
LIGHT_SPOTROLL = 0x4656 # The roll angle of the spot
|
LIGHT_SPOT_ROLL = 0x4656 # Light spot roll angle
|
||||||
|
LIGHT_SPOT_SHADOWED = 0x4630 # Light spot shadow flag
|
||||||
|
LIGHT_SPOT_SEE_CONE = 0x4650 # Light spot show cone flag
|
||||||
|
LIGHT_SPOT_RECTANGLE = 0x4651 # Light spot rectangle flag
|
||||||
|
|
||||||
# >------ sub defines of CAMERA
|
# >------ sub defines of CAMERA
|
||||||
OBJECT_CAM_RANGES = 0x4720 # The camera range values
|
OBJECT_CAM_RANGES = 0x4720 # The camera range values
|
||||||
@ -106,13 +109,29 @@ KFDATA_KFCURTIME = 0xB009
|
|||||||
KFDATA_OBJECT_NODE_TAG = 0xB002
|
KFDATA_OBJECT_NODE_TAG = 0xB002
|
||||||
|
|
||||||
# >------ sub defines of OBJECT_NODE_TAG
|
# >------ sub defines of OBJECT_NODE_TAG
|
||||||
OBJECT_NODE_ID = 0xB030
|
AMBIENT_NODE_TAG = 0xB001 # Ambient node tag
|
||||||
OBJECT_NODE_HDR = 0xB010
|
OBJECT_NODE_TAG = 0xB002 # Object tree tag
|
||||||
OBJECT_PIVOT = 0xB013
|
CAMERA_NODE_TAG = 0xB003 # Camera object tag
|
||||||
OBJECT_INSTANCE_NAME = 0xB011
|
TARGET_NODE_TAG = 0xB004 # Camera target tag
|
||||||
POS_TRACK_TAG = 0xB020
|
LIGHT_NODE_TAG = 0xB005 # Light object tag
|
||||||
ROT_TRACK_TAG = 0xB021
|
LTARGET_NODE_TAG = 0xB006 # Light target tag
|
||||||
SCL_TRACK_TAG = 0xB022
|
SPOT_NODE_TAG = 0xB007 # Spotlight tag
|
||||||
|
OBJECT_NODE_ID = 0xB030 # Object hierachy ID
|
||||||
|
OBJECT_NODE_HDR = 0xB010 # Hierachy tree header
|
||||||
|
OBJECT_INSTANCE_NAME = 0xB011 # Object instance name
|
||||||
|
OBJECT_PIVOT = 0xB013 # Object pivot position
|
||||||
|
OBJECT_BOUNDBOX = 0xB014 # Object boundbox
|
||||||
|
OBJECT_MORPH_SMOOTH = 0xB015 # Object smooth angle
|
||||||
|
POS_TRACK_TAG = 0xB020 # Position transform tag
|
||||||
|
ROT_TRACK_TAG = 0xB021 # Rotation transform tag
|
||||||
|
SCL_TRACK_TAG = 0xB022 # Scale transform tag
|
||||||
|
FOV_TRACK_TAG = 0xB023 # Field of view tag
|
||||||
|
ROLL_TRACK_TAG = 0xB024 # Roll transform tag
|
||||||
|
COL_TRACK_TAG = 0xB025 # Color transform tag
|
||||||
|
HOTSPOT_TRACK_TAG = 0xB027 # Hotspot transform tag
|
||||||
|
FALLOFF_TRACK_TAG = 0xB028 # Falloff transform tag
|
||||||
|
|
||||||
|
ROOT_OBJECT = 0xFFFF # Root object
|
||||||
|
|
||||||
|
|
||||||
# So 3ds max can open files, limit names to 12 in length
|
# So 3ds max can open files, limit names to 12 in length
|
||||||
@ -120,7 +139,6 @@ SCL_TRACK_TAG = 0xB022
|
|||||||
name_unique = [] # stores str, ascii only
|
name_unique = [] # stores str, ascii only
|
||||||
name_mapping = {} # stores {orig: byte} mapping
|
name_mapping = {} # stores {orig: byte} mapping
|
||||||
|
|
||||||
|
|
||||||
def sane_name(name):
|
def sane_name(name):
|
||||||
name_fixed = name_mapping.get(name)
|
name_fixed = name_mapping.get(name)
|
||||||
if name_fixed is not None:
|
if name_fixed is not None:
|
||||||
@ -143,13 +161,11 @@ def sane_name(name):
|
|||||||
def uv_key(uv):
|
def uv_key(uv):
|
||||||
return round(uv[0], 6), round(uv[1], 6)
|
return round(uv[0], 6), round(uv[1], 6)
|
||||||
|
|
||||||
|
|
||||||
# size defines:
|
# size defines:
|
||||||
SZ_SHORT = 2
|
SZ_SHORT = 2
|
||||||
SZ_INT = 4
|
SZ_INT = 4
|
||||||
SZ_FLOAT = 4
|
SZ_FLOAT = 4
|
||||||
|
|
||||||
|
|
||||||
class _3ds_ushort(object):
|
class _3ds_ushort(object):
|
||||||
"""Class representing a short (2-byte integer) for a 3ds file.
|
"""Class representing a short (2-byte integer) for a 3ds file.
|
||||||
*** This looks like an unsigned short H is unsigned from the struct docs - Cam***"""
|
*** This looks like an unsigned short H is unsigned from the struct docs - Cam***"""
|
||||||
@ -467,9 +483,9 @@ class _3ds_chunk(object):
|
|||||||
subchunk.dump(indent + 1)
|
subchunk.dump(indent + 1)
|
||||||
|
|
||||||
|
|
||||||
######################################################
|
##########
|
||||||
# EXPORT
|
# EXPORT #
|
||||||
######################################################
|
##########
|
||||||
|
|
||||||
def get_material_image(material):
|
def get_material_image(material):
|
||||||
""" Get images from paint slots."""
|
""" Get images from paint slots."""
|
||||||
@ -570,12 +586,12 @@ def make_material_texture_chunk(chunk_id, texslots, pct):
|
|||||||
|
|
||||||
if socket == 'Alpha':
|
if socket == 'Alpha':
|
||||||
mat_sub_alpha = _3ds_chunk(MAP_TILING)
|
mat_sub_alpha = _3ds_chunk(MAP_TILING)
|
||||||
alphaflag = 0x40 # summed area sampling 0x20
|
alphaflag |= 0x40 # summed area sampling 0x20
|
||||||
mat_sub_alpha.add_variable("alpha", _3ds_ushort(alphaflag))
|
mat_sub_alpha.add_variable("alpha", _3ds_ushort(alphaflag))
|
||||||
mat_sub.add_subchunk(mat_sub_alpha)
|
mat_sub.add_subchunk(mat_sub_alpha)
|
||||||
if texslot.socket_dst.identifier in {'Base Color', 'Specular'}:
|
if texslot.socket_dst.identifier in {'Base Color', 'Specular'}:
|
||||||
mat_sub_tint = _3ds_chunk(MAP_TILING) # RGB tint 0x200
|
mat_sub_tint = _3ds_chunk(MAP_TILING) # RGB tint 0x200
|
||||||
tint = 0x80 if texslot.image.colorspace_settings.name == 'Non-Color' else 0x200
|
tint |= 0x80 if texslot.image.colorspace_settings.name == 'Non-Color' else 0x200
|
||||||
mat_sub_tint.add_variable("tint", _3ds_ushort(tint))
|
mat_sub_tint.add_variable("tint", _3ds_ushort(tint))
|
||||||
mat_sub.add_subchunk(mat_sub_tint)
|
mat_sub.add_subchunk(mat_sub_tint)
|
||||||
|
|
||||||
@ -801,11 +817,11 @@ def extract_triangles(mesh):
|
|||||||
|
|
||||||
faceflag = 0
|
faceflag = 0
|
||||||
if c_a.use_edge_sharp:
|
if c_a.use_edge_sharp:
|
||||||
faceflag = faceflag + 0x1
|
faceflag |= 0x1
|
||||||
if b_c.use_edge_sharp:
|
if b_c.use_edge_sharp:
|
||||||
faceflag = faceflag + 0x2
|
faceflag |= 0x2
|
||||||
if a_b.use_edge_sharp:
|
if a_b.use_edge_sharp:
|
||||||
faceflag = faceflag + 0x4
|
faceflag |= 0x4
|
||||||
|
|
||||||
smoothgroup = polygroup[face.polygon_index]
|
smoothgroup = polygroup[face.polygon_index]
|
||||||
|
|
||||||
@ -1362,7 +1378,7 @@ def save(operator,
|
|||||||
object_chunk.add_variable("light", _3ds_string(sane_name(ob.name)))
|
object_chunk.add_variable("light", _3ds_string(sane_name(ob.name)))
|
||||||
light_chunk.add_variable("location", _3ds_point_3d(ob.location))
|
light_chunk.add_variable("location", _3ds_point_3d(ob.location))
|
||||||
color_float_chunk.add_variable("color", _3ds_float_color(ob.data.color))
|
color_float_chunk.add_variable("color", _3ds_float_color(ob.data.color))
|
||||||
energy_factor.add_variable("energy", _3ds_float(ob.data.energy * .001))
|
energy_factor.add_variable("energy", _3ds_float(ob.data.energy * 0.001))
|
||||||
light_chunk.add_subchunk(color_float_chunk)
|
light_chunk.add_subchunk(color_float_chunk)
|
||||||
light_chunk.add_subchunk(energy_factor)
|
light_chunk.add_subchunk(energy_factor)
|
||||||
|
|
||||||
@ -1374,12 +1390,18 @@ def save(operator,
|
|||||||
pos_y = ob.location[1] + (ob.location[0] * math.tan(math.radians(90) - ob.rotation_euler[2]))
|
pos_y = ob.location[1] + (ob.location[0] * math.tan(math.radians(90) - ob.rotation_euler[2]))
|
||||||
pos_z = hypo * math.tan(math.radians(90) - ob.rotation_euler[0])
|
pos_z = hypo * math.tan(math.radians(90) - ob.rotation_euler[0])
|
||||||
spotlight_chunk = _3ds_chunk(LIGHT_SPOTLIGHT)
|
spotlight_chunk = _3ds_chunk(LIGHT_SPOTLIGHT)
|
||||||
spot_roll_chunk = _3ds_chunk(LIGHT_SPOTROLL)
|
spot_roll_chunk = _3ds_chunk(LIGHT_SPOT_ROLL)
|
||||||
spotlight_chunk.add_variable("target", _3ds_point_3d((pos_x, pos_y, pos_z)))
|
spotlight_chunk.add_variable("target", _3ds_point_3d((pos_x, pos_y, pos_z)))
|
||||||
spotlight_chunk.add_variable("hotspot", _3ds_float(round(hotspot, 4)))
|
spotlight_chunk.add_variable("hotspot", _3ds_float(round(hotspot, 4)))
|
||||||
spotlight_chunk.add_variable("angle", _3ds_float(round(cone_angle, 4)))
|
spotlight_chunk.add_variable("angle", _3ds_float(round(cone_angle, 4)))
|
||||||
spot_roll_chunk.add_variable("roll", _3ds_float(round(ob.rotation_euler[1], 6)))
|
spot_roll_chunk.add_variable("roll", _3ds_float(round(ob.rotation_euler[1], 6)))
|
||||||
spotlight_chunk.add_subchunk(spot_roll_chunk)
|
spotlight_chunk.add_subchunk(spot_roll_chunk)
|
||||||
|
if ob.data.show_cone:
|
||||||
|
spot_cone_chunk = _3ds_chunk(LIGHT_SPOT_SEE_CONE)
|
||||||
|
spotlight_chunk.add_subchunk(spot_cone_chunk)
|
||||||
|
if ob.data.use_square:
|
||||||
|
spot_square_chunk = _3ds_chunk(LIGHT_SPOT_RECTANGLE)
|
||||||
|
spotlight_chunk.add_subchunk(spot_square_chunk)
|
||||||
light_chunk.add_subchunk(spotlight_chunk)
|
light_chunk.add_subchunk(spotlight_chunk)
|
||||||
|
|
||||||
# Add light to object info
|
# Add light to object info
|
||||||
|
@ -12,9 +12,9 @@ from bpy_extras.node_shader_utils import PrincipledBSDFWrapper
|
|||||||
BOUNDS_3DS = []
|
BOUNDS_3DS = []
|
||||||
|
|
||||||
|
|
||||||
######################################################
|
###################
|
||||||
# Data Structures
|
# Data Structures #
|
||||||
######################################################
|
###################
|
||||||
|
|
||||||
# Some of the chunks that we will see
|
# Some of the chunks that we will see
|
||||||
# ----- Primary Chunk, at the beginning of each file
|
# ----- Primary Chunk, at the beginning of each file
|
||||||
@ -62,12 +62,12 @@ MAT_TEX2_MAP = 0xA33A # This is a header for a secondary texture
|
|||||||
MAT_SHIN_MAP = 0xA33C # This is a header for a new roughness map
|
MAT_SHIN_MAP = 0xA33C # This is a header for a new roughness map
|
||||||
MAT_SELFI_MAP = 0xA33D # This is a header for a new emission map
|
MAT_SELFI_MAP = 0xA33D # This is a header for a new emission map
|
||||||
MAT_MAP_FILEPATH = 0xA300 # This holds the file name of the texture
|
MAT_MAP_FILEPATH = 0xA300 # This holds the file name of the texture
|
||||||
MAT_MAP_TILING = 0xA351 # 2nd bit (from LSB) is mirror UV flag
|
MAT_MAP_TILING = 0xA351 # 2nd bit (from LSB) is mirror UV flag
|
||||||
MAT_MAP_USCALE = 0xA354 # U axis scaling
|
MAT_MAP_USCALE = 0xA354 # U axis scaling
|
||||||
MAT_MAP_VSCALE = 0xA356 # V axis scaling
|
MAT_MAP_VSCALE = 0xA356 # V axis scaling
|
||||||
MAT_MAP_UOFFSET = 0xA358 # U axis offset
|
MAT_MAP_UOFFSET = 0xA358 # U axis offset
|
||||||
MAT_MAP_VOFFSET = 0xA35A # V axis offset
|
MAT_MAP_VOFFSET = 0xA35A # V axis offset
|
||||||
MAT_MAP_ANG = 0xA35C # UV rotation around the z-axis in rad
|
MAT_MAP_ANG = 0xA35C # UV rotation around the z-axis in rad
|
||||||
MAT_MAP_COL1 = 0xA360 # Map Color1
|
MAT_MAP_COL1 = 0xA360 # Map Color1
|
||||||
MAT_MAP_COL2 = 0xA362 # Map Color2
|
MAT_MAP_COL2 = 0xA362 # Map Color2
|
||||||
MAT_MAP_RCOL = 0xA364 # Red mapping
|
MAT_MAP_RCOL = 0xA364 # Red mapping
|
||||||
@ -76,71 +76,73 @@ MAT_MAP_BCOL = 0xA368 # Blue mapping
|
|||||||
|
|
||||||
# >------ sub defines of OBJECT
|
# >------ sub defines of OBJECT
|
||||||
OBJECT_MESH = 0x4100 # This lets us know that we are reading a new object
|
OBJECT_MESH = 0x4100 # This lets us know that we are reading a new object
|
||||||
OBJECT_LIGHT = 0x4600 # This lets un know we are reading a light object
|
OBJECT_LIGHT = 0x4600 # This lets us know we are reading a light object
|
||||||
OBJECT_LIGHT_SPOT = 0x4610 # The light is a spotloght.
|
OBJECT_CAMERA = 0x4700 # This lets us know we are reading a camera object
|
||||||
OBJECT_LIGHT_OFF = 0x4620 # The light off.
|
|
||||||
OBJECT_LIGHT_ATTENUATE = 0x4625
|
#>------ Sub defines of LIGHT
|
||||||
OBJECT_LIGHT_RAYSHADE = 0x4627
|
LIGHT_SPOTLIGHT = 0x4610 # The target of a spotlight
|
||||||
OBJECT_LIGHT_SHADOWED = 0x4630
|
LIGHT_OFF = 0x4620 # The light is off
|
||||||
OBJECT_LIGHT_LOCAL_SHADOW = 0x4640
|
LIGHT_ATTENUATE = 0x4625 # Light attenuate flag
|
||||||
OBJECT_LIGHT_LOCAL_SHADOW2 = 0x4641
|
LIGHT_RAYSHADE = 0x4627 # Light rayshading flag
|
||||||
OBJECT_LIGHT_SEE_CONE = 0x4650
|
LIGHT_SPOT_SHADOWED = 0x4630 # Light spot shadow flag
|
||||||
OBJECT_LIGHT_SPOT_RECTANGULAR = 0x4651
|
LIGHT_LOCAL_SHADOW = 0x4640 # Light shadow values 1
|
||||||
OBJECT_LIGHT_SPOT_OVERSHOOT = 0x4652
|
LIGHT_LOCAL_SHADOW2 = 0x4641 # Light shadow values 2
|
||||||
OBJECT_LIGHT_SPOT_PROJECTOR = 0x4653
|
LIGHT_SPOT_SEE_CONE = 0x4650 # Light spot cone flag
|
||||||
OBJECT_LIGHT_EXCLUDE = 0x4654
|
LIGHT_SPOT_RECTANGLE = 0x4651 # Light spot rectangle flag
|
||||||
OBJECT_LIGHT_RANGE = 0x4655
|
LIGHT_SPOT_OVERSHOOT = 0x4652 # Light spot overshoot flag
|
||||||
OBJECT_LIGHT_ROLL = 0x4656
|
LIGHT_SPOT_PROJECTOR = 0x4653 # Light spot bitmap name
|
||||||
OBJECT_LIGHT_SPOT_ASPECT = 0x4657
|
LIGHT_EXCLUDE = 0x4654 # Light excluded objects
|
||||||
OBJECT_LIGHT_RAY_BIAS = 0x4658
|
LIGHT_RANGE = 0x4655 # Light range
|
||||||
OBJECT_LIGHT_INNER_RANGE = 0x4659
|
LIGHT_SPOT_ROLL = 0x4656 # The roll angle of the spot
|
||||||
OBJECT_LIGHT_OUTER_RANGE = 0x465A
|
LIGHT_SPOT_ASPECT = 0x4657 # Light spot aspect flag
|
||||||
OBJECT_LIGHT_MULTIPLIER = 0x465B
|
LIGHT_RAY_BIAS = 0x4658 # Light ray bias value
|
||||||
OBJECT_LIGHT_AMBIENT_LIGHT = 0x4680
|
LIGHT_INNER_RANGE = 0x4659 # The light inner range
|
||||||
|
LIGHT_OUTER_RANGE = 0x465A # The light outer range
|
||||||
|
LIGHT_MULTIPLIER = 0x465B # The light energy factor
|
||||||
|
LIGHT_AMBIENT_LIGHT = 0x4680 # Light ambient flag
|
||||||
|
|
||||||
# >------ sub defines of CAMERA
|
# >------ sub defines of CAMERA
|
||||||
OBJECT_CAMERA = 0x4700 # This lets un know we are reading a camera object
|
|
||||||
OBJECT_CAM_RANGES = 0x4720 # The camera range values
|
OBJECT_CAM_RANGES = 0x4720 # The camera range values
|
||||||
|
|
||||||
# >------ sub defines of OBJECT_MESH
|
# >------ sub defines of OBJECT_MESH
|
||||||
OBJECT_VERTICES = 0x4110 # The objects vertices
|
OBJECT_VERTICES = 0x4110 # The objects vertices
|
||||||
OBJECT_VERTFLAGS = 0x4111 # The objects vertex flags
|
OBJECT_VERTFLAGS = 0x4111 # The objects vertex flags
|
||||||
OBJECT_FACES = 0x4120 # The objects faces
|
OBJECT_FACES = 0x4120 # The objects faces
|
||||||
OBJECT_MATERIAL = 0x4130 # This is found if the object has a material, either texture map or color
|
OBJECT_MATERIAL = 0x4130 # The objects face material
|
||||||
OBJECT_UV = 0x4140 # The UV texture coordinates
|
OBJECT_UV = 0x4140 # The vertex UV texture coordinates
|
||||||
OBJECT_SMOOTH = 0x4150 # The Object smooth groups
|
OBJECT_SMOOTH = 0x4150 # The objects face smooth groups
|
||||||
OBJECT_TRANS_MATRIX = 0x4160 # The Object Matrix
|
OBJECT_TRANS_MATRIX = 0x4160 # The objects Matrix
|
||||||
|
|
||||||
# >------ sub defines of EDITKEYFRAME
|
# >------ sub defines of EDITKEYFRAME
|
||||||
KFDATA_AMBIENT = 0xB001
|
KFDATA_AMBIENT = 0xB001 # Keyframe ambient node
|
||||||
KFDATA_OBJECT = 0xB002
|
KFDATA_OBJECT = 0xB002 # Keyframe object node
|
||||||
KFDATA_CAMERA = 0xB003
|
KFDATA_CAMERA = 0xB003 # Keyframe camera node
|
||||||
KFDATA_TARGET = 0xB004
|
KFDATA_TARGET = 0xB004 # Keyframe target node
|
||||||
KFDATA_LIGHT = 0xB005
|
KFDATA_LIGHT = 0xB005 # Keyframe light node
|
||||||
KFDATA_L_TARGET = 0xB006
|
KFDATA_LTARGET = 0xB006 # Keyframe light target node
|
||||||
KFDATA_SPOTLIGHT = 0xB007
|
KFDATA_SPOTLIGHT = 0xB007 # Keyframe spotlight node
|
||||||
KFDATA_KFSEG = 0xB008
|
KFDATA_KFSEG = 0xB008 # Keyframe start and stop
|
||||||
KFDATA_CURTIME = 0xB009
|
KFDATA_CURTIME = 0xB009 # Keyframe current frame
|
||||||
# KFDATA_KFHDR = 0xB00A
|
KFDATA_KFHDR = 0xB00A # Keyframe node header
|
||||||
|
|
||||||
# >------ sub defines of KEYFRAME_NODE
|
# >------ sub defines of KEYFRAME_NODE
|
||||||
OBJECT_NODE_HDR = 0xB010
|
OBJECT_NODE_HDR = 0xB010 # Keyframe object node header
|
||||||
OBJECT_INSTANCE_NAME = 0xB011
|
OBJECT_INSTANCE_NAME = 0xB011 # Keyframe object name for dummy objects
|
||||||
# OBJECT_PRESCALE = 0xB012
|
OBJECT_PRESCALE = 0xB012 # Keyframe object prescale
|
||||||
OBJECT_PIVOT = 0xB013
|
OBJECT_PIVOT = 0xB013 # Keyframe object pivot position
|
||||||
# OBJECT_BOUNDBOX = 0xB014
|
OBJECT_BOUNDBOX = 0xB014 # Keyframe object boundbox
|
||||||
MORPH_SMOOTH = 0xB015
|
MORPH_SMOOTH = 0xB015 # Auto smooth angle for keyframe mesh objects
|
||||||
POS_TRACK_TAG = 0xB020
|
POS_TRACK_TAG = 0xB020 # Keyframe object position track
|
||||||
ROT_TRACK_TAG = 0xB021
|
ROT_TRACK_TAG = 0xB021 # Keyframe object rotation track
|
||||||
SCL_TRACK_TAG = 0xB022
|
SCL_TRACK_TAG = 0xB022 # Keyframe object scale track
|
||||||
FOV_TRACK_TAG = 0xB023
|
FOV_TRACK_TAG = 0xB023 # Keyframe camera field of view track
|
||||||
ROLL_TRACK_TAG = 0xB024
|
ROLL_TRACK_TAG = 0xB024 # Keyframe camera roll track
|
||||||
COL_TRACK_TAG = 0xB025
|
COL_TRACK_TAG = 0xB025 # Keyframe light color track
|
||||||
# MORPH_TRACK_TAG = 0xB026
|
MORPH_TRACK_TAG = 0xB026 # Keyframe object morph smooth track
|
||||||
HOTSPOT_TRACK_TAG = 0xB027
|
HOTSPOT_TRACK_TAG = 0xB027 # Keyframe spotlight hotspot track
|
||||||
FALLOFF_TRACK_TAG = 0xB028
|
FALLOFF_TRACK_TAG = 0xB028 # Keyframe spotlight falloff track
|
||||||
# HIDE_TRACK_TAG = 0xB029
|
HIDE_TRACK_TAG = 0xB029 # Keyframe object hide track
|
||||||
OBJECT_NODE_ID = 0xB030
|
OBJECT_NODE_ID = 0xB030 # Keyframe object node id
|
||||||
|
|
||||||
ROOT_OBJECT = 0xFFFF
|
ROOT_OBJECT = 0xFFFF
|
||||||
|
|
||||||
@ -198,10 +200,10 @@ def read_string(file):
|
|||||||
# print("read string", s)
|
# print("read string", s)
|
||||||
return str(b''.join(s), "utf-8", "replace"), len(s) + 1
|
return str(b''.join(s), "utf-8", "replace"), len(s) + 1
|
||||||
|
|
||||||
######################################################
|
|
||||||
# IMPORT
|
|
||||||
######################################################
|
|
||||||
|
|
||||||
|
##########
|
||||||
|
# IMPORT #
|
||||||
|
##########
|
||||||
|
|
||||||
def process_next_object_chunk(file, previous_chunk):
|
def process_next_object_chunk(file, previous_chunk):
|
||||||
new_chunk = Chunk()
|
new_chunk = Chunk()
|
||||||
@ -210,7 +212,6 @@ def process_next_object_chunk(file, previous_chunk):
|
|||||||
# read the next chunk
|
# read the next chunk
|
||||||
read_chunk(file, new_chunk)
|
read_chunk(file, new_chunk)
|
||||||
|
|
||||||
|
|
||||||
def skip_to_end(file, skip_chunk):
|
def skip_to_end(file, skip_chunk):
|
||||||
buffer_size = skip_chunk.length - skip_chunk.bytes_read
|
buffer_size = skip_chunk.length - skip_chunk.bytes_read
|
||||||
binary_format = "%ic" % buffer_size
|
binary_format = "%ic" % buffer_size
|
||||||
@ -308,7 +309,7 @@ def add_texture_to_material(image, contextWrapper, pct, extend, alpha, scale, of
|
|||||||
contextWrapper._grid_to_location(1, 0, dst_node=contextWrapper.node_out, ref_node=shader)
|
contextWrapper._grid_to_location(1, 0, dst_node=contextWrapper.node_out, ref_node=shader)
|
||||||
|
|
||||||
|
|
||||||
def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAIN_BOUNDS, IMAGE_SEARCH, WORLD_MATRIX, KEYFRAME):
|
def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAIN, IMAGE_SEARCH, WORLD_MATRIX, KEYFRAME):
|
||||||
from bpy_extras.image_utils import load_image
|
from bpy_extras.image_utils import load_image
|
||||||
|
|
||||||
contextObName = None
|
contextObName = None
|
||||||
@ -411,8 +412,8 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
imported_objects.append(ob)
|
imported_objects.append(ob)
|
||||||
|
|
||||||
if myContextMesh_flag:
|
if myContextMesh_flag:
|
||||||
# Bit 0 (0x1) sets edge CA visible, Bit 1 (0x2) sets edge BC visible and Bit 2 (0x4) sets edge AB visible
|
"""Bit 0 (0x1) sets edge CA visible, Bit 1 (0x2) sets edge BC visible and Bit 2 (0x4) sets edge AB visible
|
||||||
# In Blender we use sharp edges for those flags
|
In Blender we use sharp edges for those flags"""
|
||||||
for f, pl in enumerate(bmesh.polygons):
|
for f, pl in enumerate(bmesh.polygons):
|
||||||
face = myContextMesh_facels[f]
|
face = myContextMesh_facels[f]
|
||||||
faceflag = myContextMesh_flag[f]
|
faceflag = myContextMesh_flag[f]
|
||||||
@ -421,25 +422,12 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
edge_ca = bmesh.edges[bmesh.loops[pl.loop_start + 2].edge_index]
|
edge_ca = bmesh.edges[bmesh.loops[pl.loop_start + 2].edge_index]
|
||||||
if face[2] == 0:
|
if face[2] == 0:
|
||||||
edge_ab, edge_bc, edge_ca = edge_ca, edge_ab, edge_bc
|
edge_ab, edge_bc, edge_ca = edge_ca, edge_ab, edge_bc
|
||||||
if faceflag == 1:
|
if faceflag & 0x1:
|
||||||
edge_ca.use_edge_sharp = True
|
edge_ca.use_edge_sharp = True
|
||||||
elif faceflag == 2:
|
if faceflag & 0x2:
|
||||||
edge_bc.use_edge_sharp = True
|
edge_bc.use_edge_sharp = True
|
||||||
elif faceflag == 3:
|
if faceflag & 0x4:
|
||||||
edge_ca.use_edge_sharp = True
|
|
||||||
edge_bc.use_edge_sharp = True
|
|
||||||
elif faceflag == 4:
|
|
||||||
edge_ab.use_edge_sharp = True
|
edge_ab.use_edge_sharp = True
|
||||||
elif faceflag == 5:
|
|
||||||
edge_ca.use_edge_sharp = True
|
|
||||||
edge_ab.use_edge_sharp = True
|
|
||||||
elif faceflag == 6:
|
|
||||||
edge_bc.use_edge_sharp = True
|
|
||||||
edge_ab.use_edge_sharp = True
|
|
||||||
elif faceflag == 7:
|
|
||||||
edge_bc.use_edge_sharp = True
|
|
||||||
edge_ab.use_edge_sharp = True
|
|
||||||
edge_ca.use_edge_sharp = True
|
|
||||||
|
|
||||||
if myContextMesh_smooth:
|
if myContextMesh_smooth:
|
||||||
for f, pl in enumerate(bmesh.polygons):
|
for f, pl in enumerate(bmesh.polygons):
|
||||||
@ -461,6 +449,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
CreateBlenderObject = False
|
CreateBlenderObject = False
|
||||||
CreateLightObject = False
|
CreateLightObject = False
|
||||||
CreateCameraObject = False
|
CreateCameraObject = False
|
||||||
|
CreateTrackData = False
|
||||||
|
|
||||||
def read_float_color(temp_chunk):
|
def read_float_color(temp_chunk):
|
||||||
temp_data = file.read(SZ_3FLOAT)
|
temp_data = file.read(SZ_3FLOAT)
|
||||||
@ -518,6 +507,12 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
voffset = read_float(temp_chunk)
|
voffset = read_float(temp_chunk)
|
||||||
|
|
||||||
elif temp_chunk.ID == MAT_MAP_TILING:
|
elif temp_chunk.ID == 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"""
|
||||||
tiling = read_short(temp_chunk)
|
tiling = read_short(temp_chunk)
|
||||||
if tiling & 0x1:
|
if tiling & 0x1:
|
||||||
extend = 'decal'
|
extend = 'decal'
|
||||||
@ -527,20 +522,19 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
extend = 'invert'
|
extend = 'invert'
|
||||||
elif tiling & 0x10:
|
elif tiling & 0x10:
|
||||||
extend = 'noWrap'
|
extend = 'noWrap'
|
||||||
elif tiling & 0x20:
|
if tiling & 0x20:
|
||||||
alpha = 'sat'
|
alpha = 'sat'
|
||||||
elif tiling & 0x40:
|
if tiling & 0x40:
|
||||||
alpha = 'alpha'
|
alpha = 'alpha'
|
||||||
elif tiling & 0x80:
|
if tiling & 0x80:
|
||||||
tint = 'tint'
|
tint = 'tint'
|
||||||
elif tiling & 0x100:
|
if tiling & 0x100:
|
||||||
tint = 'noAlpha'
|
tint = 'noAlpha'
|
||||||
elif tiling & 0x200:
|
if tiling & 0x200:
|
||||||
tint = 'RGBtint'
|
tint = 'RGBtint'
|
||||||
|
|
||||||
elif temp_chunk.ID == MAT_MAP_ANG:
|
elif temp_chunk.ID == MAT_MAP_ANG:
|
||||||
angle = read_float(temp_chunk)
|
angle = read_float(temp_chunk)
|
||||||
print("\nwarning: UV angle mapped to z-rotation")
|
|
||||||
|
|
||||||
elif temp_chunk.ID == MAT_MAP_COL1:
|
elif temp_chunk.ID == MAT_MAP_COL1:
|
||||||
tintcolor = read_byte_color(temp_chunk)
|
tintcolor = read_byte_color(temp_chunk)
|
||||||
@ -635,7 +629,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
|
|
||||||
# is it an object info chunk?
|
# is it an object info chunk?
|
||||||
elif new_chunk.ID == OBJECTINFO:
|
elif new_chunk.ID == OBJECTINFO:
|
||||||
process_next_chunk(context, file, new_chunk, imported_objects, CONSTRAIN_BOUNDS, IMAGE_SEARCH, WORLD_MATRIX, KEYFRAME)
|
process_next_chunk(context, file, new_chunk, imported_objects, CONSTRAIN, IMAGE_SEARCH, WORLD_MATRIX, KEYFRAME)
|
||||||
|
|
||||||
# keep track of how much we read in the main chunk
|
# keep track of how much we read in the main chunk
|
||||||
new_chunk.bytes_read += temp_chunk.bytes_read
|
new_chunk.bytes_read += temp_chunk.bytes_read
|
||||||
@ -659,7 +653,6 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
contextMesh_flag = None
|
contextMesh_flag = None
|
||||||
contextMesh_smooth = None
|
contextMesh_smooth = None
|
||||||
contextMeshUV = None
|
contextMeshUV = None
|
||||||
# Reset matrix
|
|
||||||
contextMatrix = None
|
contextMatrix = None
|
||||||
|
|
||||||
CreateBlenderObject = True
|
CreateBlenderObject = True
|
||||||
@ -673,15 +666,14 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
|
|
||||||
elif new_chunk.ID == MAT_NAME:
|
elif new_chunk.ID == MAT_NAME:
|
||||||
material_name, read_str_len = read_string(file)
|
material_name, read_str_len = read_string(file)
|
||||||
|
|
||||||
# plus one for the null character that ended the string
|
# plus one for the null character that ended the string
|
||||||
new_chunk.bytes_read += read_str_len
|
new_chunk.bytes_read += read_str_len
|
||||||
contextMaterial.name = material_name.rstrip() # remove trailing whitespace
|
contextMaterial.name = material_name.rstrip() # remove trailing whitespace
|
||||||
MATDICT[material_name] = contextMaterial
|
MATDICT[material_name] = contextMaterial
|
||||||
|
|
||||||
elif new_chunk.ID == MAT_AMBIENT:
|
elif new_chunk.ID == MAT_AMBIENT:
|
||||||
read_chunk(file, temp_chunk)
|
read_chunk(file, temp_chunk)
|
||||||
# only available color is emission color
|
# to not loose this data, ambient color is stored in line color
|
||||||
if temp_chunk.ID == COLOR_F:
|
if temp_chunk.ID == COLOR_F:
|
||||||
contextMaterial.line_color[:3] = read_float_color(temp_chunk)
|
contextMaterial.line_color[:3] = read_float_color(temp_chunk)
|
||||||
elif temp_chunk.ID == COLOR_24:
|
elif temp_chunk.ID == COLOR_24:
|
||||||
@ -702,7 +694,6 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
|
|
||||||
elif new_chunk.ID == MAT_SPECULAR:
|
elif new_chunk.ID == MAT_SPECULAR:
|
||||||
read_chunk(file, temp_chunk)
|
read_chunk(file, temp_chunk)
|
||||||
# Specular color is available
|
|
||||||
if temp_chunk.ID == COLOR_F:
|
if temp_chunk.ID == COLOR_F:
|
||||||
contextMaterial.specular_color = read_float_color(temp_chunk)
|
contextMaterial.specular_color = read_float_color(temp_chunk)
|
||||||
elif temp_chunk.ID == COLOR_24:
|
elif temp_chunk.ID == COLOR_24:
|
||||||
@ -758,7 +749,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
temp_chunk.bytes_read += SZ_FLOAT
|
temp_chunk.bytes_read += SZ_FLOAT
|
||||||
contextMaterial.diffuse_color[3] = 1 - float(struct.unpack('f', temp_data)[0])
|
contextMaterial.diffuse_color[3] = 1 - float(struct.unpack('f', temp_data)[0])
|
||||||
else:
|
else:
|
||||||
print("Cannot read material transparency")
|
skip_to_end(file, temp_chunk)
|
||||||
new_chunk.bytes_read += temp_chunk.bytes_read
|
new_chunk.bytes_read += temp_chunk.bytes_read
|
||||||
|
|
||||||
elif new_chunk.ID == MAT_SELF_ILPCT:
|
elif new_chunk.ID == MAT_SELF_ILPCT:
|
||||||
@ -827,7 +818,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
elif new_chunk.ID == MAT_TEX2_MAP:
|
elif new_chunk.ID == MAT_TEX2_MAP:
|
||||||
read_texture(new_chunk, temp_chunk, "Tex", "TEXTURE")
|
read_texture(new_chunk, temp_chunk, "Tex", "TEXTURE")
|
||||||
|
|
||||||
# mesh chunk
|
# If mesh chunk
|
||||||
elif new_chunk.ID == OBJECT_MESH:
|
elif new_chunk.ID == OBJECT_MESH:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -838,7 +829,6 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
new_chunk.bytes_read += 2
|
new_chunk.bytes_read += 2
|
||||||
contextMesh_vertls = struct.unpack('<%df' % (num_verts * 3), file.read(SZ_3FLOAT * num_verts))
|
contextMesh_vertls = struct.unpack('<%df' % (num_verts * 3), file.read(SZ_3FLOAT * num_verts))
|
||||||
new_chunk.bytes_read += SZ_3FLOAT * num_verts
|
new_chunk.bytes_read += SZ_3FLOAT * num_verts
|
||||||
# dummyvert is not used atm!
|
|
||||||
|
|
||||||
elif new_chunk.ID == OBJECT_FACES:
|
elif new_chunk.ID == OBJECT_FACES:
|
||||||
temp_data = file.read(SZ_U_SHORT)
|
temp_data = file.read(SZ_U_SHORT)
|
||||||
@ -884,9 +874,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
contextMatrix = mathutils.Matrix(
|
contextMatrix = mathutils.Matrix(
|
||||||
(data[:3] + [0], data[3:6] + [0], data[6:9] + [0], data[9:] + [1])).transposed()
|
(data[:3] + [0], data[3:6] + [0], data[6:9] + [0], data[9:] + [1])).transposed()
|
||||||
|
|
||||||
elif contextObName and new_chunk.ID == OBJECT_LIGHT: # Basic lamp support.
|
elif contextObName and new_chunk.ID == OBJECT_LIGHT: # Basic lamp support
|
||||||
# no lamp in dict that would be confusing
|
|
||||||
# ...why not? just set CreateBlenderObject to False
|
|
||||||
newLamp = bpy.data.lights.new("Lamp", 'POINT')
|
newLamp = bpy.data.lights.new("Lamp", 'POINT')
|
||||||
contextLamp = bpy.data.objects.new(contextObName, newLamp)
|
contextLamp = bpy.data.objects.new(contextObName, newLamp)
|
||||||
context.view_layer.active_layer_collection.collection.objects.link(contextLamp)
|
context.view_layer.active_layer_collection.collection.objects.link(contextLamp)
|
||||||
@ -898,17 +886,16 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
contextMatrix = None # Reset matrix
|
contextMatrix = None # Reset matrix
|
||||||
CreateBlenderObject = False
|
CreateBlenderObject = False
|
||||||
CreateLightObject = True
|
CreateLightObject = True
|
||||||
|
|
||||||
elif CreateLightObject and new_chunk.ID == COLOR_F: # Light color
|
elif CreateLightObject and new_chunk.ID == COLOR_F: # Light color
|
||||||
temp_data = file.read(SZ_3FLOAT)
|
temp_data = file.read(SZ_3FLOAT)
|
||||||
contextLamp.data.color = struct.unpack('<3f', temp_data)
|
contextLamp.data.color = struct.unpack('<3f', temp_data)
|
||||||
new_chunk.bytes_read += SZ_3FLOAT
|
new_chunk.bytes_read += SZ_3FLOAT
|
||||||
elif CreateLightObject and new_chunk.ID == OBJECT_LIGHT_MULTIPLIER: # Intensity
|
elif CreateLightObject and new_chunk.ID == LIGHT_MULTIPLIER: # Intensity
|
||||||
temp_data = file.read(SZ_FLOAT)
|
temp_data = file.read(SZ_FLOAT)
|
||||||
contextLamp.data.energy = (float(struct.unpack('f', temp_data)[0]) * 1000)
|
contextLamp.data.energy = (float(struct.unpack('f', temp_data)[0]) * 1000)
|
||||||
new_chunk.bytes_read += SZ_FLOAT
|
new_chunk.bytes_read += SZ_FLOAT
|
||||||
|
|
||||||
elif CreateLightObject and new_chunk.ID == OBJECT_LIGHT_SPOT: # Spotlight
|
elif CreateLightObject and new_chunk.ID == LIGHT_SPOTLIGHT: # Spotlight
|
||||||
temp_data = file.read(SZ_3FLOAT)
|
temp_data = file.read(SZ_3FLOAT)
|
||||||
contextLamp.data.type = 'SPOT'
|
contextLamp.data.type = 'SPOT'
|
||||||
spot = mathutils.Vector(struct.unpack('<3f', temp_data))
|
spot = mathutils.Vector(struct.unpack('<3f', temp_data))
|
||||||
@ -925,12 +912,18 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
temp_data = file.read(SZ_FLOAT) # Beam angle
|
temp_data = file.read(SZ_FLOAT) # Beam angle
|
||||||
beam_angle = float(struct.unpack('f', temp_data)[0])
|
beam_angle = float(struct.unpack('f', temp_data)[0])
|
||||||
contextLamp.data.spot_size = math.radians(beam_angle)
|
contextLamp.data.spot_size = math.radians(beam_angle)
|
||||||
contextLamp.data.spot_blend = (1.0 - (hotspot / beam_angle)) * 2
|
contextLamp.data.spot_blend = 1.0 - (hotspot / beam_angle)
|
||||||
new_chunk.bytes_read += SZ_FLOAT
|
new_chunk.bytes_read += SZ_FLOAT
|
||||||
elif CreateLightObject and new_chunk.ID == OBJECT_LIGHT_ROLL: # Roll
|
elif CreateLightObject and new_chunk.ID == LIGHT_SPOT_ROLL: # Roll
|
||||||
temp_data = file.read(SZ_FLOAT)
|
temp_data = file.read(SZ_FLOAT)
|
||||||
contextLamp.rotation_euler[1] = float(struct.unpack('f', temp_data)[0])
|
contextLamp.rotation_euler[1] = float(struct.unpack('f', temp_data)[0])
|
||||||
new_chunk.bytes_read += SZ_FLOAT
|
new_chunk.bytes_read += SZ_FLOAT
|
||||||
|
elif CreateLightObject and new_chunk.ID == LIGHT_SPOT_SHADOWED: # Shadow
|
||||||
|
contextLamp.data.use_shadow = True
|
||||||
|
elif CreateLightObject and new_chunk.ID == LIGHT_SPOT_SEE_CONE: # Cone
|
||||||
|
contextLamp.data.show_cone = True
|
||||||
|
elif CreateLightObject and new_chunk.ID == LIGHT_SPOT_RECTANGLE: # Square
|
||||||
|
contextLamp.data.use_square = True
|
||||||
|
|
||||||
elif contextObName and new_chunk.ID == OBJECT_CAMERA and CreateCameraObject is False: # Basic camera support
|
elif contextObName and new_chunk.ID == OBJECT_CAMERA and CreateCameraObject is False: # Basic camera support
|
||||||
camera = bpy.data.cameras.new("Camera")
|
camera = bpy.data.cameras.new("Camera")
|
||||||
@ -948,20 +941,24 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
new_chunk.bytes_read += SZ_3FLOAT
|
new_chunk.bytes_read += SZ_3FLOAT
|
||||||
temp_data = file.read(SZ_FLOAT) # triangulating camera angles
|
temp_data = file.read(SZ_FLOAT) # triangulating camera angles
|
||||||
direction = math.copysign(math.sqrt(pow(focus, 2) + pow(target[2], 2)), cam[1])
|
direction = math.copysign(math.sqrt(pow(focus, 2) + pow(target[2], 2)), cam[1])
|
||||||
pitch = math.radians(90) - math.copysign(math.acos(focus / direction), cam[2])
|
pitch = math.radians(90)-math.copysign(math.acos(focus/direction), cam[2])
|
||||||
contextCamera.rotation_euler[0] = -1 * math.copysign(pitch, cam[1])
|
if contextCamera.location[1] > target[1]:
|
||||||
contextCamera.rotation_euler[1] = float(struct.unpack('f', temp_data)[0])
|
contextCamera.rotation_euler[0] = math.copysign(pitch, cam[1])
|
||||||
contextCamera.rotation_euler[2] = -1 * (math.radians(90) - math.acos(cam[0] / focus))
|
contextCamera.rotation_euler[2] = math.radians(180)-math.copysign(math.atan(cam[0]/focus), cam[0])
|
||||||
|
else:
|
||||||
|
contextCamera.rotation_euler[0] = -1*(math.copysign(pitch, cam[1]))
|
||||||
|
contextCamera.rotation_euler[2] = -1*(math.radians(90)-math.acos(cam[0]/focus))
|
||||||
|
contextCamera.rotation_euler[1] = float(struct.unpack('f', temp_data)[0]) # Roll
|
||||||
new_chunk.bytes_read += SZ_FLOAT
|
new_chunk.bytes_read += SZ_FLOAT
|
||||||
temp_data = file.read(SZ_FLOAT)
|
temp_data = file.read(SZ_FLOAT)
|
||||||
contextCamera.data.lens = float(struct.unpack('f', temp_data)[0])
|
contextCamera.data.lens = float(struct.unpack('f', temp_data)[0]) # Focus
|
||||||
new_chunk.bytes_read += SZ_FLOAT
|
new_chunk.bytes_read += SZ_FLOAT
|
||||||
contextMatrix = None # Reset matrix
|
contextMatrix = None # Reset matrix
|
||||||
CreateBlenderObject = False
|
CreateBlenderObject = False
|
||||||
CreateCameraObject = True
|
CreateCameraObject = True
|
||||||
|
|
||||||
elif new_chunk.ID == EDITKEYFRAME:
|
elif new_chunk.ID == EDITKEYFRAME:
|
||||||
pass
|
trackposition = {}
|
||||||
|
|
||||||
elif KEYFRAME and new_chunk.ID == KFDATA_KFSEG:
|
elif KEYFRAME and new_chunk.ID == KFDATA_KFSEG:
|
||||||
temp_data = file.read(SZ_U_INT)
|
temp_data = file.read(SZ_U_INT)
|
||||||
@ -981,12 +978,12 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
|
|
||||||
# including these here means their OB_NODE_HDR are scanned
|
# including these here means their OB_NODE_HDR are scanned
|
||||||
# another object is being processed
|
# another object is being processed
|
||||||
elif new_chunk.ID in {KFDATA_AMBIENT, KFDATA_OBJECT, KFDATA_CAMERA, KFDATA_LIGHT}:
|
elif new_chunk.ID in {KFDATA_AMBIENT, KFDATA_OBJECT, KFDATA_CAMERA, KFDATA_LIGHT, KFDATA_SPOTLIGHT}:
|
||||||
object_id = ROOT_OBJECT
|
object_id = ROOT_OBJECT
|
||||||
tracking = 'OBJECT'
|
tracking = 'OBJECT'
|
||||||
child = None
|
child = None
|
||||||
|
|
||||||
elif new_chunk.ID in {KFDATA_TARGET, KFDATA_L_TARGET}:
|
elif CreateTrackData and new_chunk.ID in {KFDATA_TARGET, KFDATA_LTARGET}:
|
||||||
tracking = 'TARGET'
|
tracking = 'TARGET'
|
||||||
child = None
|
child = None
|
||||||
|
|
||||||
@ -1063,8 +1060,12 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
keyframe_data = {}
|
keyframe_data = {}
|
||||||
default_data = child.location[:]
|
default_data = child.location[:]
|
||||||
child.location = read_track_data(temp_chunk)[0]
|
child.location = read_track_data(temp_chunk)[0]
|
||||||
|
if child.type in {'LIGHT', 'CAMERA'}:
|
||||||
|
trackposition[0] = child.location
|
||||||
|
CreateTrackData = True
|
||||||
for keydata in keyframe_data.items():
|
for keydata in keyframe_data.items():
|
||||||
child.location = mathutils.Vector(keydata[1]) * (CONSTRAIN_BOUNDS * 0.1) if hierarchy == ROOT_OBJECT and CONSTRAIN_BOUNDS != 0.0 else keydata[1]
|
trackposition[keydata[0]] = keydata[1] # Keep track to position for target calculation
|
||||||
|
child.location = mathutils.Vector(keydata[1]) * (CONSTRAIN * 0.1) if hierarchy == ROOT_OBJECT and CONSTRAIN != 0.0 else keydata[1]
|
||||||
child.keyframe_insert(data_path="location", frame=keydata[0])
|
child.keyframe_insert(data_path="location", frame=keydata[0])
|
||||||
|
|
||||||
elif KEYFRAME and new_chunk.ID == POS_TRACK_TAG and tracking == 'TARGET': # Target position
|
elif KEYFRAME and new_chunk.ID == POS_TRACK_TAG and tracking == 'TARGET': # Target position
|
||||||
@ -1074,16 +1075,24 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
foc = math.copysign(math.sqrt(pow(pos[1],2)+pow(pos[0],2)),pos[1])
|
foc = math.copysign(math.sqrt(pow(pos[1],2)+pow(pos[0],2)),pos[1])
|
||||||
hyp = math.copysign(math.sqrt(pow(foc,2)+pow(target[2],2)),pos[1])
|
hyp = math.copysign(math.sqrt(pow(foc,2)+pow(target[2],2)),pos[1])
|
||||||
tilt = math.radians(90)-math.copysign(math.acos(foc/hyp), pos[2])
|
tilt = math.radians(90)-math.copysign(math.acos(foc/hyp), pos[2])
|
||||||
child.rotation_euler[0] = -1*math.copysign(tilt, pos[1])
|
if child.location[0] > target[1]:
|
||||||
child.rotation_euler[2] = -1*(math.radians(90)-math.acos(pos[0]/foc))
|
child.rotation_euler[0] = math.copysign(tilt, pos[1])
|
||||||
|
child.rotation_euler[2] = math.radians(180)-math.copysign(math.atan(pos[0]/foc), pos[0])
|
||||||
|
else:
|
||||||
|
child.rotation_euler[0] = -1*(math.copysign(tilt, pos[1]))
|
||||||
|
child.rotation_euler[2] = -1*(math.radians(90)-math.acos(pos[0]/foc))
|
||||||
for keydata in keyframe_data.items():
|
for keydata in keyframe_data.items():
|
||||||
target = keydata[1]
|
target = keydata[1]
|
||||||
pos = child.location + mathutils.Vector(target)
|
pos = mathutils.Vector(trackposition[keydata[0]]) + mathutils.Vector(target)
|
||||||
foc = math.copysign(math.sqrt(pow(pos[1],2)+pow(pos[0],2)),pos[1])
|
foc = math.copysign(math.sqrt(pow(pos[1],2)+pow(pos[0],2)),pos[1])
|
||||||
hyp = math.copysign(math.sqrt(pow(foc,2)+pow(target[2],2)),pos[1])
|
hyp = math.copysign(math.sqrt(pow(foc,2)+pow(target[2],2)),pos[1])
|
||||||
tilt = math.radians(90)-math.copysign(math.acos(foc/hyp), pos[2])
|
tilt = math.radians(90)-math.copysign(math.acos(foc/hyp), pos[2])
|
||||||
child.rotation_euler[0] = -1*math.copysign(tilt, pos[1])
|
if trackposition[keydata[0]][1] > target[1]:
|
||||||
child.rotation_euler[2] = -1*(math.radians(90)-math.acos(pos[0]/foc))
|
child.rotation_euler[0] = math.copysign(tilt, pos[1])
|
||||||
|
child.rotation_euler[2] = math.radians(180)-math.copysign(math.atan(pos[0]/foc), pos[0])
|
||||||
|
else:
|
||||||
|
child.rotation_euler[0] = -1*(math.copysign(tilt, pos[1]))
|
||||||
|
child.rotation_euler[2] = -1*(math.radians(90)-math.acos(pos[0]/foc))
|
||||||
child.keyframe_insert(data_path="rotation_euler", frame=keydata[0])
|
child.keyframe_insert(data_path="rotation_euler", frame=keydata[0])
|
||||||
|
|
||||||
elif KEYFRAME and new_chunk.ID == ROT_TRACK_TAG and tracking == 'OBJECT': # Rotation
|
elif KEYFRAME and new_chunk.ID == ROT_TRACK_TAG and tracking == 'OBJECT': # Rotation
|
||||||
@ -1121,7 +1130,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
default_data = child.scale[:]
|
default_data = child.scale[:]
|
||||||
child.scale = read_track_data(temp_chunk)[0]
|
child.scale = read_track_data(temp_chunk)[0]
|
||||||
for keydata in keyframe_data.items():
|
for keydata in keyframe_data.items():
|
||||||
child.scale = mathutils.Vector(keydata[1]) * (CONSTRAIN_BOUNDS * 0.1) if hierarchy == ROOT_OBJECT and CONSTRAIN_BOUNDS != 0.0 else keydata[1]
|
child.scale = mathutils.Vector(keydata[1]) * (CONSTRAIN * 0.1) if hierarchy == ROOT_OBJECT and CONSTRAIN != 0.0 else keydata[1]
|
||||||
child.keyframe_insert(data_path="scale", frame=keydata[0])
|
child.keyframe_insert(data_path="scale", frame=keydata[0])
|
||||||
|
|
||||||
elif KEYFRAME and new_chunk.ID == ROLL_TRACK_TAG and tracking == 'OBJECT': # Roll angle
|
elif KEYFRAME and new_chunk.ID == ROLL_TRACK_TAG and tracking == 'OBJECT': # Roll angle
|
||||||
@ -1144,10 +1153,10 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
keyframe_angle = {}
|
keyframe_angle = {}
|
||||||
cone_angle = math.degrees(child.data.spot_size)
|
cone_angle = math.degrees(child.data.spot_size)
|
||||||
default_value = cone_angle-(child.data.spot_blend*math.floor(cone_angle))
|
default_value = cone_angle-(child.data.spot_blend*math.floor(cone_angle))
|
||||||
hot_spot = read_track_angle(temp_chunk)[0]
|
hot_spot = math.degrees(read_track_angle(temp_chunk)[0])
|
||||||
child.data.spot_blend = 1.0 - (hot_spot/cone_angle)
|
child.data.spot_blend = 1.0 - (hot_spot/cone_angle)
|
||||||
for keydata in keyframe_angle.items():
|
for keydata in keyframe_angle.items():
|
||||||
child.data.spot_blend = 1.0 - (keydata[1]/cone_angle)
|
child.data.spot_blend = 1.0 - (math.degrees(keydata[1])/cone_angle)
|
||||||
child.data.keyframe_insert(data_path="spot_blend", frame=keydata[0])
|
child.data.keyframe_insert(data_path="spot_blend", frame=keydata[0])
|
||||||
|
|
||||||
elif new_chunk.ID == FALLOFF_TRACK_TAG and child.type == 'LIGHT' and child.data.type == 'SPOT': # Falloff
|
elif new_chunk.ID == FALLOFF_TRACK_TAG and child.type == 'LIGHT' and child.data.type == 'SPOT': # Falloff
|
||||||
@ -1190,6 +1199,12 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
if parent == ROOT_OBJECT:
|
if parent == ROOT_OBJECT:
|
||||||
if ob.parent is not None:
|
if ob.parent is not None:
|
||||||
ob.parent = None
|
ob.parent = None
|
||||||
|
elif parent not in object_dict:
|
||||||
|
if ob.parent != object_list[parent]:
|
||||||
|
if ob == object_list[parent]:
|
||||||
|
print(' warning: Cannot assign self to parent ', ob)
|
||||||
|
else:
|
||||||
|
ob.parent = object_list[parent]
|
||||||
else:
|
else:
|
||||||
if ob.parent != object_dict[parent]:
|
if ob.parent != object_dict[parent]:
|
||||||
if ob == object_dict[parent]:
|
if ob == object_dict[parent]:
|
||||||
@ -1197,7 +1212,8 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
else:
|
else:
|
||||||
ob.parent = object_dict[parent]
|
ob.parent = object_dict[parent]
|
||||||
|
|
||||||
# pivot_list[ind] += pivot_list[parent] # XXX, not sure this is correct, should parent space matrix be applied before combining?
|
#pivot_list[ind] += pivot_list[parent] # Not sure this is correct, should parent space matrix be applied before combining?
|
||||||
|
|
||||||
# fix pivots
|
# fix pivots
|
||||||
for ind, ob in enumerate(object_list):
|
for ind, ob in enumerate(object_list):
|
||||||
if ob.type == 'MESH':
|
if ob.type == 'MESH':
|
||||||
@ -1210,16 +1226,12 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
|||||||
|
|
||||||
def load_3ds(filepath,
|
def load_3ds(filepath,
|
||||||
context,
|
context,
|
||||||
CONSTRAIN_BOUNDS=10.0,
|
CONSTRAIN=10.0,
|
||||||
IMAGE_SEARCH=True,
|
IMAGE_SEARCH=True,
|
||||||
WORLD_MATRIX=False,
|
WORLD_MATRIX=False,
|
||||||
KEYFRAME=True,
|
KEYFRAME=True,
|
||||||
APPLY_MATRIX=True,
|
APPLY_MATRIX=True,
|
||||||
global_matrix=None):
|
global_matrix=None):
|
||||||
# global SCN
|
|
||||||
# XXX
|
|
||||||
# if BPyMessages.Error_NoFile(filepath):
|
|
||||||
# return
|
|
||||||
|
|
||||||
print("importing 3DS: %r..." % (filepath), end="")
|
print("importing 3DS: %r..." % (filepath), end="")
|
||||||
|
|
||||||
@ -1227,27 +1239,21 @@ def load_3ds(filepath,
|
|||||||
bpy.ops.object.select_all(action='DESELECT')
|
bpy.ops.object.select_all(action='DESELECT')
|
||||||
|
|
||||||
time1 = time.time()
|
time1 = time.time()
|
||||||
# time1 = Blender.sys.time()
|
|
||||||
|
|
||||||
current_chunk = Chunk()
|
current_chunk = Chunk()
|
||||||
|
|
||||||
file = open(filepath, 'rb')
|
file = open(filepath, 'rb')
|
||||||
|
|
||||||
# here we go!
|
# here we go!
|
||||||
# print 'reading the first chunk'
|
|
||||||
read_chunk(file, current_chunk)
|
read_chunk(file, current_chunk)
|
||||||
if current_chunk.ID != PRIMARY:
|
if current_chunk.ID != PRIMARY:
|
||||||
print('\tFatal Error: Not a valid 3ds file: %r' % filepath)
|
print('\tFatal Error: Not a valid 3ds file: %r' % filepath)
|
||||||
file.close()
|
file.close()
|
||||||
return
|
return
|
||||||
|
|
||||||
if CONSTRAIN_BOUNDS:
|
if CONSTRAIN:
|
||||||
BOUNDS_3DS[:] = [1 << 30, 1 << 30, 1 << 30, -1 << 30, -1 << 30, -1 << 30]
|
BOUNDS_3DS[:] = [1 << 30, 1 << 30, 1 << 30, -1 << 30, -1 << 30, -1 << 30]
|
||||||
else:
|
else:
|
||||||
del BOUNDS_3DS[:]
|
del BOUNDS_3DS[:]
|
||||||
|
|
||||||
# IMAGE_SEARCH
|
|
||||||
|
|
||||||
# fixme, make unglobal, clear in case
|
# fixme, make unglobal, clear in case
|
||||||
object_dictionary.clear()
|
object_dictionary.clear()
|
||||||
object_matrix.clear()
|
object_matrix.clear()
|
||||||
@ -1255,17 +1261,12 @@ def load_3ds(filepath,
|
|||||||
scn = context.scene
|
scn = context.scene
|
||||||
|
|
||||||
imported_objects = [] # Fill this list with objects
|
imported_objects = [] # Fill this list with objects
|
||||||
process_next_chunk(context, file, current_chunk, imported_objects, CONSTRAIN_BOUNDS, IMAGE_SEARCH, WORLD_MATRIX, KEYFRAME)
|
process_next_chunk(context, file, current_chunk, imported_objects, CONSTRAIN, IMAGE_SEARCH, WORLD_MATRIX, KEYFRAME)
|
||||||
|
|
||||||
# fixme, make unglobal
|
# fixme, make unglobal
|
||||||
object_dictionary.clear()
|
object_dictionary.clear()
|
||||||
object_matrix.clear()
|
object_matrix.clear()
|
||||||
|
|
||||||
# Link the objects into this scene.
|
|
||||||
# Layers = scn.Layers
|
|
||||||
|
|
||||||
# REMOVE DUMMYVERT, - remove this in the next release when blenders internal are fixed.
|
|
||||||
|
|
||||||
if APPLY_MATRIX:
|
if APPLY_MATRIX:
|
||||||
for ob in imported_objects:
|
for ob in imported_objects:
|
||||||
if ob.type == 'MESH':
|
if ob.type == 'MESH':
|
||||||
@ -1284,7 +1285,6 @@ def load_3ds(filepath,
|
|||||||
bpy.ops.object.rotation_clear()
|
bpy.ops.object.rotation_clear()
|
||||||
bpy.ops.object.location_clear()
|
bpy.ops.object.location_clear()
|
||||||
|
|
||||||
# Done DUMMYVERT
|
|
||||||
"""
|
"""
|
||||||
if IMPORT_AS_INSTANCE:
|
if IMPORT_AS_INSTANCE:
|
||||||
name = filepath.split('\\')[-1].split('/')[-1]
|
name = filepath.split('\\')[-1].split('/')[-1]
|
||||||
@ -1314,7 +1314,7 @@ def load_3ds(filepath,
|
|||||||
|
|
||||||
axis_min = [1000000000] * 3
|
axis_min = [1000000000] * 3
|
||||||
axis_max = [-1000000000] * 3
|
axis_max = [-1000000000] * 3
|
||||||
global_clamp_size = CONSTRAIN_BOUNDS
|
global_clamp_size = CONSTRAIN
|
||||||
if global_clamp_size != 0.0:
|
if global_clamp_size != 0.0:
|
||||||
# Get all object bounds
|
# Get all object bounds
|
||||||
for ob in imported_objects:
|
for ob in imported_objects:
|
||||||
@ -1358,7 +1358,7 @@ def load(operator,
|
|||||||
|
|
||||||
load_3ds(filepath,
|
load_3ds(filepath,
|
||||||
context,
|
context,
|
||||||
CONSTRAIN_BOUNDS=constrain_size,
|
CONSTRAIN=constrain_size,
|
||||||
IMAGE_SEARCH=use_image_search,
|
IMAGE_SEARCH=use_image_search,
|
||||||
WORLD_MATRIX=use_world_matrix,
|
WORLD_MATRIX=use_world_matrix,
|
||||||
KEYFRAME=read_keyframe,
|
KEYFRAME=read_keyframe,
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "Node Wrangler",
|
"name": "Node Wrangler",
|
||||||
"author": "Bartek Skorupa, Greg Zaal, Sebastian Koenig, Christian Brinkmann, Florian Meyer",
|
"author": "Bartek Skorupa, Greg Zaal, Sebastian Koenig, Christian Brinkmann, Florian Meyer",
|
||||||
"version": (3, 45),
|
"version": (3, 46),
|
||||||
"blender": (3, 6, 0),
|
"blender": (3, 6, 0),
|
||||||
"location": "Node Editor Toolbar or Shift-W",
|
"location": "Node Editor Toolbar or Shift-W",
|
||||||
"description": "Various tools to enhance and speed up node-based workflow",
|
"description": "Various tools to enhance and speed up node-based workflow",
|
||||||
|
@ -14,6 +14,7 @@ from bpy.props import (
|
|||||||
CollectionProperty,
|
CollectionProperty,
|
||||||
)
|
)
|
||||||
from bpy_extras.io_utils import ImportHelper, ExportHelper
|
from bpy_extras.io_utils import ImportHelper, ExportHelper
|
||||||
|
from bpy_extras.node_utils import connect_sockets
|
||||||
from mathutils import Vector
|
from mathutils import Vector
|
||||||
from os import path
|
from os import path
|
||||||
from glob import glob
|
from glob import glob
|
||||||
@ -369,13 +370,13 @@ class NWSwapLinks(Operator, NWBase):
|
|||||||
|
|
||||||
for connection in n1_outputs:
|
for connection in n1_outputs:
|
||||||
try:
|
try:
|
||||||
links.new(n2.outputs[connection[0]], connection[1])
|
connect_sockets(n2.outputs[connection[0]], connection[1])
|
||||||
except:
|
except:
|
||||||
self.report({'WARNING'},
|
self.report({'WARNING'},
|
||||||
"Some connections have been lost due to differing numbers of output sockets")
|
"Some connections have been lost due to differing numbers of output sockets")
|
||||||
for connection in n2_outputs:
|
for connection in n2_outputs:
|
||||||
try:
|
try:
|
||||||
links.new(n1.outputs[connection[0]], connection[1])
|
connect_sockets(n1.outputs[connection[0]], connection[1])
|
||||||
except:
|
except:
|
||||||
self.report({'WARNING'},
|
self.report({'WARNING'},
|
||||||
"Some connections have been lost due to differing numbers of output sockets")
|
"Some connections have been lost due to differing numbers of output sockets")
|
||||||
@ -413,8 +414,8 @@ class NWSwapLinks(Operator, NWBase):
|
|||||||
i1t = pair[0].links[0].to_socket
|
i1t = pair[0].links[0].to_socket
|
||||||
i2f = pair[1].links[0].from_socket
|
i2f = pair[1].links[0].from_socket
|
||||||
i2t = pair[1].links[0].to_socket
|
i2t = pair[1].links[0].to_socket
|
||||||
links.new(i1f, i2t)
|
connect_sockets(i1f, i2t)
|
||||||
links.new(i2f, i1t)
|
connect_sockets(i2f, i1t)
|
||||||
if t[1] == 1:
|
if t[1] == 1:
|
||||||
if len(types) == 1:
|
if len(types) == 1:
|
||||||
fs = t[0].links[0].from_socket
|
fs = t[0].links[0].from_socket
|
||||||
@ -425,14 +426,14 @@ class NWSwapLinks(Operator, NWBase):
|
|||||||
i += 1
|
i += 1
|
||||||
while n1.inputs[i].is_linked:
|
while n1.inputs[i].is_linked:
|
||||||
i += 1
|
i += 1
|
||||||
links.new(fs, n1.inputs[i])
|
connect_sockets(fs, n1.inputs[i])
|
||||||
elif len(types) == 2:
|
elif len(types) == 2:
|
||||||
i1f = types[0][0].links[0].from_socket
|
i1f = types[0][0].links[0].from_socket
|
||||||
i1t = types[0][0].links[0].to_socket
|
i1t = types[0][0].links[0].to_socket
|
||||||
i2f = types[1][0].links[0].from_socket
|
i2f = types[1][0].links[0].from_socket
|
||||||
i2t = types[1][0].links[0].to_socket
|
i2t = types[1][0].links[0].to_socket
|
||||||
links.new(i1f, i2t)
|
connect_sockets(i1f, i2t)
|
||||||
links.new(i2f, i1t)
|
connect_sockets(i2f, i1t)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.report({'WARNING'}, "This node has no input connections to swap!")
|
self.report({'WARNING'}, "This node has no input connections to swap!")
|
||||||
@ -703,7 +704,7 @@ class NWPreviewNode(Operator, NWBase):
|
|||||||
make_links.append((active.outputs[out_i], geometryoutput.inputs[geometryoutindex]))
|
make_links.append((active.outputs[out_i], geometryoutput.inputs[geometryoutindex]))
|
||||||
output_socket = geometryoutput.inputs[geometryoutindex]
|
output_socket = geometryoutput.inputs[geometryoutindex]
|
||||||
for li_from, li_to in make_links:
|
for li_from, li_to in make_links:
|
||||||
base_node_tree.links.new(li_from, li_to)
|
connect_sockets(li_from, li_to)
|
||||||
tree = base_node_tree
|
tree = base_node_tree
|
||||||
link_end = output_socket
|
link_end = output_socket
|
||||||
while tree.nodes.active != active:
|
while tree.nodes.active != active:
|
||||||
@ -714,11 +715,11 @@ class NWPreviewNode(Operator, NWBase):
|
|||||||
node_socket = node.node_tree.outputs[index]
|
node_socket = node.node_tree.outputs[index]
|
||||||
if node_socket in delete_sockets:
|
if node_socket in delete_sockets:
|
||||||
delete_sockets.remove(node_socket)
|
delete_sockets.remove(node_socket)
|
||||||
tree.links.new(link_start, link_end)
|
connect_sockets(link_start, link_end)
|
||||||
# Iterate
|
# Iterate
|
||||||
link_end = self.ensure_group_output(node.node_tree).inputs[index]
|
link_end = self.ensure_group_output(node.node_tree).inputs[index]
|
||||||
tree = tree.nodes.active.node_tree
|
tree = tree.nodes.active.node_tree
|
||||||
tree.links.new(active.outputs[out_i], link_end)
|
connect_sockets(active.outputs[out_i], link_end)
|
||||||
|
|
||||||
# Delete sockets
|
# Delete sockets
|
||||||
for socket in delete_sockets:
|
for socket in delete_sockets:
|
||||||
@ -777,7 +778,7 @@ class NWPreviewNode(Operator, NWBase):
|
|||||||
make_links.append((active.outputs[out_i], materialout.inputs[materialout_index]))
|
make_links.append((active.outputs[out_i], materialout.inputs[materialout_index]))
|
||||||
output_socket = materialout.inputs[materialout_index]
|
output_socket = materialout.inputs[materialout_index]
|
||||||
for li_from, li_to in make_links:
|
for li_from, li_to in make_links:
|
||||||
base_node_tree.links.new(li_from, li_to)
|
connect_sockets(li_from, li_to)
|
||||||
|
|
||||||
# Create links through node groups until we reach the active node
|
# Create links through node groups until we reach the active node
|
||||||
tree = base_node_tree
|
tree = base_node_tree
|
||||||
@ -790,11 +791,11 @@ class NWPreviewNode(Operator, NWBase):
|
|||||||
node_socket = node.node_tree.outputs[index]
|
node_socket = node.node_tree.outputs[index]
|
||||||
if node_socket in delete_sockets:
|
if node_socket in delete_sockets:
|
||||||
delete_sockets.remove(node_socket)
|
delete_sockets.remove(node_socket)
|
||||||
tree.links.new(link_start, link_end)
|
connect_sockets(link_start, link_end)
|
||||||
# Iterate
|
# Iterate
|
||||||
link_end = self.ensure_group_output(node.node_tree).inputs[index]
|
link_end = self.ensure_group_output(node.node_tree).inputs[index]
|
||||||
tree = tree.nodes.active.node_tree
|
tree = tree.nodes.active.node_tree
|
||||||
tree.links.new(active.outputs[out_i], link_end)
|
connect_sockets(active.outputs[out_i], link_end)
|
||||||
|
|
||||||
# Delete sockets
|
# Delete sockets
|
||||||
for socket in delete_sockets:
|
for socket in delete_sockets:
|
||||||
@ -1065,31 +1066,31 @@ class NWSwitchNodeType(Operator, NWBase):
|
|||||||
if node.inputs[src_i].links and not new_node.inputs[dst_i].links:
|
if node.inputs[src_i].links and not new_node.inputs[dst_i].links:
|
||||||
in_src_link = node.inputs[src_i].links[0]
|
in_src_link = node.inputs[src_i].links[0]
|
||||||
in_dst_socket = new_node.inputs[dst_i]
|
in_dst_socket = new_node.inputs[dst_i]
|
||||||
links.new(in_src_link.from_socket, in_dst_socket)
|
connect_sockets(in_src_link.from_socket, in_dst_socket)
|
||||||
links.remove(in_src_link)
|
links.remove(in_src_link)
|
||||||
# OUTPUTS: Base on matches in proper order.
|
# OUTPUTS: Base on matches in proper order.
|
||||||
for (src_i, src_dval), (dst_i, dst_dval) in matches['OUTPUTS'][tp]:
|
for (src_i, src_dval), (dst_i, dst_dval) in matches['OUTPUTS'][tp]:
|
||||||
for out_src_link in node.outputs[src_i].links:
|
for out_src_link in node.outputs[src_i].links:
|
||||||
out_dst_socket = new_node.outputs[dst_i]
|
out_dst_socket = new_node.outputs[dst_i]
|
||||||
links.new(out_dst_socket, out_src_link.to_socket)
|
connect_sockets(out_dst_socket, out_src_link.to_socket)
|
||||||
# relink rest inputs if possible, no criteria
|
# relink rest inputs if possible, no criteria
|
||||||
for src_inp in node.inputs:
|
for src_inp in node.inputs:
|
||||||
for dst_inp in new_node.inputs:
|
for dst_inp in new_node.inputs:
|
||||||
if src_inp.links and not dst_inp.links:
|
if src_inp.links and not dst_inp.links:
|
||||||
src_link = src_inp.links[0]
|
src_link = src_inp.links[0]
|
||||||
links.new(src_link.from_socket, dst_inp)
|
connect_sockets(src_link.from_socket, dst_inp)
|
||||||
links.remove(src_link)
|
links.remove(src_link)
|
||||||
# relink rest outputs if possible, base on node kind if any left.
|
# relink rest outputs if possible, base on node kind if any left.
|
||||||
for src_o in node.outputs:
|
for src_o in node.outputs:
|
||||||
for out_src_link in src_o.links:
|
for out_src_link in src_o.links:
|
||||||
for dst_o in new_node.outputs:
|
for dst_o in new_node.outputs:
|
||||||
if src_o.type == dst_o.type:
|
if src_o.type == dst_o.type:
|
||||||
links.new(dst_o, out_src_link.to_socket)
|
connect_sockets(dst_o, out_src_link.to_socket)
|
||||||
# relink rest outputs no criteria if any left. Link all from first output.
|
# relink rest outputs no criteria if any left. Link all from first output.
|
||||||
for src_o in node.outputs:
|
for src_o in node.outputs:
|
||||||
for out_src_link in src_o.links:
|
for out_src_link in src_o.links:
|
||||||
if new_node.outputs:
|
if new_node.outputs:
|
||||||
links.new(new_node.outputs[0], out_src_link.to_socket)
|
connect_sockets(new_node.outputs[0], out_src_link.to_socket)
|
||||||
nodes.remove(node)
|
nodes.remove(node)
|
||||||
force_update(context)
|
force_update(context)
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
@ -1178,16 +1179,16 @@ class NWMergeNodes(Operator, NWBase):
|
|||||||
# outputs to the multi input socket.
|
# outputs to the multi input socket.
|
||||||
if i < len(socket_indices) - 1:
|
if i < len(socket_indices) - 1:
|
||||||
ind = socket_indices[i]
|
ind = socket_indices[i]
|
||||||
links.new(node.outputs[0], new_node.inputs[ind])
|
connect_sockets(node.outputs[0], new_node.inputs[ind])
|
||||||
else:
|
else:
|
||||||
outputs_for_multi_input.insert(0, node.outputs[0])
|
outputs_for_multi_input.insert(0, node.outputs[0])
|
||||||
if outputs_for_multi_input != []:
|
if outputs_for_multi_input != []:
|
||||||
ind = socket_indices[-1]
|
ind = socket_indices[-1]
|
||||||
for output in outputs_for_multi_input:
|
for output in outputs_for_multi_input:
|
||||||
links.new(output, new_node.inputs[ind])
|
connect_sockets(output, new_node.inputs[ind])
|
||||||
if prev_links != []:
|
if prev_links != []:
|
||||||
for link in prev_links:
|
for link in prev_links:
|
||||||
links.new(new_node.outputs[0], link.to_node.inputs[0])
|
connect_sockets(new_node.outputs[0], link.to_node.inputs[0])
|
||||||
return new_node
|
return new_node
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
@ -1448,19 +1449,19 @@ class NWMergeNodes(Operator, NWBase):
|
|||||||
# Prevent cyclic dependencies when nodes to be merged are linked to one another.
|
# Prevent cyclic dependencies when nodes to be merged are linked to one another.
|
||||||
# Link only if "to_node" index not in invalid indexes list.
|
# Link only if "to_node" index not in invalid indexes list.
|
||||||
if not self.link_creates_cycle(ss_link, invalid_nodes):
|
if not self.link_creates_cycle(ss_link, invalid_nodes):
|
||||||
links.new(get_first_enabled_output(last_add), ss_link.to_socket)
|
connect_sockets(get_first_enabled_output(last_add), ss_link.to_socket)
|
||||||
# add links from last_add to all links 'to_socket' of out links of first selected.
|
# add links from last_add to all links 'to_socket' of out links of first selected.
|
||||||
for fs_link in first_selected_output.links:
|
for fs_link in first_selected_output.links:
|
||||||
# Link only if "to_node" index not in invalid indexes list.
|
# Link only if "to_node" index not in invalid indexes list.
|
||||||
if not self.link_creates_cycle(fs_link, invalid_nodes):
|
if not self.link_creates_cycle(fs_link, invalid_nodes):
|
||||||
links.new(get_first_enabled_output(last_add), fs_link.to_socket)
|
connect_sockets(get_first_enabled_output(last_add), fs_link.to_socket)
|
||||||
# add link from "first" selected and "first" add node
|
# add link from "first" selected and "first" add node
|
||||||
node_to = nodes[count_after - 1]
|
node_to = nodes[count_after - 1]
|
||||||
links.new(first_selected_output, node_to.inputs[first])
|
connect_sockets(first_selected_output, node_to.inputs[first])
|
||||||
if node_to.type == 'ZCOMBINE':
|
if node_to.type == 'ZCOMBINE':
|
||||||
for fs_out in first_selected.outputs:
|
for fs_out in first_selected.outputs:
|
||||||
if fs_out != first_selected_output and fs_out.name in ('Z', 'Depth'):
|
if fs_out != first_selected_output and fs_out.name in ('Z', 'Depth'):
|
||||||
links.new(fs_out, node_to.inputs[1])
|
connect_sockets(fs_out, node_to.inputs[1])
|
||||||
break
|
break
|
||||||
# add links between added ADD nodes and between selected and ADD nodes
|
# add links between added ADD nodes and between selected and ADD nodes
|
||||||
for i in range(count_adds):
|
for i in range(count_adds):
|
||||||
@ -1469,21 +1470,21 @@ class NWMergeNodes(Operator, NWBase):
|
|||||||
node_to = nodes[index - 1]
|
node_to = nodes[index - 1]
|
||||||
node_to_input_i = first
|
node_to_input_i = first
|
||||||
node_to_z_i = 1 # if z combine - link z to first z input
|
node_to_z_i = 1 # if z combine - link z to first z input
|
||||||
links.new(get_first_enabled_output(node_from), node_to.inputs[node_to_input_i])
|
connect_sockets(get_first_enabled_output(node_from), node_to.inputs[node_to_input_i])
|
||||||
if node_to.type == 'ZCOMBINE':
|
if node_to.type == 'ZCOMBINE':
|
||||||
for from_out in node_from.outputs:
|
for from_out in node_from.outputs:
|
||||||
if from_out != get_first_enabled_output(node_from) and from_out.name in ('Z', 'Depth'):
|
if from_out != get_first_enabled_output(node_from) and from_out.name in ('Z', 'Depth'):
|
||||||
links.new(from_out, node_to.inputs[node_to_z_i])
|
connect_sockets(from_out, node_to.inputs[node_to_z_i])
|
||||||
if len(nodes_list) > 1:
|
if len(nodes_list) > 1:
|
||||||
node_from = nodes[nodes_list[i + 1][0]]
|
node_from = nodes[nodes_list[i + 1][0]]
|
||||||
node_to = nodes[index]
|
node_to = nodes[index]
|
||||||
node_to_input_i = second
|
node_to_input_i = second
|
||||||
node_to_z_i = 3 # if z combine - link z to second z input
|
node_to_z_i = 3 # if z combine - link z to second z input
|
||||||
links.new(get_first_enabled_output(node_from), node_to.inputs[node_to_input_i])
|
connect_sockets(get_first_enabled_output(node_from), node_to.inputs[node_to_input_i])
|
||||||
if node_to.type == 'ZCOMBINE':
|
if node_to.type == 'ZCOMBINE':
|
||||||
for from_out in node_from.outputs:
|
for from_out in node_from.outputs:
|
||||||
if from_out != get_first_enabled_output(node_from) and from_out.name in ('Z', 'Depth'):
|
if from_out != get_first_enabled_output(node_from) and from_out.name in ('Z', 'Depth'):
|
||||||
links.new(from_out, node_to.inputs[node_to_z_i])
|
connect_sockets(from_out, node_to.inputs[node_to_z_i])
|
||||||
index -= 1
|
index -= 1
|
||||||
# set "last" of added nodes as active
|
# set "last" of added nodes as active
|
||||||
nodes.active = last_add
|
nodes.active = last_add
|
||||||
@ -1691,7 +1692,7 @@ class NWCopySettings(Operator, NWBase):
|
|||||||
new_node.location = node_loc
|
new_node.location = node_loc
|
||||||
|
|
||||||
for str_from, str_to in reconnections:
|
for str_from, str_to in reconnections:
|
||||||
node_tree.links.new(eval(str_from), eval(str_to))
|
node_tree.connect_sockets(eval(str_from), eval(str_to))
|
||||||
|
|
||||||
success_names.append(new_node.name)
|
success_names.append(new_node.name)
|
||||||
|
|
||||||
@ -1860,7 +1861,7 @@ class NWAddTextureSetup(Operator, NWBase):
|
|||||||
x_offset = x_offset + image_texture_node.width + padding
|
x_offset = x_offset + image_texture_node.width + padding
|
||||||
image_texture_node.location = [locx - x_offset, locy]
|
image_texture_node.location = [locx - x_offset, locy]
|
||||||
nodes.active = image_texture_node
|
nodes.active = image_texture_node
|
||||||
links.new(image_texture_node.outputs[0], target_input)
|
connect_sockets(image_texture_node.outputs[0], target_input)
|
||||||
|
|
||||||
# The mapping setup following this will connect to the first input of this image texture.
|
# The mapping setup following this will connect to the first input of this image texture.
|
||||||
target_input = image_texture_node.inputs[0]
|
target_input = image_texture_node.inputs[0]
|
||||||
@ -1872,7 +1873,7 @@ class NWAddTextureSetup(Operator, NWBase):
|
|||||||
mapping_node = nodes.new('ShaderNodeMapping')
|
mapping_node = nodes.new('ShaderNodeMapping')
|
||||||
x_offset = x_offset + mapping_node.width + padding
|
x_offset = x_offset + mapping_node.width + padding
|
||||||
mapping_node.location = [locx - x_offset, locy]
|
mapping_node.location = [locx - x_offset, locy]
|
||||||
links.new(mapping_node.outputs[0], target_input)
|
connect_sockets(mapping_node.outputs[0], target_input)
|
||||||
|
|
||||||
# Add Texture Coordinates node.
|
# Add Texture Coordinates node.
|
||||||
tex_coord_node = nodes.new('ShaderNodeTexCoord')
|
tex_coord_node = nodes.new('ShaderNodeTexCoord')
|
||||||
@ -1882,7 +1883,7 @@ class NWAddTextureSetup(Operator, NWBase):
|
|||||||
is_procedural_texture = is_texture_node and node.type != 'TEX_IMAGE'
|
is_procedural_texture = is_texture_node and node.type != 'TEX_IMAGE'
|
||||||
use_generated_coordinates = is_procedural_texture or use_environment_texture
|
use_generated_coordinates = is_procedural_texture or use_environment_texture
|
||||||
tex_coord_output = tex_coord_node.outputs[0 if use_generated_coordinates else 2]
|
tex_coord_output = tex_coord_node.outputs[0 if use_generated_coordinates else 2]
|
||||||
links.new(tex_coord_output, mapping_node.inputs[0])
|
connect_sockets(tex_coord_output, mapping_node.inputs[0])
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
@ -2007,7 +2008,7 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper):
|
|||||||
disp_node = nodes.new(type='ShaderNodeDisplacement')
|
disp_node = nodes.new(type='ShaderNodeDisplacement')
|
||||||
# Align the Displacement node under the active Principled BSDF node
|
# Align the Displacement node under the active Principled BSDF node
|
||||||
disp_node.location = active_node.location + Vector((100, -700))
|
disp_node.location = active_node.location + Vector((100, -700))
|
||||||
link = links.new(disp_node.inputs[0], disp_texture.outputs[0])
|
link = connect_sockets(disp_node.inputs[0], disp_texture.outputs[0])
|
||||||
|
|
||||||
# TODO Turn on true displacement in the material
|
# TODO Turn on true displacement in the material
|
||||||
# Too complicated for now
|
# Too complicated for now
|
||||||
@ -2016,7 +2017,7 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper):
|
|||||||
output_node = [n for n in nodes if n.bl_idname == 'ShaderNodeOutputMaterial']
|
output_node = [n for n in nodes if n.bl_idname == 'ShaderNodeOutputMaterial']
|
||||||
if output_node:
|
if output_node:
|
||||||
if not output_node[0].inputs[2].is_linked:
|
if not output_node[0].inputs[2].is_linked:
|
||||||
link = links.new(output_node[0].inputs[2], disp_node.outputs[0])
|
link = connect_sockets(output_node[0].inputs[2], disp_node.outputs[0])
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -2046,13 +2047,13 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper):
|
|||||||
if match_normal:
|
if match_normal:
|
||||||
# If Normal add normal node in between
|
# If Normal add normal node in between
|
||||||
normal_node = nodes.new(type='ShaderNodeNormalMap')
|
normal_node = nodes.new(type='ShaderNodeNormalMap')
|
||||||
link = links.new(normal_node.inputs[1], texture_node.outputs[0])
|
link = connect_sockets(normal_node.inputs[1], texture_node.outputs[0])
|
||||||
elif match_bump:
|
elif match_bump:
|
||||||
# If Bump add bump node in between
|
# If Bump add bump node in between
|
||||||
normal_node = nodes.new(type='ShaderNodeBump')
|
normal_node = nodes.new(type='ShaderNodeBump')
|
||||||
link = links.new(normal_node.inputs[2], texture_node.outputs[0])
|
link = connect_sockets(normal_node.inputs[2], texture_node.outputs[0])
|
||||||
|
|
||||||
link = links.new(active_node.inputs[sname[0]], normal_node.outputs[0])
|
link = connect_sockets(active_node.inputs[sname[0]], normal_node.outputs[0])
|
||||||
normal_node_texture = texture_node
|
normal_node_texture = texture_node
|
||||||
|
|
||||||
elif sname[0] == 'Roughness':
|
elif sname[0] == 'Roughness':
|
||||||
@ -2063,19 +2064,19 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper):
|
|||||||
|
|
||||||
if match_rough:
|
if match_rough:
|
||||||
# If Roughness nothing to to
|
# If Roughness nothing to to
|
||||||
link = links.new(active_node.inputs[sname[0]], texture_node.outputs[0])
|
link = connect_sockets(active_node.inputs[sname[0]], texture_node.outputs[0])
|
||||||
|
|
||||||
elif match_gloss:
|
elif match_gloss:
|
||||||
# If Gloss Map add invert node
|
# If Gloss Map add invert node
|
||||||
invert_node = nodes.new(type='ShaderNodeInvert')
|
invert_node = nodes.new(type='ShaderNodeInvert')
|
||||||
link = links.new(invert_node.inputs[1], texture_node.outputs[0])
|
link = connect_sockets(invert_node.inputs[1], texture_node.outputs[0])
|
||||||
|
|
||||||
link = links.new(active_node.inputs[sname[0]], invert_node.outputs[0])
|
link = connect_sockets(active_node.inputs[sname[0]], invert_node.outputs[0])
|
||||||
roughness_node = texture_node
|
roughness_node = texture_node
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# This is a simple connection Texture --> Input slot
|
# This is a simple connection Texture --> Input slot
|
||||||
link = links.new(active_node.inputs[sname[0]], texture_node.outputs[0])
|
link = connect_sockets(active_node.inputs[sname[0]], texture_node.outputs[0])
|
||||||
|
|
||||||
# Use non-color for all but 'Base Color' Textures
|
# Use non-color for all but 'Base Color' Textures
|
||||||
if not sname[0] in ['Base Color', 'Emission'] and texture_node.image:
|
if not sname[0] in ['Base Color', 'Emission'] and texture_node.image:
|
||||||
@ -2120,15 +2121,15 @@ class NWAddPrincipledSetup(Operator, NWBase, ImportHelper):
|
|||||||
sum(n.location.y for n in texture_nodes) / len(texture_nodes)))
|
sum(n.location.y for n in texture_nodes) / len(texture_nodes)))
|
||||||
reroute.location = tex_coords + Vector((-50, -120))
|
reroute.location = tex_coords + Vector((-50, -120))
|
||||||
for texture_node in texture_nodes:
|
for texture_node in texture_nodes:
|
||||||
link = links.new(texture_node.inputs[0], reroute.outputs[0])
|
link = connect_sockets(texture_node.inputs[0], reroute.outputs[0])
|
||||||
link = links.new(reroute.inputs[0], mapping.outputs[0])
|
link = connect_sockets(reroute.inputs[0], mapping.outputs[0])
|
||||||
else:
|
else:
|
||||||
link = links.new(texture_nodes[0].inputs[0], mapping.outputs[0])
|
link = connect_sockets(texture_nodes[0].inputs[0], mapping.outputs[0])
|
||||||
|
|
||||||
# Connect texture_coordiantes to mapping node
|
# Connect texture_coordiantes to mapping node
|
||||||
texture_input = nodes.new(type='ShaderNodeTexCoord')
|
texture_input = nodes.new(type='ShaderNodeTexCoord')
|
||||||
texture_input.location = mapping.location + Vector((-200, 0))
|
texture_input.location = mapping.location + Vector((-200, 0))
|
||||||
link = links.new(mapping.inputs[0], texture_input.outputs[2])
|
link = connect_sockets(mapping.inputs[0], texture_input.outputs[2])
|
||||||
|
|
||||||
# Create frame around tex coords and mapping
|
# Create frame around tex coords and mapping
|
||||||
frame = nodes.new(type='NodeFrame')
|
frame = nodes.new(type='NodeFrame')
|
||||||
@ -2232,8 +2233,8 @@ class NWAddReroutes(Operator, NWBase):
|
|||||||
n = nodes.new('NodeReroute')
|
n = nodes.new('NodeReroute')
|
||||||
nodes.active = n
|
nodes.active = n
|
||||||
for link in output.links:
|
for link in output.links:
|
||||||
links.new(n.outputs[0], link.to_socket)
|
connect_sockets(n.outputs[0], link.to_socket)
|
||||||
links.new(output, n.inputs[0])
|
connect_sockets(output, n.inputs[0])
|
||||||
n.location = loc
|
n.location = loc
|
||||||
post_select.append(n)
|
post_select.append(n)
|
||||||
reroutes_count += 1
|
reroutes_count += 1
|
||||||
@ -2325,7 +2326,7 @@ class NWLinkActiveToSelected(Operator, NWBase):
|
|||||||
for input in node.inputs:
|
for input in node.inputs:
|
||||||
if input.type == out.type or node.type == 'REROUTE':
|
if input.type == out.type or node.type == 'REROUTE':
|
||||||
if replace or not input.is_linked:
|
if replace or not input.is_linked:
|
||||||
links.new(out, input)
|
connect_sockets(out, input)
|
||||||
if not use_node_name and not use_outputs_names:
|
if not use_node_name and not use_outputs_names:
|
||||||
doit = False
|
doit = False
|
||||||
break
|
break
|
||||||
@ -2590,7 +2591,7 @@ class NWLinkToOutputNode(Operator):
|
|||||||
elif tree_type == 'GeometryNodeTree':
|
elif tree_type == 'GeometryNodeTree':
|
||||||
if active.outputs[output_index].type != 'GEOMETRY':
|
if active.outputs[output_index].type != 'GEOMETRY':
|
||||||
return {'CANCELLED'}
|
return {'CANCELLED'}
|
||||||
links.new(active.outputs[output_index], output_node.inputs[out_input_index])
|
connect_sockets(active.outputs[output_index], output_node.inputs[out_input_index])
|
||||||
|
|
||||||
force_update(context) # viewport render does not update
|
force_update(context) # viewport render does not update
|
||||||
|
|
||||||
@ -2611,7 +2612,7 @@ class NWMakeLink(Operator, NWBase):
|
|||||||
n1 = nodes[context.scene.NWLazySource]
|
n1 = nodes[context.scene.NWLazySource]
|
||||||
n2 = nodes[context.scene.NWLazyTarget]
|
n2 = nodes[context.scene.NWLazyTarget]
|
||||||
|
|
||||||
links.new(n1.outputs[self.from_socket], n2.inputs[self.to_socket])
|
connect_sockets(n1.outputs[self.from_socket], n2.inputs[self.to_socket])
|
||||||
|
|
||||||
force_update(context)
|
force_update(context)
|
||||||
|
|
||||||
@ -2635,7 +2636,7 @@ class NWCallInputsMenu(Operator, NWBase):
|
|||||||
if len(n2.inputs) > 1:
|
if len(n2.inputs) > 1:
|
||||||
bpy.ops.wm.call_menu("INVOKE_DEFAULT", name=NWConnectionListInputs.bl_idname)
|
bpy.ops.wm.call_menu("INVOKE_DEFAULT", name=NWConnectionListInputs.bl_idname)
|
||||||
elif len(n2.inputs) == 1:
|
elif len(n2.inputs) == 1:
|
||||||
links.new(n1.outputs[self.from_socket], n2.inputs[0])
|
connect_sockets(n1.outputs[self.from_socket], n2.inputs[0])
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
@ -3019,7 +3020,7 @@ class NWResetNodes(bpy.types.Operator):
|
|||||||
new_node.location = node_loc
|
new_node.location = node_loc
|
||||||
|
|
||||||
for str_from, str_to in reconnections:
|
for str_from, str_to in reconnections:
|
||||||
node_tree.links.new(eval(str_from), eval(str_to))
|
connect_sockets(eval(str_from), eval(str_to))
|
||||||
|
|
||||||
new_node.select = False
|
new_node.select = False
|
||||||
success_names.append(new_node.name)
|
success_names.append(new_node.name)
|
||||||
|
Loading…
Reference in New Issue
Block a user