work
save startup blend for animation tab & whatnot
This commit is contained in:
@@ -20,12 +20,15 @@ import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import requests
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from typing import Optional, Any
|
||||
|
||||
import bpy
|
||||
from bpy.props import ( # TODO only keep the ones actually used when cleaning
|
||||
IntProperty,
|
||||
BoolProperty,
|
||||
EnumProperty,
|
||||
StringProperty,
|
||||
@@ -49,7 +52,6 @@ from . import (
|
||||
search,
|
||||
)
|
||||
|
||||
|
||||
NAME_MINIMUM = 3
|
||||
NAME_MAXIMUM = 40
|
||||
TAGS_MINIMUM = 3
|
||||
@@ -64,6 +66,15 @@ licenses = (
|
||||
)
|
||||
|
||||
|
||||
def wire_thumbnail_upload_enabled() -> bool:
|
||||
"""Feature gate for experimental wireframe thumbnail uploads."""
|
||||
addon = bpy.context.preferences.addons.get(__package__)
|
||||
if addon is None:
|
||||
return False
|
||||
preferences = addon.preferences
|
||||
return getattr(preferences, "enable_wire_thumbnail_upload", False)
|
||||
|
||||
|
||||
def add_version(data):
|
||||
data["sourceAppName"] = "blender"
|
||||
data["sourceAppVersion"] = utils.get_blender_version()
|
||||
@@ -199,7 +210,7 @@ def check_missing_data(asset_type, props, upload_set):
|
||||
)
|
||||
|
||||
if "THUMBNAIL" in upload_set:
|
||||
if asset_type in ("MODEL", "SCENE", "MATERIAL", "PRINTABLE"):
|
||||
if asset_type in ("MODEL", "SCENE", "MATERIAL", "PRINTABLE", "BRUSH"):
|
||||
thumb_path = bpy.path.abspath(props.thumbnail)
|
||||
if props.thumbnail == "":
|
||||
write_to_report(
|
||||
@@ -213,23 +224,6 @@ def check_missing_data(asset_type, props, upload_set):
|
||||
"Thumbnail filepath does not exist on the disk.\n"
|
||||
" Please check the filepath and try again.",
|
||||
)
|
||||
|
||||
if asset_type == "BRUSH":
|
||||
brush = utils.get_active_brush()
|
||||
if brush is not None:
|
||||
thumb_path = bpy.path.abspath(brush.icon_filepath)
|
||||
if thumb_path == "":
|
||||
write_to_report(
|
||||
props,
|
||||
"Brush Icon Filepath has not been provided.\n"
|
||||
" Please check Custom Icon option add a Brush Icon in JPG or PNG format, ensuring at least 1024x1024 pixels.",
|
||||
)
|
||||
elif not os.path.exists(Path(thumb_path)):
|
||||
write_to_report(
|
||||
props,
|
||||
"Brush Icon Filepath does not exist on the disk.\n"
|
||||
" Please check the filepath and try again.",
|
||||
)
|
||||
if "PHOTO_THUMBNAIL" in upload_set: # for printable assets
|
||||
# Add validation for the photo thumbnail for printable assets
|
||||
# only if it's in the upload set
|
||||
@@ -251,6 +245,24 @@ def check_missing_data(asset_type, props, upload_set):
|
||||
" Please check the filepath and try again.",
|
||||
)
|
||||
|
||||
if wire_thumbnail_upload_enabled() and "WIRE_THUMBNAIL" in upload_set:
|
||||
if props.wire_thumbnail_will_upload_on_website:
|
||||
pass
|
||||
else:
|
||||
wire_thumb_path = bpy.path.abspath(props.wire_thumbnail)
|
||||
if props.wire_thumbnail == "":
|
||||
write_to_report(
|
||||
props,
|
||||
"A wireframe thumbnail image has not been provided.\n"
|
||||
" Please add a wireframe thumbnail in JPG or PNG format, ensuring at least 1024x1024 pixels.",
|
||||
)
|
||||
elif not os.path.exists(Path(wire_thumb_path)):
|
||||
write_to_report(
|
||||
props,
|
||||
"Wireframe thumbnail filepath does not exist on the disk.\n"
|
||||
" Please check the filepath and try again.",
|
||||
)
|
||||
|
||||
if props.is_private == "PUBLIC":
|
||||
check_public_requirements(props)
|
||||
|
||||
@@ -333,7 +345,7 @@ def sub_to_camel(content):
|
||||
|
||||
def get_upload_data(caller=None, context=None, asset_type=None):
|
||||
"""
|
||||
works though metadata from addom props and prepares it for upload to dicts.
|
||||
works though metadata from addon props and prepares it for upload to dicts.
|
||||
Parameters
|
||||
----------
|
||||
caller - upload operator or none
|
||||
@@ -342,8 +354,8 @@ def get_upload_data(caller=None, context=None, asset_type=None):
|
||||
|
||||
Returns
|
||||
-------
|
||||
export_ddta- all extra data that the process needs to upload and communicate with UI from a thread.
|
||||
- eval_path_computing - string path to UI prop that denots if upload is still running
|
||||
export_data- all extra data that the process needs to upload and communicate with UI from a thread.
|
||||
- eval_path_computing - string path to UI prop that denotes if upload is still running
|
||||
- eval_path_state - string path to UI prop that delivers messages about upload to ui
|
||||
- eval_path - path to object holding upload data to be able to access it with various further commands
|
||||
- models - in case of model upload, list of objects
|
||||
@@ -353,10 +365,13 @@ def get_upload_data(caller=None, context=None, asset_type=None):
|
||||
|
||||
"""
|
||||
user_preferences = bpy.context.preferences.addons[__package__].preferences
|
||||
export_data = {
|
||||
export_data: dict[str, Any] = {
|
||||
# "type": asset_type,
|
||||
}
|
||||
upload_params = {}
|
||||
upload_params: dict[str, Any] = {}
|
||||
# initialize here to prevent unbound
|
||||
upload_data: dict[str, Any] = {}
|
||||
|
||||
if asset_type in ("MODEL", "PRINTABLE"):
|
||||
# Prepare to save the file
|
||||
mainmodel = utils.get_active_model()
|
||||
@@ -375,6 +390,13 @@ def get_upload_data(caller=None, context=None, asset_type=None):
|
||||
export_data["photo_thumbnail_path"] = bpy.path.abspath(
|
||||
props.photo_thumbnail
|
||||
)
|
||||
# Add wire thumbnail path to export_data for models and printable assets
|
||||
if (
|
||||
wire_thumbnail_upload_enabled()
|
||||
and asset_type in ("MODEL", "SCENE", "PRINTABLE")
|
||||
and props.wire_thumbnail
|
||||
):
|
||||
export_data["wire_thumbnail_path"] = bpy.path.abspath(props.wire_thumbnail)
|
||||
|
||||
eval_path_computing = (
|
||||
"bpy.data.objects['%s'].blenderkit.uploading" % mainmodel.name
|
||||
@@ -511,9 +533,9 @@ def get_upload_data(caller=None, context=None, asset_type=None):
|
||||
"animated": props.animated,
|
||||
# "simulation": props.simulation,
|
||||
"purePbr": props.pbr,
|
||||
"faceCount": 1, # props.face_count,
|
||||
"faceCountRender": 1, # props.face_count_render,
|
||||
"objectCount": 1, # props.object_count,
|
||||
"faceCount": max(0, props.face_count),
|
||||
"faceCountRender": max(0, props.face_count_render),
|
||||
"objectCount": max(0, props.object_count),
|
||||
# "scene": props.is_scene,
|
||||
}
|
||||
if props.use_design_year:
|
||||
@@ -588,7 +610,7 @@ def get_upload_data(caller=None, context=None, asset_type=None):
|
||||
# props.name = brush.name
|
||||
|
||||
export_data["brush"] = str(brush.name)
|
||||
export_data["thumbnail_path"] = bpy.path.abspath(brush.icon_filepath)
|
||||
export_data["thumbnail_path"] = bpy.path.abspath(props.thumbnail)
|
||||
|
||||
eval_path_computing = "bpy.data.brushes['%s'].blenderkit.uploading" % brush.name
|
||||
eval_path_state = "bpy.data.brushes['%s'].blenderkit.upload_state" % brush.name
|
||||
@@ -749,7 +771,7 @@ def update_free_full(self, context):
|
||||
message="Any material uploaded to BlenderKit is free."
|
||||
" However, it can still earn money for the author,"
|
||||
" based on our fair share system. "
|
||||
"Part of subscription is sent to artists based on usage by paying users.",
|
||||
"Part of subscription is sent to authors based on usage by paying users.",
|
||||
)
|
||||
|
||||
|
||||
@@ -883,6 +905,38 @@ class FastMetadata(bpy.types.Operator):
|
||||
update=update_free_full,
|
||||
)
|
||||
|
||||
# Design metadata
|
||||
manufacturer: StringProperty( # type: ignore[valid-type]
|
||||
name="Manufacturer",
|
||||
description="Manufacturer, company making a design piece or product.",
|
||||
default="",
|
||||
)
|
||||
designer: StringProperty( # type: ignore[valid-type]
|
||||
name="Designer",
|
||||
description="Author of the original design piece depicted.",
|
||||
default="",
|
||||
)
|
||||
design_collection: StringProperty( # type: ignore[valid-type]
|
||||
name="Design Collection",
|
||||
description="Name of the collection this design belongs to.",
|
||||
default="",
|
||||
)
|
||||
design_variant: StringProperty( # type: ignore[valid-type]
|
||||
name="Design Variant",
|
||||
description="Colour or material variant of the product.",
|
||||
default="",
|
||||
)
|
||||
use_design_year: BoolProperty( # type: ignore[valid-type]
|
||||
name="Use Design Year",
|
||||
description="Whether to include the design year in the metadata. If enabled, the design year will be included as a parameter in the asset metadata.",
|
||||
default=False,
|
||||
)
|
||||
design_year: IntProperty( # type: ignore[valid-type]
|
||||
name="Design Year",
|
||||
description="When this item was designed.",
|
||||
default=1960,
|
||||
)
|
||||
|
||||
####################
|
||||
|
||||
@classmethod
|
||||
@@ -905,6 +959,13 @@ class FastMetadata(bpy.types.Operator):
|
||||
layout.prop(self, "free_full", expand=True)
|
||||
if self.is_private == "PUBLIC":
|
||||
layout.prop(self, "license")
|
||||
layout.prop(self, "manufacturer")
|
||||
layout.prop(self, "designer")
|
||||
layout.prop(self, "design_collection")
|
||||
layout.prop(self, "design_variant")
|
||||
layout.prop(self, "use_design_year")
|
||||
if self.use_design_year:
|
||||
layout.prop(self, "design_year")
|
||||
# layout.label(text="Content Flags:")
|
||||
content_flag_box = layout.box()
|
||||
content_flag_box.alignment = "EXPAND"
|
||||
@@ -934,9 +995,38 @@ class FastMetadata(bpy.types.Operator):
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
# Optional design-related parameters
|
||||
extra_parameters = []
|
||||
if self.designer:
|
||||
extra_parameters.append(
|
||||
{"parameterType": "designer", "value": self.designer}
|
||||
)
|
||||
if self.manufacturer:
|
||||
extra_parameters.append(
|
||||
{"parameterType": "manufacturer", "value": self.manufacturer}
|
||||
)
|
||||
if self.design_collection:
|
||||
extra_parameters.append(
|
||||
{
|
||||
"parameterType": "designCollection",
|
||||
"value": self.design_collection,
|
||||
}
|
||||
)
|
||||
if self.design_variant:
|
||||
extra_parameters.append(
|
||||
{"parameterType": "designVariant", "value": self.design_variant}
|
||||
)
|
||||
if self.use_design_year:
|
||||
extra_parameters.append(
|
||||
{"parameterType": "designYear", "value": self.design_year}
|
||||
)
|
||||
|
||||
if extra_parameters:
|
||||
metadata["parameters"].extend(extra_parameters)
|
||||
url = f"{paths.BLENDERKIT_API}/assets/{self.asset_id}/"
|
||||
messages = {
|
||||
"success": "Metadata upload succeded",
|
||||
"success": "Metadata upload succeeded",
|
||||
"error": "Metadata upload failed",
|
||||
}
|
||||
client_lib.nonblocking_request(url, "PATCH", {}, metadata, messages)
|
||||
@@ -984,6 +1074,13 @@ class FastMetadata(bpy.types.Operator):
|
||||
"sexualizedContent", False
|
||||
)
|
||||
|
||||
params = asset_data.get("dictParameters", {})
|
||||
self.designer = params.get("designer", "")
|
||||
self.manufacturer = params.get("manufacturer", "")
|
||||
self.design_collection = params.get("designCollection", "")
|
||||
self.design_variant = params.get("designVariant", "")
|
||||
self.design_year = params.get("designYear", 1960)
|
||||
|
||||
wm = context.window_manager
|
||||
|
||||
return wm.invoke_props_dialog(self, width=600)
|
||||
@@ -991,7 +1088,7 @@ class FastMetadata(bpy.types.Operator):
|
||||
|
||||
def get_upload_location(props):
|
||||
"""
|
||||
not used by now, gets location of uploaded asset - potentially usefull if we draw a nice upload gizmo in viewport.
|
||||
not used by now, gets location of uploaded asset - potentially useful if we draw a nice upload gizmo in viewport.
|
||||
Parameters
|
||||
----------
|
||||
props
|
||||
@@ -1037,6 +1134,179 @@ def storage_quota_available(props) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def _get_upload_datablock(asset_type: str):
|
||||
if bpy.app.version < (3, 0, 0):
|
||||
return None
|
||||
if asset_type in ("MODEL", "PRINTABLE"):
|
||||
return utils.get_active_model()
|
||||
if asset_type == "SCENE":
|
||||
return bpy.context.scene
|
||||
if asset_type == "MATERIAL":
|
||||
obj = bpy.context.active_object
|
||||
if obj is not None:
|
||||
return obj.active_material
|
||||
return None
|
||||
if asset_type == "BRUSH":
|
||||
return utils.get_active_brush()
|
||||
if asset_type == "NODEGROUP":
|
||||
return bpy.context.window_manager.blenderkitUI.nodegroup_upload
|
||||
return None
|
||||
|
||||
|
||||
def ensure_asset_metadata_on_datablock(asset_type: str, props) -> None:
|
||||
"""Write tags/description/author into the datablock before we save for upload."""
|
||||
|
||||
data_block = _get_upload_datablock(asset_type)
|
||||
if data_block is None:
|
||||
return
|
||||
|
||||
if getattr(data_block, "asset_data", None) is None:
|
||||
mark_fn = getattr(data_block, "asset_mark", None)
|
||||
if callable(mark_fn):
|
||||
mark_fn()
|
||||
|
||||
asset_meta = getattr(data_block, "asset_data", None)
|
||||
if asset_meta is None:
|
||||
return
|
||||
|
||||
try:
|
||||
tags_prop = asset_meta.tags
|
||||
for tag in list(tags_prop):
|
||||
tags_prop.remove(tag)
|
||||
for tag in utils.string2list(props.tags):
|
||||
tags_prop.new(str(tag))
|
||||
|
||||
profile = global_vars.BKIT_PROFILE
|
||||
author_name = getattr(profile, "fullName", "") or getattr(
|
||||
profile, "username", ""
|
||||
)
|
||||
asset_meta.author = author_name
|
||||
asset_meta.description = props.description
|
||||
|
||||
# inject also additional metadata
|
||||
other_meta = {}
|
||||
|
||||
if props.id:
|
||||
other_meta["id"] = props.asset_base_id
|
||||
|
||||
# further custom meta from dictParameters
|
||||
if props.condition:
|
||||
other_meta["condition"] = props.condition
|
||||
if props.pbr_type:
|
||||
other_meta["pbr_type"] = props.pbr_type
|
||||
if props.style:
|
||||
other_meta["style"] = props.style
|
||||
if props.engine:
|
||||
other_meta["engine"] = props.engine
|
||||
if props.animated:
|
||||
other_meta["animated"] = "yes"
|
||||
if props.simulation:
|
||||
other_meta["simulation"] = "yes"
|
||||
|
||||
# ad additional metadata to tags
|
||||
for key, value in other_meta.items():
|
||||
tags_prop.new(f"{key}:{value}")
|
||||
|
||||
except Exception as e: # pragma: no cover - defensive for asset_data API quirks
|
||||
bk_logger.warning("Failed to write asset metadata before upload: %s", e)
|
||||
|
||||
|
||||
def _sanitize_preview_image(preview_path: str) -> str:
|
||||
"""Some thumbnail images have issues libEx support.
|
||||
|
||||
This function tries to sanitize the image by re-saving it as PNG from the blender.
|
||||
"""
|
||||
if not preview_path or not os.path.exists(preview_path):
|
||||
return ""
|
||||
base_dir = os.path.dirname(preview_path)
|
||||
base_name = os.path.splitext(os.path.basename(preview_path))[0]
|
||||
sanitized_path = os.path.join(base_dir, f"{base_name}_clean.png")
|
||||
if os.path.exists(sanitized_path):
|
||||
return sanitized_path
|
||||
img = None
|
||||
try:
|
||||
img = bpy.data.images.load(preview_path, check_existing=False)
|
||||
img.filepath_raw = sanitized_path
|
||||
img.file_format = "PNG"
|
||||
img.save()
|
||||
return sanitized_path
|
||||
except Exception:
|
||||
return ""
|
||||
finally:
|
||||
if img is not None:
|
||||
try:
|
||||
bpy.data.images.remove(img)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def _op_poll(op_callable, data_block) -> bool:
|
||||
"""Check if the operator can run in the context of the given data block."""
|
||||
try:
|
||||
if hasattr(bpy.context, "temp_override"):
|
||||
with bpy.context.temp_override(id=data_block):
|
||||
return op_callable.poll()
|
||||
override = bpy.context.copy()
|
||||
override["id"] = data_block
|
||||
return op_callable.poll(override)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _op_call(op_callable, data_block, **kwargs):
|
||||
"""Call the operator in the context of the given data block."""
|
||||
if hasattr(bpy.context, "temp_override"):
|
||||
with bpy.context.temp_override(id=data_block):
|
||||
return op_callable(**kwargs)
|
||||
override = bpy.context.copy()
|
||||
override["id"] = data_block
|
||||
return op_callable(override, **kwargs)
|
||||
|
||||
|
||||
def apply_asset_preview(data_block, props) -> None:
|
||||
"""Apply asset preview image to the asset data block.
|
||||
|
||||
It first tries to download the thumbnail from the URL provided in asset data.
|
||||
If that fails, it falls back to generating a preview within Blender."""
|
||||
if data_block is None:
|
||||
return
|
||||
thumbnail = getattr(props, "thumbnail", "")
|
||||
if not thumbnail:
|
||||
return
|
||||
thmb_path = bpy.path.abspath(thumbnail)
|
||||
if not os.path.exists(thmb_path):
|
||||
return
|
||||
if thmb_path:
|
||||
clean_path = _sanitize_preview_image(thmb_path)
|
||||
if clean_path:
|
||||
thmb_path = clean_path
|
||||
try:
|
||||
loaded = False
|
||||
if _op_poll(bpy.ops.ed.lib_id_load_custom_preview, data_block):
|
||||
result = _op_call(
|
||||
bpy.ops.ed.lib_id_load_custom_preview,
|
||||
data_block,
|
||||
filepath=thmb_path,
|
||||
)
|
||||
loaded = "FINISHED" in result
|
||||
if loaded:
|
||||
bk_logger.info("Thumbnail preview applied successfully.")
|
||||
return
|
||||
except Exception as e:
|
||||
bk_logger.warning(
|
||||
"Failed to load thumbnail preview, falling back to generating preview: "
|
||||
f"{e}"
|
||||
)
|
||||
|
||||
try:
|
||||
if _op_poll(bpy.ops.ed.lib_id_generate_preview, data_block):
|
||||
_op_call(bpy.ops.ed.lib_id_generate_preview, data_block)
|
||||
bk_logger.info("Generated preview applied successfully.")
|
||||
except Exception:
|
||||
bk_logger.warning("Failed to generate preview, asset will have no preview")
|
||||
return
|
||||
|
||||
|
||||
def auto_fix(asset_type=""):
|
||||
# this applies various procedures to ensure coherency in the database.
|
||||
asset = utils.get_active_asset()
|
||||
@@ -1067,6 +1337,9 @@ def prepare_asset_data(self, context, asset_type, reupload, upload_set):
|
||||
if props.report != "":
|
||||
return False, None, None
|
||||
|
||||
ensure_asset_metadata_on_datablock(asset_type, props)
|
||||
apply_asset_preview(_get_upload_datablock(asset_type), props)
|
||||
|
||||
if not reupload:
|
||||
props.asset_base_id = ""
|
||||
props.id = ""
|
||||
@@ -1097,6 +1370,13 @@ def prepare_asset_data(self, context, asset_type, reupload, upload_set):
|
||||
props.uploading = False
|
||||
return False, None, None
|
||||
|
||||
# check if we have wire_thumbnail
|
||||
if wire_thumbnail_upload_enabled() and "wire_thumbnail" in upload_set:
|
||||
if not os.path.exists(export_data.get("wire_thumbnail_path", "")):
|
||||
props.upload_state = "0% - wire thumbnail not found"
|
||||
props.uploading = False
|
||||
return False, None, None
|
||||
|
||||
# save a copy of the file for processing. Only for blend files
|
||||
_, ext = os.path.splitext(bpy.data.filepath)
|
||||
if not ext:
|
||||
@@ -1164,8 +1444,17 @@ class UploadOperator(Operator):
|
||||
# Add new property for photo thumbnail
|
||||
photo_thumbnail: BoolProperty(name="photo thumbnail", default=False, options={"SKIP_SAVE"}) # type: ignore[valid-type]
|
||||
|
||||
# Add new property for wire thumbnail
|
||||
wire_thumbnail: BoolProperty(name="wire thumbnail", default=False, options={"SKIP_SAVE"}) # type: ignore[valid-type]
|
||||
|
||||
main_file: BoolProperty(name="main file", default=False, options={"SKIP_SAVE"}) # type: ignore[valid-type]
|
||||
|
||||
skip_hdr_tune_popup: BoolProperty( # type: ignore[valid-type]
|
||||
name="Skip HDR tune popup",
|
||||
default=False,
|
||||
options={"SKIP_SAVE", "HIDDEN"},
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return utils.uploadable_asset_poll()
|
||||
@@ -1173,6 +1462,7 @@ class UploadOperator(Operator):
|
||||
def execute(self, context):
|
||||
bpy.ops.object.blenderkit_auto_tags()
|
||||
props = utils.get_upload_props()
|
||||
wire_upload_enabled = wire_thumbnail_upload_enabled()
|
||||
|
||||
upload_set = []
|
||||
if not self.reupload:
|
||||
@@ -1180,6 +1470,14 @@ class UploadOperator(Operator):
|
||||
# Add photo_thumbnail to the upload set for printable assets
|
||||
if self.asset_type == "PRINTABLE" and props.photo_thumbnail:
|
||||
upload_set.append("photo_thumbnail")
|
||||
|
||||
# add wire_thumbnail for models if it exists
|
||||
if (
|
||||
wire_upload_enabled
|
||||
and self.asset_type in {"MODEL", "SCENE", "PRINTABLE"}
|
||||
and props.wire_thumbnail
|
||||
):
|
||||
upload_set.append("wire_thumbnail")
|
||||
else:
|
||||
if self.metadata:
|
||||
upload_set.append("METADATA")
|
||||
@@ -1187,6 +1485,8 @@ class UploadOperator(Operator):
|
||||
upload_set.append("THUMBNAIL")
|
||||
if self.photo_thumbnail:
|
||||
upload_set.append("photo_thumbnail")
|
||||
if wire_upload_enabled and self.wire_thumbnail:
|
||||
upload_set.append("wire_thumbnail")
|
||||
if self.main_file:
|
||||
upload_set.append("MAINFILE")
|
||||
|
||||
@@ -1207,6 +1507,7 @@ class UploadOperator(Operator):
|
||||
props.uploading = True
|
||||
|
||||
client_lib.asset_upload(upload_data, export_data, upload_set)
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
def draw(self, context):
|
||||
@@ -1227,6 +1528,14 @@ class UploadOperator(Operator):
|
||||
if self.asset_type == "PRINTABLE":
|
||||
layout.prop(self, "photo_thumbnail")
|
||||
|
||||
# Show wire_thumbnail option for models, scenes, and printable assets
|
||||
if wire_thumbnail_upload_enabled() and self.asset_type in {
|
||||
"MODEL",
|
||||
"SCENE",
|
||||
"PRINTABLE",
|
||||
}:
|
||||
layout.prop(self, "wire_thumbnail")
|
||||
|
||||
if props.asset_base_id != "" and not self.reupload:
|
||||
utils.label_multiline(
|
||||
layout,
|
||||
@@ -1290,7 +1599,7 @@ class UploadOperator(Operator):
|
||||
utils.label_multiline(
|
||||
layout,
|
||||
width=500,
|
||||
text="Would you like tu upload your asset to BlenderKit?",
|
||||
text="Would you like to upload your asset to BlenderKit?",
|
||||
)
|
||||
|
||||
def invoke(self, context, event):
|
||||
@@ -1300,6 +1609,20 @@ class UploadOperator(Operator):
|
||||
)
|
||||
return {"CANCELLED"}
|
||||
|
||||
ui_props = bpy.context.window_manager.blenderkitUI
|
||||
|
||||
if (
|
||||
self.asset_type == "HDR"
|
||||
and ui_props.hdr_use_custom_thumbnail_tone
|
||||
and not self.skip_hdr_tune_popup
|
||||
):
|
||||
bpy.ops.wm.blenderkit_hdr_thumbnail_tune(
|
||||
"INVOKE_DEFAULT",
|
||||
trigger_upload=True,
|
||||
upload_reupload=self.reupload,
|
||||
)
|
||||
return {"CANCELLED"}
|
||||
|
||||
if self.asset_type == "HDR":
|
||||
# getting upload data for images ensures true_hdr check so users can be informed about their handling
|
||||
# simple 360 photos or renders with LDR are hidden by default..
|
||||
@@ -1425,7 +1748,7 @@ def handle_asset_upload(task: client_tasks.Task):
|
||||
task.message, type="ERROR", details=task.message_detailed
|
||||
)
|
||||
|
||||
# crazy shit to parse stupid Django incosistent error messages
|
||||
# crazy shit to parse stupid Django inconsistent error messages
|
||||
if "detail" in task.result:
|
||||
if type(task.result["detail"]) == dict:
|
||||
for key in task.result["detail"]:
|
||||
@@ -1458,7 +1781,7 @@ def handle_asset_upload(task: client_tasks.Task):
|
||||
|
||||
if task.status == "finished":
|
||||
asset.uploading = False
|
||||
return reports.add_report("Upload successfull")
|
||||
return reports.add_report("Upload successful")
|
||||
|
||||
|
||||
def handle_asset_metadata_upload(task: client_tasks.Task):
|
||||
@@ -1469,20 +1792,20 @@ def handle_asset_metadata_upload(task: client_tasks.Task):
|
||||
new_asset_base_id = task.result.get("assetBaseId", "")
|
||||
if new_asset_base_id != "":
|
||||
asset.asset_base_id = new_asset_base_id
|
||||
bk_logger.info(f"Assigned new asset.asset_base_id: {new_asset_base_id}")
|
||||
bk_logger.info("Assigned new asset.asset_base_id: %s", new_asset_base_id)
|
||||
else:
|
||||
asset.asset_base_id = task.data["export_data"]["assetBaseId"]
|
||||
bk_logger.info(f"Assigned original asset.asset_base_id: {asset.asset_base_id}")
|
||||
bk_logger.info("Assigned original asset.asset_base_id: %s", asset.asset_base_id)
|
||||
|
||||
new_asset_id = task.result.get("id", "")
|
||||
if new_asset_id != "":
|
||||
asset.id = new_asset_id
|
||||
bk_logger.info(f"Assigned new asset.id: {new_asset_id}")
|
||||
bk_logger.info("Assigned new asset.id: %s", new_asset_id)
|
||||
else:
|
||||
asset.id = task.data["export_data"]["id"]
|
||||
bk_logger.info(f"Assigned original asset.id: {asset.id}")
|
||||
bk_logger.info("Assigned original asset.id: %s", asset.id)
|
||||
|
||||
return reports.add_report("Metadata upload successfull")
|
||||
return reports.add_report("Metadata upload successful")
|
||||
|
||||
|
||||
def patch_individual_parameter(asset_id="", param_name="", param_value="", api_key=""):
|
||||
@@ -1593,7 +1916,7 @@ def mark_for_thumbnail(
|
||||
asset_id, "markThumbnailRender", json_data, api_key
|
||||
)
|
||||
except Exception as e:
|
||||
bk_logger.error(f"Failed to mark asset for thumbnail regeneration: {e}")
|
||||
bk_logger.error("Failed to mark asset for thumbnail regeneration: %s", e)
|
||||
return False
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user