work
save startup blend for animation tab & whatnot
This commit is contained in:
@@ -16,16 +16,16 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import addon_utils
|
||||
import copy
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import time
|
||||
import urllib.request
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from . import (
|
||||
append_link,
|
||||
@@ -56,6 +56,12 @@ from bpy.props import (
|
||||
|
||||
bk_logger = logging.getLogger(__name__)
|
||||
|
||||
STALE_DOWNLOAD_TIMEOUT = (
|
||||
20.0 # seconds without progress before we treat a download as stalled
|
||||
)
|
||||
|
||||
download_tasks = {}
|
||||
|
||||
|
||||
def get_blenderkit_repository():
|
||||
"""Find the BlenderKit extensions repository index.
|
||||
@@ -123,7 +129,7 @@ def get_addon_installation_status(asset_data):
|
||||
) and addon_module.startswith("bl_ext."):
|
||||
is_enabled = True
|
||||
bk_logger.info(
|
||||
f"Found enabled addon with extension format: {addon_module}"
|
||||
"Found enabled addon with extension format: %s", addon_module
|
||||
)
|
||||
break
|
||||
|
||||
@@ -141,11 +147,12 @@ def get_addon_installation_status(asset_data):
|
||||
) and addon_module.__name__.startswith("bl_ext."):
|
||||
is_installed = True
|
||||
bk_logger.info(
|
||||
f"Found installed addon with extension format: {addon_module.__name__}"
|
||||
"Found installed addon with extension format: %s",
|
||||
addon_module.__name__,
|
||||
)
|
||||
break
|
||||
except Exception as e:
|
||||
bk_logger.warning(f"Error checking addon_utils.modules(): {e}")
|
||||
bk_logger.warning("Error checking addon_utils.modules(): %s", e)
|
||||
|
||||
# If found through addon_utils, we know it's installed
|
||||
# But we need to double-check enabled status using the correct module name
|
||||
@@ -160,10 +167,10 @@ def get_addon_installation_status(asset_data):
|
||||
# Check if this specific module name is enabled
|
||||
is_enabled = addon_module.__name__ in enabled_addons
|
||||
if is_enabled:
|
||||
bk_logger.info(f"Found enabled addon: {addon_module.__name__}")
|
||||
bk_logger.info("Found enabled addon: %s", addon_module.__name__)
|
||||
break
|
||||
except Exception as e:
|
||||
bk_logger.warning(f"Error double-checking enabled status: {e}")
|
||||
bk_logger.warning("Error double-checking enabled status: %s", e)
|
||||
|
||||
# Method 3: If not found through traditional addon system, check extensions system
|
||||
if not is_installed:
|
||||
@@ -173,7 +180,7 @@ def get_addon_installation_status(asset_data):
|
||||
"blenderkit_extensions_repo_cache", {}
|
||||
)
|
||||
|
||||
for cache_key, pkg_data in bk_ext_cache.items():
|
||||
for _cache_key, pkg_data in bk_ext_cache.items():
|
||||
if isinstance(pkg_data, dict) and pkg_data.get("id") == extension_id:
|
||||
# Check if it's actually installed in the extension system
|
||||
is_installed = pkg_data.get("installed", False)
|
||||
@@ -182,12 +189,11 @@ def get_addon_installation_status(asset_data):
|
||||
is_enabled = pkg_data.get("enabled", False)
|
||||
break
|
||||
except Exception as e:
|
||||
bk_logger.warning(f"Error checking extension cache: {e}")
|
||||
bk_logger.warning("Error checking extension cache: %s", e)
|
||||
|
||||
# Method 4: Check through Blender's extension repositories directly
|
||||
if not is_installed:
|
||||
try:
|
||||
|
||||
# Look for BlenderKit repository and check its packages
|
||||
for repo in bpy.context.preferences.extensions.repos:
|
||||
if not repo.enabled:
|
||||
@@ -203,7 +209,7 @@ def get_addon_installation_status(asset_data):
|
||||
# For now, we'll rely on the previous methods
|
||||
break
|
||||
except Exception as e:
|
||||
bk_logger.warning(f"Error checking extension repositories: {e}")
|
||||
bk_logger.warning("Error checking extension repositories: %s", e)
|
||||
|
||||
# Debug: Show some enabled addons for reference
|
||||
blenderkit_addons = [
|
||||
@@ -252,7 +258,7 @@ def install_addon_from_local_file(asset_data, file_path, enable_on_install=True)
|
||||
reports.add_report(error_msg, type="ERROR")
|
||||
raise Exception(error_msg)
|
||||
|
||||
bk_logger.info(f"Installing addon '{addon_name}' from local file: {file_path}")
|
||||
bk_logger.info("Installing addon '%s' from local file: %s", addon_name, file_path)
|
||||
|
||||
status = get_addon_installation_status(asset_data)
|
||||
if status["installed"]:
|
||||
@@ -288,7 +294,19 @@ def install_addon_from_local_file(asset_data, file_path, enable_on_install=True)
|
||||
)
|
||||
|
||||
|
||||
download_tasks = {}
|
||||
def _reset_progress_for_asset_ids(asset_ids):
|
||||
"""Reset UI progress bars for the given asset ids."""
|
||||
if not asset_ids:
|
||||
return
|
||||
|
||||
search_results = search.get_search_results()
|
||||
if search_results is None:
|
||||
return
|
||||
|
||||
for result in search_results:
|
||||
if result.get("id") in asset_ids:
|
||||
result["downloaded"] = 0
|
||||
|
||||
|
||||
INT32_MIN = -2_147_483_648
|
||||
INT32_MAX = 2_147_483_647
|
||||
@@ -348,7 +366,7 @@ def check_unused():
|
||||
|
||||
for l in bpy.data.libraries:
|
||||
if l not in used_libs and l.getn("asset_data"):
|
||||
bk_logger.info(f"attempt to remove this library: {l.filepath}")
|
||||
bk_logger.info("attempt to remove this library: %s", l.filepath)
|
||||
# have to unlink all groups, since the file is a 'user' even if the groups aren't used at all...
|
||||
for user_id in l.users_id:
|
||||
if type(user_id) == bpy.types.Collection:
|
||||
@@ -364,7 +382,7 @@ def get_temp_enabled_addons():
|
||||
temp_addons_json = prefs.temp_enabled_addons
|
||||
return json.loads(temp_addons_json)
|
||||
except Exception as e:
|
||||
bk_logger.warning(f"Error reading temporary addons from preferences: {e}")
|
||||
bk_logger.warning("Error reading temporary addons from preferences: %s", e)
|
||||
return []
|
||||
|
||||
|
||||
@@ -374,9 +392,9 @@ def set_temp_enabled_addons(addon_list):
|
||||
try:
|
||||
prefs = bpy.context.preferences.addons[__package__].preferences
|
||||
prefs.temp_enabled_addons = json.dumps(addon_list)
|
||||
bk_logger.info(f"Saved {len(addon_list)} temporary addons to preferences")
|
||||
bk_logger.info("Saved %d temporary addons to preferences", len(addon_list))
|
||||
except Exception as e:
|
||||
bk_logger.error(f"Error saving temporary addons to preferences: {e}")
|
||||
bk_logger.error("Error saving temporary addons to preferences: %s", e)
|
||||
|
||||
|
||||
def add_temp_enabled_addon(pkg_id):
|
||||
@@ -385,7 +403,7 @@ def add_temp_enabled_addon(pkg_id):
|
||||
if pkg_id not in temp_enabled:
|
||||
temp_enabled.append(pkg_id)
|
||||
set_temp_enabled_addons(temp_enabled)
|
||||
bk_logger.info(f"Added {pkg_id} to temporary addons list")
|
||||
bk_logger.info("Added %s to temporary addons list", pkg_id)
|
||||
|
||||
|
||||
def cleanup_temp_enabled_addons():
|
||||
@@ -398,24 +416,24 @@ def cleanup_temp_enabled_addons():
|
||||
bk_logger.info("No temporarily enabled addons to clean up")
|
||||
return
|
||||
|
||||
bk_logger.info(f"Cleaning up {len(temp_enabled)} temporarily enabled addons")
|
||||
bk_logger.info("Cleaning up %d temporarily enabled addons", len(temp_enabled))
|
||||
|
||||
# Disable all temporarily enabled addons using preferences API
|
||||
for pkg_id in temp_enabled:
|
||||
try:
|
||||
full_module_name = f"bl_ext.www_blenderkit_com.{pkg_id}"
|
||||
bpy.ops.preferences.addon_disable(module=full_module_name)
|
||||
bk_logger.info(f"Disabled temporarily enabled addon: {pkg_id}")
|
||||
bk_logger.info("Disabled temporarily enabled addon: %s", pkg_id)
|
||||
except Exception as e:
|
||||
bk_logger.warning(
|
||||
f"Failed to disable temporarily enabled addon {pkg_id}: {e}"
|
||||
"Failed to disable temporarily enabled addon %s: %s", pkg_id, e
|
||||
)
|
||||
|
||||
# Clear the list in preferences
|
||||
set_temp_enabled_addons([])
|
||||
bk_logger.info("Temporary addon cleanup completed")
|
||||
except Exception as e:
|
||||
bk_logger.error(f"Error during temporary addon cleanup: {e}")
|
||||
bk_logger.error("Error during temporary addon cleanup: %s", e)
|
||||
|
||||
|
||||
@persistent
|
||||
@@ -466,7 +484,7 @@ def refresh_addon_search_results_status():
|
||||
asset_data["enabled"] = False
|
||||
|
||||
except Exception as e:
|
||||
bk_logger.warning(f"Error refreshing addon search results status: {e}")
|
||||
bk_logger.warning("Error refreshing addon search results status: %s", e)
|
||||
|
||||
|
||||
@persistent
|
||||
@@ -617,7 +635,7 @@ def _sanitize_for_idprops(value):
|
||||
return value
|
||||
|
||||
|
||||
def udpate_asset_data_in_dicts(asset_data):
|
||||
def update_asset_data_in_dicts(asset_data):
|
||||
"""
|
||||
updates asset data in all relevant dictionaries, after a threaded download task \
|
||||
- where the urls were retrieved, and now they can be reused
|
||||
@@ -705,6 +723,8 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
|
||||
user_preferences = bpy.context.preferences.addons[__package__].preferences
|
||||
user_preferences.download_counter += 1
|
||||
|
||||
asset_main = None
|
||||
|
||||
if asset_data["assetType"] == "scene":
|
||||
sprops = wm.blenderkit_scene
|
||||
|
||||
@@ -758,7 +778,7 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
|
||||
# also, if it was successful, no other operations are needed , basically all asset data is already ready from the original asset
|
||||
if new_obs:
|
||||
# update here assets rated/used because there might be new download urls?
|
||||
udpate_asset_data_in_dicts(asset_data)
|
||||
update_asset_data_in_dicts(asset_data)
|
||||
bpy.ops.ed.undo_push(
|
||||
"INVOKE_REGION_WIN",
|
||||
message="add %s to scene" % asset_data["name"],
|
||||
@@ -772,7 +792,7 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
|
||||
if downloaders:
|
||||
for downloader in downloaders:
|
||||
# this cares for adding particle systems directly to target mesh, but I had to block it now,
|
||||
# because of the sluggishnes of it. Possibly re-enable when it's possible to do this faster?
|
||||
# because of the sluggishness of it. Possibly re-enable when it's possible to do this faster?
|
||||
if (
|
||||
"particle_plants" in asset_data["tags"]
|
||||
and kwargs["target_object"] != ""
|
||||
@@ -854,6 +874,7 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
|
||||
lib["asset_data"] = asset_data
|
||||
|
||||
elif asset_data["assetType"] == "brush":
|
||||
brush = None
|
||||
inscene = False
|
||||
for b in bpy.data.brushes:
|
||||
if b.blenderkit.id == asset_data["id"]:
|
||||
@@ -910,9 +931,11 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
|
||||
)
|
||||
# TODO add grease pencil brushes!
|
||||
# bpy.context.tool_settings.image_paint.brush = brush
|
||||
asset_main = brush
|
||||
if brush is not None:
|
||||
asset_main = brush
|
||||
|
||||
elif asset_data["assetType"] == "material":
|
||||
material = None
|
||||
inscene = False
|
||||
sprops = wm.blenderkit_mat
|
||||
|
||||
@@ -927,12 +950,14 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
|
||||
file_names[-1], matname=asset_data["name"], link=link, fake_user=False
|
||||
)
|
||||
|
||||
target_object = bpy.data.objects[kwargs["target_object"]]
|
||||
assign_material(target_object, material, kwargs["material_target_slot"])
|
||||
if material is not None:
|
||||
target_object = bpy.data.objects[kwargs["target_object"]]
|
||||
assign_material(target_object, material, kwargs["material_target_slot"])
|
||||
|
||||
asset_main = material
|
||||
asset_main = material
|
||||
|
||||
elif asset_data["assetType"] == "nodegroup":
|
||||
nodegroup = None
|
||||
inscene = False
|
||||
sprops = wm.blenderkit_nodegroup
|
||||
for g in bpy.data.node_groups:
|
||||
@@ -979,11 +1004,12 @@ def append_asset(asset_data, **kwargs): # downloaders=[], location=None,
|
||||
model_location=kwargs.get("model_location", (0, 0, 0)),
|
||||
model_rotation=kwargs.get("model_rotation", (0, 0, 0)),
|
||||
)
|
||||
bk_logger.info(f"appended nodegroup: {nodegroup}")
|
||||
asset_main = nodegroup
|
||||
if nodegroup is not None:
|
||||
bk_logger.info("appended nodegroup: %s", nodegroup)
|
||||
asset_main = nodegroup
|
||||
|
||||
asset_data["resolution"] = kwargs["resolution"]
|
||||
udpate_asset_data_in_dicts(asset_data)
|
||||
update_asset_data_in_dicts(asset_data)
|
||||
if asset_main is not None:
|
||||
update_asset_metadata(asset_main, asset_data)
|
||||
|
||||
@@ -1000,6 +1026,36 @@ def update_asset_metadata(asset_main, asset_data):
|
||||
asset_main.blenderkit.id = asset_data["id"]
|
||||
asset_main.blenderkit.description = asset_data["description"]
|
||||
asset_main.blenderkit.tags = utils.list2string(asset_data["tags"])
|
||||
asset_main.blenderkit.is_private = (
|
||||
"PRIVATE" if asset_data["isPrivate"] else "PUBLIC"
|
||||
)
|
||||
asset_main.blenderkit.verification_status = asset_data.get(
|
||||
"verificationStatus", "UPLOADING"
|
||||
).upper()
|
||||
|
||||
# manufacturer
|
||||
if asset_data.get("dictParameters"):
|
||||
dp = asset_data["dictParameters"]
|
||||
if dp.get("manufacturer"):
|
||||
asset_main.blenderkit.manufacturer = dp["manufacturer"]
|
||||
else:
|
||||
asset_main.blenderkit.manufacturer = ""
|
||||
if dp.get("designer"):
|
||||
asset_main.blenderkit.designer = dp["designer"]
|
||||
else:
|
||||
asset_main.blenderkit.designer = ""
|
||||
if dp.get("designCollection"):
|
||||
asset_main.blenderkit.design_collection = dp["designCollection"]
|
||||
else:
|
||||
asset_main.blenderkit.design_collection = ""
|
||||
if dp.get("designVariant"):
|
||||
asset_main.blenderkit.design_variant = dp["designVariant"]
|
||||
else:
|
||||
asset_main.blenderkit.design_variant = ""
|
||||
if dp.get("designYear"):
|
||||
asset_main.blenderkit.use_design_year = True
|
||||
asset_main.blenderkit.design_year = int(float(dp["designYear"]))
|
||||
|
||||
# BUG #554: categories needs update, but are not in asset_data
|
||||
sanitized = _sanitize_for_idprops(asset_data)
|
||||
# TODO consider reducing stored fields for filesize.
|
||||
@@ -1022,11 +1078,11 @@ def replace_resolution_linked(file_paths, asset_data):
|
||||
bk_logger.debug("try to re-link library")
|
||||
|
||||
if not os.path.isfile(file_paths[-1]):
|
||||
bk_logger.debug("library file doesnt exist")
|
||||
bk_logger.debug("library file doesn't exist")
|
||||
break
|
||||
l.filepath = os.path.join(os.path.dirname(l.filepath), file_name)
|
||||
l.name = file_name
|
||||
udpate_asset_data_in_dicts(asset_data)
|
||||
update_asset_data_in_dicts(asset_data)
|
||||
|
||||
|
||||
def replace_resolution_appended(file_paths, asset_data, resolution):
|
||||
@@ -1060,7 +1116,7 @@ def replace_resolution_appended(file_paths, asset_data, resolution):
|
||||
for pf in i.packed_files:
|
||||
pf.filepath = fp
|
||||
i.reload()
|
||||
udpate_asset_data_in_dicts(asset_data)
|
||||
update_asset_data_in_dicts(asset_data)
|
||||
|
||||
|
||||
# TODO: keep this until we check resolution replacement and other features from this one are supported in daemon.
|
||||
@@ -1179,6 +1235,13 @@ def handle_download_task(task: client_tasks.Task):
|
||||
"""
|
||||
global download_tasks
|
||||
|
||||
# If the task was already pruned/cancelled, ignore late reports from the client.
|
||||
if task.task_id not in download_tasks:
|
||||
bk_logger.debug(
|
||||
"Ignoring late download task %s (no longer tracked)", task.task_id
|
||||
)
|
||||
return
|
||||
|
||||
if task.status == "finished":
|
||||
# we still write progress since sometimes the progress bars wouldn't end on 100%
|
||||
download_write_progress(task.task_id, task)
|
||||
@@ -1188,7 +1251,7 @@ def handle_download_task(task: client_tasks.Task):
|
||||
download_tasks.pop(task.task_id)
|
||||
return
|
||||
except Exception as e:
|
||||
bk_logger.exception(f"Asset appending/linking has failed")
|
||||
bk_logger.exception("Asset appending/linking has failed: %s", e)
|
||||
task.message = f"Append failed: {e}"
|
||||
task.status = "error"
|
||||
|
||||
@@ -1205,15 +1268,92 @@ def clear_downloads():
|
||||
download_tasks.clear()
|
||||
|
||||
|
||||
def cancel_running_downloads(reason: str = ""):
|
||||
"""Cancel all running downloads for this Blender process and reset local UI state."""
|
||||
|
||||
global download_tasks
|
||||
|
||||
if not download_tasks:
|
||||
return
|
||||
|
||||
task_ids = list(download_tasks.keys())
|
||||
asset_ids = set()
|
||||
for task in download_tasks.values():
|
||||
if not isinstance(task, dict):
|
||||
continue
|
||||
asset_id = task.get("asset_data", {}).get("id")
|
||||
if asset_id:
|
||||
asset_ids.add(asset_id)
|
||||
|
||||
suffix = f" ({reason})" if reason else ""
|
||||
bk_logger.info("Cancelling %d running downloads%s", len(task_ids), suffix)
|
||||
|
||||
for task_id in task_ids:
|
||||
try:
|
||||
client_lib.cancel_download(task_id)
|
||||
except Exception as e:
|
||||
bk_logger.warning("Failed to cancel download %s: %s", task_id, e)
|
||||
|
||||
clear_downloads()
|
||||
_reset_progress_for_asset_ids(asset_ids)
|
||||
|
||||
|
||||
def prune_stalled_downloads(
|
||||
max_idle_seconds: float = STALE_DOWNLOAD_TIMEOUT, now: Optional[float] = None
|
||||
) -> None:
|
||||
"""Cancel downloads that have not reported progress for too long."""
|
||||
|
||||
if not download_tasks:
|
||||
return
|
||||
|
||||
now = now if now is not None else time.monotonic()
|
||||
stalled_task_ids = []
|
||||
stalled_asset_ids = set()
|
||||
|
||||
for task_id, task in list(download_tasks.items()):
|
||||
last_report_time = task.get("last_report_time") or task.get("started_at")
|
||||
if last_report_time is None:
|
||||
task["last_report_time"] = now
|
||||
continue
|
||||
if now - last_report_time < max_idle_seconds:
|
||||
continue
|
||||
|
||||
stalled_task_ids.append(task_id)
|
||||
|
||||
asset_info = task.get("asset_data", {})
|
||||
asset_id = asset_info.get("id")
|
||||
asset_name = asset_info.get("name", "Asset")
|
||||
|
||||
reports.add_report(
|
||||
f"Download for {asset_name} stalled and was cancelled. Please try again.",
|
||||
type="ERROR",
|
||||
)
|
||||
|
||||
if asset_id:
|
||||
stalled_asset_ids.add(asset_id)
|
||||
|
||||
if not stalled_task_ids:
|
||||
return
|
||||
|
||||
for task_id in stalled_task_ids:
|
||||
try:
|
||||
client_lib.cancel_download(task_id)
|
||||
except Exception as e:
|
||||
bk_logger.warning("Failed to cancel stalled download %s: %s", task_id, e)
|
||||
download_tasks.pop(task_id, None)
|
||||
|
||||
_reset_progress_for_asset_ids(stalled_asset_ids)
|
||||
|
||||
|
||||
def download_write_progress(task_id, task):
|
||||
"""writes progress from client_lib reports to addon tasks list"""
|
||||
global download_tasks
|
||||
task_addon = download_tasks.get(task.task_id)
|
||||
if task_addon is None:
|
||||
bk_logger.warning(f"couldn't write download progress to {task.progress}")
|
||||
return
|
||||
return # task was likely cancelled/stalled and removed; ignore late progress
|
||||
task_addon["progress"] = task.progress
|
||||
task_addon["text"] = task.message
|
||||
task_addon["last_report_time"] = time.monotonic()
|
||||
|
||||
# go through search results to write progress to display progress bars
|
||||
sr = search.get_search_results()
|
||||
@@ -1350,6 +1490,7 @@ def download(asset_data, **kwargs):
|
||||
if "unpack_files" in kwargs: # for add-on download
|
||||
prefs["unpack_files"] = kwargs["unpack_files"]
|
||||
|
||||
now = time.monotonic()
|
||||
data = {
|
||||
"asset_data": asset_data,
|
||||
"PREFS": prefs,
|
||||
@@ -1362,6 +1503,9 @@ def download(asset_data, **kwargs):
|
||||
data["download_dirs"] = paths.get_download_dirs(asset_data["assetType"])
|
||||
if "downloaders" in kwargs:
|
||||
data["downloaders"] = kwargs["downloaders"]
|
||||
data.setdefault("downloaders", [])
|
||||
data["started_at"] = now
|
||||
data["last_report_time"] = now
|
||||
|
||||
response = client_lib.asset_download(data)
|
||||
download_tasks[response["task_id"]] = data
|
||||
@@ -1379,7 +1523,7 @@ def check_downloading(asset_data, **kwargs) -> bool:
|
||||
p_asset_data = task["asset_data"]
|
||||
if p_asset_data["id"] == asset_data["id"]:
|
||||
at = asset_data["assetType"]
|
||||
if at in ("model", "material"):
|
||||
if at in ("model", "material", "printable", "scene"):
|
||||
downloader = {
|
||||
"location": kwargs["model_location"],
|
||||
"rotation": kwargs["model_rotation"],
|
||||
@@ -1449,7 +1593,7 @@ def try_finished_append(asset_data, **kwargs):
|
||||
try:
|
||||
os.remove(file_path)
|
||||
except Exception as e1:
|
||||
bk_logger.error(f"removing file {file_path} failed: {e1}")
|
||||
bk_logger.error("removing file %s failed: %s", file_path, e1)
|
||||
raise e
|
||||
|
||||
# Update downloaded status in search results
|
||||
@@ -1619,9 +1763,9 @@ def start_download(asset_data, **kwargs) -> bool:
|
||||
try_finished_append(asset_data, **kwargs)
|
||||
return False
|
||||
except Exception as e:
|
||||
bk_logger.info(f"Failed to append asset: {e}, continuing with download")
|
||||
bk_logger.info("Failed to append asset: %s, continuing with download", e)
|
||||
|
||||
if asset_data["assetType"] in ("model", "material"):
|
||||
if asset_data["assetType"] in ("model", "material", "printable", "scene"):
|
||||
downloader = {
|
||||
"location": kwargs["model_location"],
|
||||
"rotation": kwargs["model_rotation"],
|
||||
@@ -1965,7 +2109,7 @@ class BlenderkitAddonChoiceOperator(bpy.types.Operator):
|
||||
self.report({"INFO"}, f"Successfully enabled '{addon_name}'")
|
||||
refresh_addon_search_results_status()
|
||||
except Exception as e:
|
||||
bk_logger.error(f"Failed to enable addon: {e}")
|
||||
bk_logger.error("Failed to enable addon: %s", e)
|
||||
reports.add_report(
|
||||
f"Failed to enable '{addon_name}': {e}", type="ERROR"
|
||||
)
|
||||
@@ -1985,7 +2129,7 @@ class BlenderkitAddonChoiceOperator(bpy.types.Operator):
|
||||
self.report({"INFO"}, f"Successfully disabled '{addon_name}'")
|
||||
refresh_addon_search_results_status()
|
||||
except Exception as e:
|
||||
bk_logger.error(f"Failed to disable addon: {e}")
|
||||
bk_logger.error("Failed to disable addon: %s", e)
|
||||
reports.add_report(
|
||||
f"Failed to disable '{addon_name}': {e}", type="ERROR"
|
||||
)
|
||||
@@ -2000,7 +2144,7 @@ class BlenderkitAddonChoiceOperator(bpy.types.Operator):
|
||||
f"Temporary enable operation failed - returned: {result}"
|
||||
)
|
||||
except Exception as e:
|
||||
bk_logger.error(f"Failed to temp enable addon: {e}")
|
||||
bk_logger.error("Failed to temp enable addon: %s", e)
|
||||
reports.add_report(
|
||||
f"Failed to enable '{addon_name}': {e}", type="ERROR"
|
||||
)
|
||||
@@ -2016,7 +2160,7 @@ class BlenderkitAddonChoiceOperator(bpy.types.Operator):
|
||||
refresh_addon_search_results_status()
|
||||
|
||||
except Exception as e:
|
||||
bk_logger.error(f"Addon operation failed for '{addon_name}': {e}")
|
||||
bk_logger.error("Addon operation failed for '%s': %s", addon_name, e)
|
||||
error_msg = f"Failed to {selected_action.lower().replace('_', ' ')} '{addon_name}': {e}"
|
||||
reports.add_report(error_msg, type="ERROR")
|
||||
self.report({"ERROR"}, error_msg)
|
||||
@@ -2309,7 +2453,7 @@ class BlenderkitDownloadOperator(bpy.types.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
# replace resolution needs to replace all instances of the resolution in the scene
|
||||
# and deleting originals has to be thus done after the downlaod
|
||||
# and deleting originals has to be thus done after the download
|
||||
|
||||
kwargs = {
|
||||
"cast_parent": self.cast_parent,
|
||||
@@ -2333,7 +2477,7 @@ class BlenderkitDownloadOperator(bpy.types.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
def draw(self, context):
|
||||
# this timer is there to not let double clicks thorugh the popups down to the asset bar.
|
||||
# this timer is there to not let double clicks through the popups down to the asset bar.
|
||||
ui_panels.last_time_overlay_panel_active = time.time()
|
||||
layout = self.layout
|
||||
if self.invoke_resolution:
|
||||
|
||||
Reference in New Issue
Block a user