Update leenkx/blender/lnx/material/cycles.py
This commit is contained in:
@ -69,9 +69,12 @@ def resize_texture_if_needed(image: bpy.types.Image, filepath: str, max_size: in
|
|||||||
if image.size[0] <= max_size and image.size[1] <= max_size:
|
if image.size[0] <= max_size and image.size[1] <= max_size:
|
||||||
return filepath
|
return filepath
|
||||||
|
|
||||||
cache_key = (filepath, max_size, os.path.getmtime(filepath) if os.path.exists(filepath) else 0)
|
wrd = bpy.data.worlds['Lnx']
|
||||||
if cache_key in texture_resize_cache:
|
texture_quality = wrd.lnx_texture_quality
|
||||||
cached_path = texture_resize_cache[cache_key]
|
|
||||||
|
cache_key = (filepath, max_size, texture_quality, os.path.getmtime(filepath) if os.path.exists(filepath) else 0)
|
||||||
|
if cache_key in _texture_resize_cache:
|
||||||
|
cached_path = _texture_resize_cache[cache_key]
|
||||||
if os.path.exists(cached_path):
|
if os.path.exists(cached_path):
|
||||||
return cached_path
|
return cached_path
|
||||||
|
|
||||||
@ -84,38 +87,78 @@ def resize_texture_if_needed(image: bpy.types.Image, filepath: str, max_size: in
|
|||||||
new_width = int((width / height) * max_size)
|
new_width = int((width / height) * max_size)
|
||||||
|
|
||||||
build_dir = lnx.utils.get_fp_build()
|
build_dir = lnx.utils.get_fp_build()
|
||||||
resized_dir = os.path.join(build_dir, 'compiled', 'Assets', 'resized_textures')
|
resized_dir = os.path.join(build_dir, 'compiled', 'Assets', 'unpacked')
|
||||||
os.makedirs(resized_dir, exist_ok=True)
|
os.makedirs(resized_dir, exist_ok=True)
|
||||||
|
|
||||||
basename = os.path.basename(filepath)
|
basename = os.path.basename(filepath)
|
||||||
name, ext = os.path.splitext(basename)
|
name, ext = os.path.splitext(basename)
|
||||||
resized_path = os.path.join(resized_dir, f"{name}_{max_size}px{ext}")
|
quality_suffix = f"q{int(texture_quality * 100)}"
|
||||||
|
resized_path = os.path.join(resized_dir, f"{name}_{max_size}px_{quality_suffix}{ext}")
|
||||||
|
|
||||||
if os.path.exists(resized_path):
|
if os.path.exists(resized_path):
|
||||||
src_mtime = os.path.getmtime(filepath)
|
src_mtime = os.path.getmtime(filepath)
|
||||||
dst_mtime = os.path.getmtime(resized_path)
|
dst_mtime = os.path.getmtime(resized_path)
|
||||||
if dst_mtime >= src_mtime:
|
if dst_mtime >= src_mtime:
|
||||||
print(f"Using cached: {basename} -> {new_width}x{new_height}")
|
_texture_resize_cache[cache_key] = resized_path
|
||||||
texture_resize_cache[cache_key] = resized_path
|
|
||||||
return resized_path
|
return resized_path
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from PIL import Image as PILImage
|
ffmpeg_path = lnx.utils.get_ffmpeg_path()
|
||||||
img = PILImage.open(filepath)
|
|
||||||
img_resized = img.resize((new_width, new_height), PILImage.Resampling.LANCZOS)
|
if ffmpeg_path is None or ffmpeg_path == '':
|
||||||
img_resized.save(resized_path, quality=95, optimize=True)
|
print(f"[Texture Optimizer] WARNING: FFmpeg not found. Please set FFmpeg path in addon preferences.")
|
||||||
print(f"Resized: {basename} {width}x{height} -> {new_width}x{new_height}")
|
print(f"[Texture Optimizer] Skipping resize for: {basename}")
|
||||||
texture_resize_cache[cache_key] = resized_path
|
return filepath
|
||||||
return resized_path
|
|
||||||
except ImportError:
|
file_ext = os.path.splitext(filepath)[1].lower().lstrip('.')
|
||||||
print(f"WARNING: PIL/Pillow not installed. Install with: pip install Pillow")
|
|
||||||
print(f"Skipping resize for: {basename}")
|
cmd = [
|
||||||
|
ffmpeg_path,
|
||||||
|
'-y',
|
||||||
|
'-i', filepath,
|
||||||
|
'-vf', f'scale={new_width}:{new_height}:flags=lanczos',
|
||||||
|
]
|
||||||
|
|
||||||
|
if file_ext in ('png', 'tga', 'bmp'):
|
||||||
|
compression_level = round((1.0 - texture_quality) * 9)
|
||||||
|
cmd.extend(['-compression_level', str(compression_level)])
|
||||||
|
else:
|
||||||
|
qscale = round(2 + (1.0 - texture_quality) * 29)
|
||||||
|
cmd.extend(['-q:v', str(qscale)])
|
||||||
|
|
||||||
|
cmd.append(resized_path)
|
||||||
|
|
||||||
|
startupinfo = None
|
||||||
|
if os.name == 'nt':
|
||||||
|
startupinfo = subprocess.STARTUPINFO()
|
||||||
|
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||||
|
startupinfo.wShowWindow = subprocess.SW_HIDE
|
||||||
|
|
||||||
|
result = subprocess.run(
|
||||||
|
cmd,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
startupinfo=startupinfo,
|
||||||
|
timeout=60
|
||||||
|
)
|
||||||
|
|
||||||
|
if result.returncode == 0 and os.path.exists(resized_path):
|
||||||
|
print(f"[Texture Optimizer] Resized: {basename} {width}x{height} -> {new_width}x{new_height}")
|
||||||
|
_texture_resize_cache[cache_key] = resized_path
|
||||||
|
return resized_path
|
||||||
|
else:
|
||||||
|
error_msg = result.stderr.decode('utf-8', errors='ignore') if result.stderr else 'Unknown error'
|
||||||
|
print(f"[Texture Optimizer] WARNING: FFmpeg failed to resize {basename}: {error_msg}")
|
||||||
|
return filepath
|
||||||
|
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
print(f"[Texture Optimizer] WARNING: FFmpeg timeout while resizing {basename}")
|
||||||
return filepath
|
return filepath
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"WARNING: Failed to resize {basename}: {e}")
|
print(f"[Texture Optimizer] WARNING: Failed to resize {basename}: {e}")
|
||||||
return filepath
|
return filepath
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def parse(nodes, con: ShaderContext,
|
def parse(nodes, con: ShaderContext,
|
||||||
vert: Shader, frag: Shader, geom: Shader, tesc: Shader, tese: Shader,
|
vert: Shader, frag: Shader, geom: Shader, tesc: Shader, tese: Shader,
|
||||||
parse_surface=True, parse_opacity=True, parse_displacement=True, basecol_only=False):
|
parse_surface=True, parse_opacity=True, parse_displacement=True, basecol_only=False):
|
||||||
|
|||||||
Reference in New Issue
Block a user