Fix duplicate shape key import when the FBX connections are duplicated #104954
@ -6,7 +6,7 @@ bl_info = {
|
||||
"name": "Grease Pencil Tools",
|
||||
"description": "Extra tools for Grease Pencil",
|
||||
"author": "Samuel Bernou, Antonio Vazquez, Daniel Martinez Lara, Matias Mendiola",
|
||||
"version": (1, 8, 1),
|
||||
"version": (1, 8, 2),
|
||||
"blender": (3, 0, 0),
|
||||
"location": "Sidebar > Grease Pencil > Grease Pencil Tools",
|
||||
"warning": "",
|
||||
|
@ -49,10 +49,10 @@ def get_reduced_area_coord(context):
|
||||
|
||||
## minus tool leftbar + sidebar right
|
||||
regs = context.area.regions
|
||||
toolbar = regs[2]
|
||||
sidebar = regs[3]
|
||||
header = regs[0]
|
||||
tool_header = regs[1]
|
||||
toolbar = next((r for r in regs if r.type == 'TOOLS'), None)
|
||||
sidebar = next((r for r in regs if r.type == 'UI'), None)
|
||||
header = next((r for r in regs if r.type == 'HEADER'), None)
|
||||
tool_header = next((r for r in regs if r.type == 'TOOL_HEADER'), None)
|
||||
up_margin = down_margin = 0
|
||||
if tool_header.alignment == 'TOP':
|
||||
up_margin += tool_header.height
|
||||
|
@ -5,8 +5,8 @@
|
||||
bl_info = {
|
||||
"name": "Import Images as Planes",
|
||||
"author": "Florian Meyer (tstscr), mont29, matali, Ted Schundler (SpkyElctrc), mrbimax",
|
||||
"version": (3, 5, 0),
|
||||
"blender": (2, 91, 0),
|
||||
"version": (3, 5, 1),
|
||||
"blender": (4, 0, 0),
|
||||
"location": "File > Import > Images as Planes or Add > Image > Images as Planes",
|
||||
"description": "Imports images and creates planes with the appropriate aspect ratio. "
|
||||
"The images are mapped to the planes.",
|
||||
@ -25,7 +25,10 @@ from math import pi
|
||||
|
||||
import bpy
|
||||
from bpy.types import Operator
|
||||
from bpy.app.translations import pgettext_tip as tip_
|
||||
from bpy.app.translations import (
|
||||
pgettext_tip as tip_,
|
||||
contexts as i18n_contexts
|
||||
)
|
||||
from mathutils import Vector
|
||||
|
||||
from bpy.props import (
|
||||
@ -151,6 +154,9 @@ def load_images(filenames, directory, force_reload=False, frame_start=1, find_se
|
||||
file_iter = zip(filenames, repeat(1), repeat(1))
|
||||
|
||||
for filename, offset, frames in file_iter:
|
||||
if not os.path.isfile(bpy.path.abspath(os.path.join(directory, filename))):
|
||||
continue
|
||||
|
||||
image = load_image(filename, directory, check_existing=True, force_reload=force_reload)
|
||||
|
||||
# Size is unavailable for sequences, so we grab it early
|
||||
@ -731,7 +737,9 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper):
|
||||
('HASHED', "Hashed","Use noise to dither the binary visibility (works well with multi-samples)"),
|
||||
('OPAQUE', "Opaque","Render surface without transparency"),
|
||||
)
|
||||
blend_method: EnumProperty(name="Blend Mode", items=BLEND_METHODS, default='BLEND', description="Blend Mode for Transparent Faces")
|
||||
blend_method: EnumProperty(
|
||||
name="Blend Mode", items=BLEND_METHODS, default='BLEND',
|
||||
description="Blend Mode for Transparent Faces", translation_context=i18n_contexts.id_material)
|
||||
|
||||
SHADOW_METHODS = (
|
||||
('CLIP', "Clip","Use the alpha threshold to clip the visibility (binary visibility)"),
|
||||
@ -739,7 +747,9 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper):
|
||||
('OPAQUE',"Opaque","Material will cast shadows without transparency"),
|
||||
('NONE',"None","Material will cast no shadow"),
|
||||
)
|
||||
shadow_method: EnumProperty(name="Shadow Mode", items=SHADOW_METHODS, default='CLIP', description="Shadow mapping method")
|
||||
shadow_method: EnumProperty(
|
||||
name="Shadow Mode", items=SHADOW_METHODS, default='CLIP',
|
||||
description="Shadow mapping method", translation_context=i18n_contexts.id_material)
|
||||
|
||||
use_backface_culling: BoolProperty(
|
||||
name="Backface Culling", default=False,
|
||||
@ -923,11 +933,11 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper):
|
||||
if context.active_object and context.active_object.mode != 'OBJECT':
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
|
||||
self.import_images(context)
|
||||
ret_code = self.import_images(context)
|
||||
|
||||
context.preferences.edit.use_enter_edit_mode = editmode
|
||||
|
||||
return {'FINISHED'}
|
||||
return ret_code
|
||||
|
||||
def import_images(self, context):
|
||||
|
||||
@ -939,6 +949,10 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper):
|
||||
find_sequences=self.image_sequence
|
||||
))
|
||||
|
||||
if not images:
|
||||
self.report({'WARNING'}, "Please select at least an image.")
|
||||
return {'CANCELLED'}
|
||||
|
||||
# Create individual planes
|
||||
planes = [self.single_image_spec_to_plane(context, img_spec) for img_spec in images]
|
||||
|
||||
@ -962,6 +976,7 @@ class IMPORT_IMAGE_OT_to_plane(Operator, AddObjectHelper):
|
||||
|
||||
# all done!
|
||||
self.report({'INFO'}, tip_("Added {} Image Plane(s)").format(len(planes)))
|
||||
return {'FINISHED'}
|
||||
|
||||
# operate on a single image
|
||||
def single_image_spec_to_plane(self, context, img_spec):
|
||||
|
@ -244,7 +244,7 @@ def skip_to_end(file, skip_chunk):
|
||||
# MATERIALS #
|
||||
#############
|
||||
|
||||
def add_texture_to_material(image, contextWrapper, pct, extend, alpha, scale, offset, angle, tintcolor, mapto):
|
||||
def add_texture_to_material(image, contextWrapper, pct, extend, alpha, scale, offset, angle, tint1, tint2, mapto):
|
||||
shader = contextWrapper.node_principled_bsdf
|
||||
nodetree = contextWrapper.material.node_tree
|
||||
shader.location = (-300, 0)
|
||||
@ -256,13 +256,16 @@ def add_texture_to_material(image, contextWrapper, pct, extend, alpha, scale, of
|
||||
mixer.label = "Mixer"
|
||||
mixer.inputs[0].default_value = pct / 100
|
||||
mixer.inputs[1].default_value = (
|
||||
tintcolor[:3] + [1] if tintcolor else
|
||||
shader.inputs['Base Color'].default_value[:]
|
||||
)
|
||||
tint1[:3] + [1] if tint1 else shader.inputs['Base Color'].default_value[:])
|
||||
contextWrapper._grid_to_location(1, 2, dst_node=mixer, ref_node=shader)
|
||||
img_wrap = contextWrapper.base_color_texture
|
||||
links.new(img_wrap.node_image.outputs['Color'], mixer.inputs[2])
|
||||
links.new(mixer.outputs['Color'], shader.inputs['Base Color'])
|
||||
if tint2 is not None:
|
||||
img_wrap.colorspace_name = 'Non-Color'
|
||||
mixer.inputs[2].default_value = tint2[:3] + [1]
|
||||
links.new(img_wrap.node_image.outputs['Color'], mixer.inputs[0])
|
||||
else:
|
||||
links.new(img_wrap.node_image.outputs['Color'], mixer.inputs[2])
|
||||
elif mapto == 'ROUGHNESS':
|
||||
img_wrap = contextWrapper.roughness_texture
|
||||
elif mapto == 'METALLIC':
|
||||
@ -274,6 +277,8 @@ def add_texture_to_material(image, contextWrapper, pct, extend, alpha, scale, of
|
||||
elif mapto == 'ALPHA':
|
||||
shader.location = (-300,0)
|
||||
img_wrap = contextWrapper.alpha_texture
|
||||
img_wrap.use_alpha = False
|
||||
links.new(img_wrap.node_image.outputs['Color'], img_wrap.socket_dst)
|
||||
elif mapto == 'EMISSION':
|
||||
shader.location = (0,-900)
|
||||
img_wrap = contextWrapper.emission_color_texture
|
||||
@ -310,10 +315,12 @@ def add_texture_to_material(image, contextWrapper, pct, extend, alpha, scale, of
|
||||
img_wrap.extension = 'CLIP'
|
||||
|
||||
if alpha == 'alpha':
|
||||
own_node = img_wrap.node_image
|
||||
contextWrapper.material.blend_method = 'HASHED'
|
||||
links.new(own_node.outputs['Alpha'], img_wrap.socket_dst)
|
||||
for link in links:
|
||||
if link.from_node.type == 'TEX_IMAGE' and link.to_node.type == 'MIX_RGB':
|
||||
tex = link.from_node.image.name
|
||||
own_node = img_wrap.node_image
|
||||
own_map = img_wrap.node_mapping
|
||||
if tex == image.name:
|
||||
links.new(link.from_node.outputs['Alpha'], img_wrap.socket_dst)
|
||||
@ -323,9 +330,6 @@ def add_texture_to_material(image, contextWrapper, pct, extend, alpha, scale, of
|
||||
if imgs.name[-3:].isdigit():
|
||||
if not imgs.users:
|
||||
bpy.data.images.remove(imgs)
|
||||
else:
|
||||
links.new(img_wrap.node_image.outputs['Alpha'], img_wrap.socket_dst)
|
||||
contextWrapper.material.blend_method = 'HASHED'
|
||||
|
||||
shader.location = (300, 300)
|
||||
contextWrapper._grid_to_location(1, 0, dst_node=contextWrapper.node_out, ref_node=shader)
|
||||
@ -518,7 +522,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
||||
def read_texture(new_chunk, temp_chunk, name, mapto):
|
||||
uscale, vscale, uoffset, voffset, angle = 1.0, 1.0, 0.0, 0.0, 0.0
|
||||
contextWrapper.use_nodes = True
|
||||
tintcolor = None
|
||||
tint1 = tint2 = None
|
||||
extend = 'wrap'
|
||||
alpha = False
|
||||
pct = 70
|
||||
@ -542,14 +546,8 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
||||
img = load_image(texture_name, dirname, place_holder=False, recursive=IMAGE_SEARCH, check_existing=True)
|
||||
temp_chunk.bytes_read += read_str_len # plus one for the null character that gets removed
|
||||
|
||||
elif temp_chunk.ID == MAT_MAP_USCALE:
|
||||
uscale = read_float(temp_chunk)
|
||||
elif temp_chunk.ID == MAT_MAP_VSCALE:
|
||||
vscale = read_float(temp_chunk)
|
||||
elif temp_chunk.ID == MAT_MAP_UOFFSET:
|
||||
uoffset = read_float(temp_chunk)
|
||||
elif temp_chunk.ID == MAT_MAP_VOFFSET:
|
||||
voffset = read_float(temp_chunk)
|
||||
elif temp_chunk.ID == MAT_BUMP_PERCENT:
|
||||
contextWrapper.normalmap_strength = (float(read_short(temp_chunk) / 100))
|
||||
|
||||
elif temp_chunk.ID == MAT_MAP_TILING:
|
||||
"""Control bit flags, where 0x1 activates decaling, 0x2 activates mirror,
|
||||
@ -578,11 +576,20 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
||||
if tiling & 0x200:
|
||||
tint = 'RGBtint'
|
||||
|
||||
elif temp_chunk.ID == MAT_MAP_USCALE:
|
||||
uscale = read_float(temp_chunk)
|
||||
elif temp_chunk.ID == MAT_MAP_VSCALE:
|
||||
vscale = read_float(temp_chunk)
|
||||
elif temp_chunk.ID == MAT_MAP_UOFFSET:
|
||||
uoffset = read_float(temp_chunk)
|
||||
elif temp_chunk.ID == MAT_MAP_VOFFSET:
|
||||
voffset = read_float(temp_chunk)
|
||||
elif temp_chunk.ID == MAT_MAP_ANG:
|
||||
angle = read_float(temp_chunk)
|
||||
|
||||
elif temp_chunk.ID == MAT_MAP_COL1:
|
||||
tintcolor = read_byte_color(temp_chunk)
|
||||
tint1 = read_byte_color(temp_chunk)
|
||||
elif temp_chunk.ID == MAT_MAP_COL2:
|
||||
tint2 = read_byte_color(temp_chunk)
|
||||
|
||||
skip_to_end(file, temp_chunk)
|
||||
new_chunk.bytes_read += temp_chunk.bytes_read
|
||||
@ -590,7 +597,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
||||
# add the map to the material in the right channel
|
||||
if img:
|
||||
add_texture_to_material(img, contextWrapper, pct, extend, alpha, (uscale, vscale, 1),
|
||||
(uoffset, voffset, 0), angle, tintcolor, mapto)
|
||||
(uoffset, voffset, 0), angle, tint1, tint2, mapto)
|
||||
|
||||
def apply_constrain(vec):
|
||||
convector = mathutils.Vector.Fill(3, (CONSTRAIN * 0.1))
|
||||
@ -1381,6 +1388,7 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI
|
||||
elif KEYFRAME and new_chunk.ID == POS_TRACK_TAG and tracktype == 'TARGET': # Target position
|
||||
keyframe_data = {}
|
||||
location = child.location
|
||||
keyframe_data[0] = trackposition[0]
|
||||
target = mathutils.Vector(read_track_data(new_chunk)[0])
|
||||
direction = calc_target(location, target)
|
||||
child.rotation_euler.x = direction[0]
|
||||
|
@ -5,7 +5,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": (4, 0, 34),
|
||||
"version": (4, 0, 38),
|
||||
'blender': (4, 0, 0),
|
||||
'location': 'File > Import-Export',
|
||||
'description': 'Import-Export as glTF 2.0',
|
||||
@ -144,13 +144,10 @@ class ExportGLTF2_Base(ConvertGLTF2_Base):
|
||||
'Most efficient and portable, but more difficult to edit later'),
|
||||
('GLTF_SEPARATE', 'glTF Separate (.gltf + .bin + textures)',
|
||||
'Exports multiple files, with separate JSON, binary and texture data. '
|
||||
'Easiest to edit later'),
|
||||
('GLTF_EMBEDDED', 'glTF Embedded (.gltf)',
|
||||
'Exports a single file, with all data packed in JSON. '
|
||||
'Less efficient than binary, but easier to edit later')),
|
||||
'Easiest to edit later')),
|
||||
description=(
|
||||
'Output format and embedding options. Binary is most efficient, '
|
||||
'but JSON (embedded or separate) may be easier to edit later'
|
||||
'Output format. Binary is most efficient, '
|
||||
'but JSON may be easier to edit later'
|
||||
),
|
||||
default='GLB', #Warning => If you change the default, need to change the default filter too
|
||||
update=on_export_format_changed,
|
||||
@ -174,13 +171,13 @@ class ExportGLTF2_Base(ConvertGLTF2_Base):
|
||||
export_image_format: EnumProperty(
|
||||
name='Images',
|
||||
items=(('AUTO', 'Automatic',
|
||||
'Save PNGs as PNGs, JPEGs as JPEGs, WEBPs as WEBPs. '
|
||||
'Save PNGs as PNGs, JPEGs as JPEGs, WebPs as WebPs. '
|
||||
'If neither one, use PNG'),
|
||||
('JPEG', 'JPEG Format (.jpg)',
|
||||
'Save images as JPEGs. (Images that need alpha are saved as PNGs though.) '
|
||||
'Be aware of a possible loss in quality'),
|
||||
('WEBP', 'Webp Format',
|
||||
'Save images as WEBPs as main image (no fallback)'),
|
||||
('WEBP', 'WebP Format',
|
||||
'Save images as WebPs as main image (no fallback)'),
|
||||
('NONE', 'None',
|
||||
'Don\'t export images'),
|
||||
),
|
||||
@ -192,18 +189,18 @@ class ExportGLTF2_Base(ConvertGLTF2_Base):
|
||||
)
|
||||
|
||||
export_image_add_webp: BoolProperty(
|
||||
name='Create Webp',
|
||||
name='Create WebP',
|
||||
description=(
|
||||
"Creates webp textures for every textures. "
|
||||
"For already webp textures, nothing happen"
|
||||
"Creates WebP textures for every textures. "
|
||||
"For already WebP textures, nothing happen"
|
||||
),
|
||||
default=False
|
||||
)
|
||||
|
||||
export_image_webp_fallback: BoolProperty(
|
||||
name='Webp fallback',
|
||||
name='WebP fallback',
|
||||
description=(
|
||||
"For all webp textures, create a PNG fallback texture."
|
||||
"For all WebP textures, create a PNG fallback texture"
|
||||
),
|
||||
default=False
|
||||
)
|
||||
@ -1674,10 +1671,10 @@ class ImportGLTF2(Operator, ConvertGLTF2_Base, ImportHelper):
|
||||
)
|
||||
|
||||
import_webp_texture: BoolProperty(
|
||||
name='Import Webp textures',
|
||||
name='Import WebP textures',
|
||||
description=(
|
||||
"If a texture exists in webp format,"
|
||||
"loads the webp texture instead of the fallback png/jpg one"
|
||||
"If a texture exists in WebP format,"
|
||||
"loads the WebP texture instead of the fallback png/jpg one"
|
||||
),
|
||||
default=False,
|
||||
)
|
||||
|
@ -86,11 +86,8 @@ def __create_buffer(exporter, export_settings):
|
||||
if export_settings['gltf_format'] == 'GLB':
|
||||
buffer = exporter.finalize_buffer(export_settings['gltf_filedirectory'], is_glb=True)
|
||||
else:
|
||||
if export_settings['gltf_format'] == 'GLTF_EMBEDDED':
|
||||
exporter.finalize_buffer(export_settings['gltf_filedirectory'])
|
||||
else:
|
||||
exporter.finalize_buffer(export_settings['gltf_filedirectory'],
|
||||
export_settings['gltf_binaryfilename'])
|
||||
exporter.finalize_buffer(export_settings['gltf_filedirectory'],
|
||||
export_settings['gltf_binaryfilename'])
|
||||
|
||||
return buffer
|
||||
|
||||
|
@ -117,7 +117,7 @@ class GlTF2Exporter:
|
||||
f.write(self.__buffer.to_bytes())
|
||||
uri = buffer_name
|
||||
else:
|
||||
uri = self.__buffer.to_embed_string()
|
||||
pass # This is no more possible, we don't export embedded buffers
|
||||
|
||||
buffer = gltf2_io.Buffer(
|
||||
byte_length=self.__buffer.byte_length,
|
||||
@ -320,6 +320,20 @@ class GlTF2Exporter:
|
||||
len_ = len([i for i in self.nodes_idx_to_remove if i < skin.skeleton])
|
||||
skin.skeleton = skin.skeleton - len_
|
||||
|
||||
# Remove animation channels that was targeting a node that will be removed
|
||||
new_animation_list = []
|
||||
for animation in self.__gltf.animations:
|
||||
new_channel_list = []
|
||||
for channel in animation.channels:
|
||||
if channel.target.node not in self.nodes_idx_to_remove:
|
||||
new_channel_list.append(channel)
|
||||
animation.channels = new_channel_list
|
||||
if len(animation.channels) > 0:
|
||||
new_animation_list.append(animation)
|
||||
self.__gltf.animations = new_animation_list
|
||||
|
||||
#TODO: remove unused animation accessors?
|
||||
|
||||
# And now really remove nodes
|
||||
self.__gltf.nodes = [node for idx, node in enumerate(self.__gltf.nodes) if idx not in self.nodes_idx_to_remove]
|
||||
|
||||
|
@ -9,6 +9,7 @@ from ...material.gltf2_blender_gather_texture_info import gather_texture_info
|
||||
|
||||
def export_specular(blender_material, export_settings):
|
||||
specular_extension = {}
|
||||
extensions_needed = False
|
||||
|
||||
specular_socket = gltf2_blender_get.get_socket(blender_material, 'Specular IOR Level')
|
||||
speculartint_socket = gltf2_blender_get.get_socket(blender_material, 'Specular Tint')
|
||||
@ -23,18 +24,27 @@ def export_specular(blender_material, export_settings):
|
||||
|
||||
if specular_non_linked is True:
|
||||
fac = specular_socket.default_value
|
||||
if fac != 1.0:
|
||||
fac = fac * 2.0
|
||||
if fac < 1.0:
|
||||
specular_extension['specularFactor'] = fac
|
||||
if fac == 0.0:
|
||||
return None, {}
|
||||
extensions_needed = True
|
||||
elif fac > 1.0:
|
||||
# glTF specularFactor should be <= 1.0, so we will multiply ColorFactory by specularFactor, and set SpecularFactor to 1.0 (default value)
|
||||
extensions_needed = True
|
||||
else:
|
||||
pass # If fac == 1.0, no need to export specularFactor, the default value is 1.0
|
||||
|
||||
else:
|
||||
# Factor
|
||||
fac = gltf2_blender_get.get_factor_from_socket(specular_socket, kind='VALUE')
|
||||
if fac is not None and fac != 1.0:
|
||||
specular_extension['specularFactor'] = fac
|
||||
|
||||
if fac == 0.0:
|
||||
return None, {}
|
||||
fac = fac * 2.0 if fac is not None else None
|
||||
if fac is not None and fac < 1.0:
|
||||
specular_extension['specularFactor'] = fac
|
||||
extensions_needed = True
|
||||
elif fac is not None and fac > 1.0:
|
||||
# glTF specularFactor should be <= 1.0, so we will multiply ColorFactory by specularFactor, and set SpecularFactor to 1.0 (default value)
|
||||
extensions_needed = True
|
||||
|
||||
# Texture
|
||||
if gltf2_blender_get.has_image_node_from_socket(specular_socket):
|
||||
@ -46,16 +56,26 @@ def export_specular(blender_material, export_settings):
|
||||
)
|
||||
specular_extension['specularTexture'] = original_specular_texture
|
||||
uvmap_infos.update({'specularTexture': uvmap_info})
|
||||
extensions_needed = True
|
||||
|
||||
if specularcolor_non_linked is True:
|
||||
color = speculartint_socket.default_value[:3]
|
||||
if fac is not None and fac > 1.0:
|
||||
color = (color[0] * fac, color[1] * fac, color[2] * fac)
|
||||
specular_extension['specularColorFactor'] = color if color != (1.0, 1.0, 1.0) else None
|
||||
if color != (1.0, 1.0, 1.0):
|
||||
specular_extension['specularColorFactor'] = color
|
||||
extensions_needed = True
|
||||
|
||||
else:
|
||||
# Factor
|
||||
fac = gltf2_blender_get.get_factor_from_socket(speculartint_socket, kind='RGB')
|
||||
if fac is not None and fac != (1.0, 1.0, 1.0):
|
||||
specular_extension['specularColorFactor'] = fac
|
||||
fac_color = gltf2_blender_get.get_factor_from_socket(speculartint_socket, kind='RGB')
|
||||
if fac_color is not None and fac is not None and fac > 1.0:
|
||||
fac_color = (fac_color[0] * fac, fac_color[1] * fac, fac_color[2] * fac)
|
||||
elif fac_color is None and fac is not None and fac > 1.0:
|
||||
fac_color = (fac, fac, fac)
|
||||
specular_extension['specularColorFactor'] = fac_color if fac_color != (1.0, 1.0, 1.0) else None
|
||||
if fac_color != (1.0, 1.0, 1.0):
|
||||
extensions_needed = True
|
||||
|
||||
# Texture
|
||||
if gltf2_blender_get.has_image_node_from_socket(speculartint_socket):
|
||||
@ -67,5 +87,9 @@ def export_specular(blender_material, export_settings):
|
||||
)
|
||||
specular_extension['specularColorTexture'] = original_specularcolor_texture
|
||||
uvmap_infos.update({'specularColorTexture': uvmap_info})
|
||||
extensions_needed = True
|
||||
|
||||
if extensions_needed is False:
|
||||
return None, {}
|
||||
|
||||
return Extension('KHR_materials_specular', specular_extension, False), uvmap_infos
|
||||
|
@ -59,7 +59,7 @@ def gather_image(
|
||||
|
||||
export_user_extensions('gather_image_hook', export_settings, image, blender_shader_sockets)
|
||||
|
||||
# We also return image_data, as it can be used to generate same file with another extension for webp management
|
||||
# We also return image_data, as it can be used to generate same file with another extension for WebP management
|
||||
return image, image_data, factor
|
||||
|
||||
def __gather_original_uri(original_uri, export_settings):
|
||||
@ -118,7 +118,7 @@ def __gather_mime_type(sockets, export_image, export_settings):
|
||||
if export_settings["gltf_image_format"] == "WEBP":
|
||||
return "image/webp"
|
||||
else:
|
||||
# If we keep image as is (no channel composition), we need to keep original format (for webp)
|
||||
# If we keep image as is (no channel composition), we need to keep original format (for WebP)
|
||||
image = export_image.blender_image()
|
||||
if image is not None and __is_blender_image_a_webp(image):
|
||||
return "image/webp"
|
||||
|
@ -70,7 +70,7 @@ def __gather_extensions(blender_shader_sockets, source, webp_image, image_data,
|
||||
|
||||
ext_webp = {}
|
||||
|
||||
# If user want to keep original textures, and these textures are webp, we need to remove source from
|
||||
# If user want to keep original textures, and these textures are WebP, we need to remove source from
|
||||
# gltf2_io.Texture, and populate extension
|
||||
if export_settings['gltf_keep_original_textures'] is True \
|
||||
and source is not None \
|
||||
@ -79,19 +79,19 @@ def __gather_extensions(blender_shader_sockets, source, webp_image, image_data,
|
||||
remove_source = True
|
||||
required = True
|
||||
|
||||
# If user want to export in webp format (so without fallback in png/jpg)
|
||||
# If user want to export in WebP format (so without fallback in png/jpg)
|
||||
if export_settings['gltf_image_format'] == "WEBP":
|
||||
# We create all image without fallback
|
||||
ext_webp["source"] = source
|
||||
remove_source = True
|
||||
required = True
|
||||
|
||||
# If user doesn't want to export in webp format, but want webp too. Texture is not webp
|
||||
# If user doesn't want to export in WebP format, but want WebP too. Texture is not WebP
|
||||
if export_settings['gltf_image_format'] != "WEBP" \
|
||||
and export_settings['gltf_add_webp'] \
|
||||
and source is not None \
|
||||
and source.mime_type != "image/webp":
|
||||
# We need here to create some webp textures
|
||||
# We need here to create some WebP textures
|
||||
|
||||
new_mime_type = "image/webp"
|
||||
new_data, _ = image_data.encode(new_mime_type, export_settings)
|
||||
@ -116,7 +116,7 @@ def __gather_extensions(blender_shader_sockets, source, webp_image, image_data,
|
||||
ext_webp["source"] = webp_image
|
||||
|
||||
|
||||
# If user doesn't want to export in webp format, but want webp too. Texture is webp
|
||||
# If user doesn't want to export in WebP format, but want WebP too. Texture is WebP
|
||||
if export_settings['gltf_image_format'] != "WEBP" \
|
||||
and source is not None \
|
||||
and source.mime_type == "image/webp":
|
||||
@ -127,7 +127,7 @@ def __gather_extensions(blender_shader_sockets, source, webp_image, image_data,
|
||||
remove_source = True
|
||||
required = True
|
||||
|
||||
# If user doesn't want to export in webp format, but want webp too as fallback. Texture is webp
|
||||
# If user doesn't want to export in webp format, but want WebP too as fallback. Texture is WebP
|
||||
if export_settings['gltf_image_format'] != "WEBP" \
|
||||
and webp_image is not None \
|
||||
and export_settings['gltf_webp_fallback'] is True:
|
||||
@ -209,7 +209,7 @@ def __gather_source(blender_shader_sockets, default_sockets, export_settings):
|
||||
|
||||
png_image = __make_webp_image(buffer_view, None, None, new_mime_type, name, uri, export_settings)
|
||||
|
||||
# We inverted the png & webp image, to have the png as main source
|
||||
# We inverted the png & WebP image, to have the png as main source
|
||||
return png_image, source, image_data, factor
|
||||
return source, None, image_data, factor
|
||||
|
||||
|
@ -39,7 +39,7 @@ def specular(mh, location_specular,
|
||||
x_specularcolor, y_specularcolor = location_specular_tint
|
||||
|
||||
if tex_specular_info is None:
|
||||
specular_socket.default_value = specular_factor
|
||||
specular_socket.default_value = specular_factor / 2.0
|
||||
else:
|
||||
# Mix specular factor
|
||||
if specular_factor != 1.0:
|
||||
@ -51,7 +51,7 @@ def specular(mh, location_specular,
|
||||
mh.node_tree.links.new(specular_socket, node.outputs[0])
|
||||
# Inputs
|
||||
specular_socket = node.inputs[0]
|
||||
node.inputs[1].default_value = specular_factor
|
||||
node.inputs[1].default_value = specular_factor / 2.0
|
||||
x_specular -= 200
|
||||
|
||||
texture(
|
||||
|
@ -50,9 +50,6 @@ def pbr_metallic_roughness(mh: MaterialHelper):
|
||||
# This value may be overridden later if IOR extension is set on file
|
||||
pbr_node.inputs['IOR'].default_value = GLTF_IOR
|
||||
|
||||
pbr_node.inputs['Specular IOR Level'].default_value = 0.0 # Will be overridden by KHR_materials_specular if set
|
||||
pbr_node.inputs['Specular Tint'].default_value = [0.0]*3 + [1.0] # Will be overridden by KHR_materials_specular if set
|
||||
|
||||
if mh.pymat.occlusion_texture is not None:
|
||||
if mh.settings_node is None:
|
||||
mh.settings_node = make_settings_node(mh)
|
||||
|
@ -41,7 +41,7 @@ def texture(
|
||||
if forced_image is None:
|
||||
|
||||
if mh.gltf.import_settings['import_webp_texture'] is True:
|
||||
# Get the webp image if there is one
|
||||
# Get the WebP image if there is one
|
||||
if pytexture.extensions \
|
||||
and 'EXT_texture_webp' in pytexture.extensions \
|
||||
and pytexture.extensions['EXT_texture_webp']['source'] is not None:
|
||||
|
@ -47,8 +47,5 @@ class Buffer:
|
||||
def to_bytes(self):
|
||||
return self.__data
|
||||
|
||||
def to_embed_string(self):
|
||||
return 'data:application/octet-stream;base64,' + base64.b64encode(self.__data).decode('ascii')
|
||||
|
||||
def clear(self):
|
||||
self.__data = b""
|
||||
|
@ -89,10 +89,10 @@ class ActionSlot(PropertyGroup, ActionSlotBase):
|
||||
|
||||
target_space: EnumProperty(
|
||||
name="Transform Space",
|
||||
items=[("WORLD", "World Space", "World Space"),
|
||||
("POSE", "Pose Space", "Pose Space"),
|
||||
("LOCAL_WITH_PARENT", "Local With Parent", "Local With Parent"),
|
||||
("LOCAL", "Local Space", "Local Space")],
|
||||
items=[("WORLD", "World Space", "World Space", 0),
|
||||
# ("POSE", "Pose Space", "Pose Space", 1),
|
||||
# ("LOCAL_WITH_PARENT", "Local With Parent", "Local With Parent", 2),
|
||||
("LOCAL", "Local Space", "Local Space", 3)],
|
||||
default="LOCAL"
|
||||
)
|
||||
|
||||
|
@ -153,9 +153,10 @@ def pVisRotExec(bone, active, context):
|
||||
|
||||
def pVisScaExec(bone, active, context):
|
||||
obj_bone = bone.id_data
|
||||
bone.scale = getmat(bone, active, context,
|
||||
not obj_bone.data.bones[bone.name].use_inherit_scale)\
|
||||
.to_scale()
|
||||
bone.scale = getmat(
|
||||
bone, active, context,
|
||||
obj_bone.data.bones[bone.name].inherit_scale not in {'NONE', 'NONE_LEGACY'}
|
||||
).to_scale()
|
||||
|
||||
|
||||
def pDrwExec(bone, active, context):
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
import bpy
|
||||
from bpy.props import FloatProperty, FloatVectorProperty
|
||||
from bpy.app.translations import pgettext_iface as iface_
|
||||
import gpu
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
from mathutils import Vector
|
||||
@ -248,8 +249,8 @@ class SUNPOS_OT_ShowHdr(bpy.types.Operator):
|
||||
self.initial_azimuth = context.scene.sun_pos_properties.hdr_azimuth
|
||||
|
||||
context.workspace.status_text_set(
|
||||
"Enter/LMB: confirm, Esc/RMB: cancel,"
|
||||
" MMB: pan, mouse wheel: zoom, Ctrl + mouse wheel: set exposure")
|
||||
iface_("Enter/LMB: confirm, Esc/RMB: cancel, MMB: pan, "
|
||||
"mouse wheel: zoom, Ctrl + mouse wheel: set exposure"))
|
||||
|
||||
self._handle = bpy.types.SpaceView3D.draw_handler_add(
|
||||
draw_callback_px, (self, context), 'WINDOW', 'POST_PIXEL'
|
||||
|
@ -416,6 +416,19 @@ translations_tuple = (
|
||||
("fr_FR", "Année",
|
||||
(False, ())),
|
||||
),
|
||||
(("*", "Unknown projection"),
|
||||
(("scripts/addons/sun_position/hdr.py:181",),
|
||||
()),
|
||||
("fr_FR", "Projection inconnue",
|
||||
(False, ())),
|
||||
),
|
||||
(("*", "Enter/LMB: confirm, Esc/RMB: cancel, MMB: pan, mouse wheel: zoom, Ctrl + mouse wheel: set exposure"),
|
||||
(("scripts/addons/sun_position/hdr.py:252",),
|
||||
()),
|
||||
("fr_FR", "Entrée/ClicG : Confirmer, Échap/ClicD : Annuler, ClicM : défiler, "
|
||||
"molette : zoom, Ctrl + molette : exposition",
|
||||
(False, ())),
|
||||
),
|
||||
(("*", "Could not find 3D View"),
|
||||
(("scripts/addons/sun_position/hdr.py:263",),
|
||||
()),
|
||||
@ -428,12 +441,6 @@ translations_tuple = (
|
||||
("fr_FR", "Veuillez utiliser un nœud de texture d’environnement",
|
||||
(False, ())),
|
||||
),
|
||||
(("*", "Unknown projection"),
|
||||
(("scripts/addons/sun_position/hdr.py:181",),
|
||||
()),
|
||||
("fr_FR", "Projection inconnue",
|
||||
(False, ())),
|
||||
),
|
||||
(("*", "Show options and info:"),
|
||||
(("scripts/addons/sun_position/properties.py:297",),
|
||||
()),
|
||||
|
@ -344,7 +344,9 @@ class UI_OT_i18n_addon_translation_export(Operator):
|
||||
if not lng.use:
|
||||
print("Skipping {} language ({}).".format(lng.name, lng.uid))
|
||||
continue
|
||||
uid = utils_i18n.find_best_isocode_matches(lng.uid, trans.trans.keys())
|
||||
translation_keys = {k for k in trans.trans.keys()
|
||||
if k != self.settings.PARSER_TEMPLATE_ID}
|
||||
uid = utils_i18n.find_best_isocode_matches(lng.uid, translation_keys)
|
||||
if uid:
|
||||
uids.append(uid[0])
|
||||
|
||||
@ -357,8 +359,8 @@ class UI_OT_i18n_addon_translation_export(Operator):
|
||||
if not os.path.isfile(path):
|
||||
continue
|
||||
msgs = utils_i18n.I18nMessages(kind='PO', src=path, settings=self.settings)
|
||||
msgs.update(trans.msgs[self.settings.PARSER_TEMPLATE_ID])
|
||||
trans.msgs[uid] = msgs
|
||||
msgs.update(trans.trans[self.settings.PARSER_TEMPLATE_ID])
|
||||
trans.trans[uid] = msgs
|
||||
|
||||
trans.write(kind='PO', langs=set(uids))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user