Files
blender-portable-repo/extensions/user_default/blenderkit/autothumb_material_bg.py
T
2026-03-17 15:25:32 -06:00

261 lines
10 KiB
Python

# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# type: ignore
import json
import os
import sys
from pathlib import Path
from traceback import print_exc
import bpy
def render_thumbnails():
bpy.ops.render.render(write_still=True, animation=False)
def unhide_collection(cname):
collection = bpy.context.scene.collection.children[cname]
collection.hide_viewport = False
collection.hide_render = False
collection.hide_select = False
def patch_imports(addon_module_name: str):
"""Patch the python configuration, so the relative imports work as expected. There are few problems to fix:
1. Script is not recognized as module which would break at relative import. We need to set __package__ = "blenderkit" for legacy addon.
Or __package__ = "bl_ext.user_default.blenderkit"/"bl_ext.blenderkit_com.blenderkit_com". Otherwise we would see:
from . import paths
ImportError: attempted relative import with no known parent package
2. External repository (e.g. blenderkit_com) is not available as we start with --factory-startup, we need to enable it.
We can add it as LOCAL repo as the add-on is installed and we do not care about updates or anything in this BG script. Otherwise we would see:
from . import paths
ModuleNotFoundError: No module named 'bl_ext.blenderkit_com'; 'bl_ext' is not a package
"""
print(f"- Setting __package__ = '{addon_module_name}'")
global __package__
__package__ = addon_module_name
if bpy.app.version < (4, 2, 0):
print(
f"- Skipping, Blender version {bpy.app.version} < (4,2,0), no need to handle repositories"
)
return
parts = addon_module_name.split(".")
if len(parts) != 3:
print("- Skipping, addon_module_name does not contain 3 parts")
return
bpy.ops.preferences.extension_repo_add(
name=parts[1], type="LOCAL"
) # Local is enough
print(f"- Local repository {parts[1]} added")
if __name__ == "__main__":
try:
# args order must match the order in blenderkit/autothumb.py:get_thumbnailer_args()!
BLENDERKIT_EXPORT_DATA = sys.argv[-3]
BLENDERKIT_EXPORT_API_KEY = sys.argv[-2]
patch_imports(sys.argv[-1])
bpy.ops.preferences.addon_enable(module=sys.argv[-1])
from . import append_link, bg_blender, bg_utils, client_lib, utils
bg_blender.progress("preparing thumbnail scene")
with open(BLENDERKIT_EXPORT_DATA, "r", encoding="utf-8") as s:
data = json.load(s)
# append_material(file_name, matname = None, link = False, fake_user = True)
thumbnail_use_gpu = data.get("thumbnail_use_gpu")
if data.get("do_download"):
# need to save the file, so that asset doesn't get downloaded into addon directory
temp_blend_path = os.path.join(data["tempdir"], "temp.blend")
# if this isn't here, blender crashes.
if bpy.app.version >= (3, 0, 0):
bpy.context.preferences.filepaths.file_preview_type = "NONE"
bpy.ops.wm.save_as_mainfile(filepath=temp_blend_path)
asset_data = data["asset_data"]
has_url, download_url, file_name = client_lib.get_download_url(
asset_data, utils.get_scene_id(), BLENDERKIT_EXPORT_API_KEY
)
asset_data["files"][0]["url"] = download_url
asset_data["files"][0]["file_name"] = file_name
if not has_url:
bg_blender.progress(
"couldn't download asset for thumbnail re-rendering"
)
exit()
# download first, or rather make sure if it's already downloaded
bg_blender.progress("downloading asset")
fpath = bg_utils.download_asset_file(
asset_data, api_key=BLENDERKIT_EXPORT_API_KEY
)
data["filepath"] = fpath
mat = append_link.append_material(
file_name=data["filepath"],
matname=data["asset_name"],
link=True,
fake_user=False,
)
s = bpy.context.scene
colmapdict = {
"BALL": "Ball",
"BALL_COMPLEX": "Ball complex",
"FLUID": "Fluid",
"CLOTH": "Cloth",
"HAIR": "Hair",
}
unhide_collection(colmapdict[data["thumbnail_type"]])
if data["thumbnail_background"]:
unhide_collection("Background")
bpy.data.materials["bg checker colorable"].node_tree.nodes[
"input_level"
].outputs["Value"].default_value = data["thumbnail_background_lightness"]
tscale = data["thumbnail_scale"]
scaler = bpy.context.view_layer.objects["scaler"]
scaler.scale = (tscale, tscale, tscale)
utils.activate(scaler)
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
bpy.context.view_layer.update()
for ob in bpy.context.visible_objects:
if ob.name[:15] == "MaterialPreview":
utils.activate(ob)
if bpy.app.version >= (3, 3, 0):
bpy.ops.object.transform_apply(
location=False, rotation=False, scale=True, isolate_users=True
)
else:
bpy.ops.object.transform_apply(
location=False, rotation=False, scale=True
)
bpy.ops.object.transform_apply(
location=False, rotation=False, scale=True
)
ob.material_slots[0].material = mat
ob.data.use_auto_texspace = False
ob.data.texspace_size.x = 1 # / tscale
ob.data.texspace_size.y = 1 # / tscale
ob.data.texspace_size.z = 1 # / tscale
# this option was moved in Blender 5.0 from cycles directly to modifier
if bpy.app.version >= (5, 0, 0):
for mod in ob.modifiers:
if mod.type == "SUBSURF":
if data["adaptive_subdivision"] == True:
mod.use_adaptive_subdivision = True
else:
mod.use_adaptive_subdivision = False
else:
if data["adaptive_subdivision"] == True:
ob.cycles.use_adaptive_subdivision = True
else:
ob.cycles.use_adaptive_subdivision = False
ts = data["texture_size_meters"]
if data["thumbnail_type"] in ["BALL", "BALL_COMPLEX", "CLOTH"]:
utils.automap(
ob.name,
tex_size=ts / tscale,
just_scale=True,
bg_exception=True,
)
bpy.context.view_layer.update()
# this option was removed in Blender 5.0
# but we have option to set biased volumes
if bpy.app.version >= (5, 0, 0):
# usually small speedup with little quality loss
s.cycles.volume_biased = True
else:
s.cycles.volume_step_size = tscale * 0.1
if thumbnail_use_gpu is True:
bpy.context.scene.cycles.device = "GPU"
compute_device_type = data.get("cycles_compute_device_type")
if compute_device_type is not None:
# DOCS:https://github.com/dfelinto/blender/blob/master/intern/cycles/blender/addon/properties.py
bpy.context.preferences.addons[
"cycles"
].preferences.compute_device_type = compute_device_type
bpy.context.preferences.addons["cycles"].preferences.refresh_devices()
s.cycles.samples = data["thumbnail_samples"]
bpy.context.view_layer.cycles.use_denoising = data["thumbnail_denoising"]
# import blender's HDR here
hdr_path = Path("datafiles/studiolights/world/interior.exr")
bpath = Path(bpy.utils.resource_path("LOCAL"))
ipath = bpath / hdr_path
ipath = str(ipath)
# this stuff is for mac and possibly linux. For blender // means relative path.
# for Mac, // means start of absolute path
if ipath.startswith("//"):
ipath = ipath[1:]
img = bpy.data.images["interior.exr"]
img.filepath = ipath
img.reload()
bpy.context.scene.render.resolution_x = int(data["thumbnail_resolution"])
bpy.context.scene.render.resolution_y = int(data["thumbnail_resolution"])
bpy.context.scene.render.filepath = data["thumbnail_path"]
bg_blender.progress("rendering thumbnail")
# bpy.ops.wm.save_as_mainfile(filepath='C:/tmp/test.blend')
# fal
render_thumbnails()
if not data.get("upload_after_render") or not data.get("asset_data"):
bg_blender.progress(
"background autothumbnailer finished successfully (no upload)"
)
sys.exit(0)
bg_blender.progress("uploading thumbnail")
ok = client_lib.complete_upload_file_blocking(
api_key=BLENDERKIT_EXPORT_API_KEY,
asset_id=data["asset_data"]["id"],
filepath=f"{data['thumbnail_path']}.png",
filetype=f"thumbnail",
fileindex=0,
)
if not ok:
bg_blender.progress("thumbnail upload failed, exiting")
sys.exit(1)
bg_blender.progress(
"background autothumbnailer finished successfully (with upload)"
)
except Exception as e:
print(f"background autothumbnailer failed: {e}")
print_exc()
sys.exit(1)