261 lines
10 KiB
Python
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)
|