From 8de90469296dce752af66e6a5d9e9c9067704cf8 Mon Sep 17 00:00:00 2001 From: DcruBro Date: Tue, 7 Jul 2026 18:15:35 +0200 Subject: [PATCH] Manifest Fetching --- buildmac.sh | 3 ++ d2toolbox/__init__.py | 17 +++++------ d2toolbox/blender_manifest.toml | 3 ++ d2toolbox/globals.py | 53 +++++++++++++++++++++++++++++++++ d2toolbox/operators.py | 14 +++++++++ d2toolbox/panels.py | 11 ++++++- 6 files changed, 90 insertions(+), 11 deletions(-) create mode 100755 buildmac.sh create mode 100644 d2toolbox/globals.py diff --git a/buildmac.sh b/buildmac.sh new file mode 100755 index 0000000..b816545 --- /dev/null +++ b/buildmac.sh @@ -0,0 +1,3 @@ +#!/bin/zsh + +/Applications/Blender.app/Contents/MacOS/Blender --command extension build --source-dir ./d2toolbox --output-dir ./build diff --git a/d2toolbox/__init__.py b/d2toolbox/__init__.py index e352a1a..b396f31 100644 --- a/d2toolbox/__init__.py +++ b/d2toolbox/__init__.py @@ -1,19 +1,11 @@ -bl_info = { - "name": "D2Toolbox", - "author": "DcruBro", - "version": (0, 1, 0), - "blender": (5, 1, 0), - "location": "View3D > Sidebar > D2Toolbox", - "description": "Tools for working with Destiny 2 models", - "category": "Import-Export", -} - if "bpy" in locals(): import importlib + importlib.reload(globals) importlib.reload(operators) importlib.reload(panels) importlib.reload(preferences) else: + from . import globals from . import operators from . import panels from . import preferences @@ -30,6 +22,11 @@ def register(): for cls in classes: bpy.utils.register_class(cls) + if globals.getManifest() is None and bpy.app.online_access: + try: + globals.fetchAndSaveManifest() + except Exception as e: + print(f"D2Toolbox: failed to fetch manifest on load: {e}") def unregister(): for cls in reversed(classes): diff --git a/d2toolbox/blender_manifest.toml b/d2toolbox/blender_manifest.toml index d13f8bd..f885d70 100644 --- a/d2toolbox/blender_manifest.toml +++ b/d2toolbox/blender_manifest.toml @@ -10,6 +10,9 @@ type = "add-on" website = "https://git.dcrubro.com/dcrubro/d2toolbox" tags = ["Import-Export"] +copyright = [ + "2026 Copyright (C) DcruBro", +] blender_version_min = "5.1.0" diff --git a/d2toolbox/globals.py b/d2toolbox/globals.py new file mode 100644 index 0000000..f8b5cfd --- /dev/null +++ b/d2toolbox/globals.py @@ -0,0 +1,53 @@ +import bpy +import json +import os +import urllib.request + +manifest = None # Object JSON + +def getManifestPath(): + manifestPath = bpy.utils.extension_path_user(__package__, create=True) + return os.path.join(manifestPath, "manifest.json") + + +def loadManifest(): + global manifest + + manifestPath = getManifestPath() + if os.path.exists(manifestPath): + with open(manifestPath, "r") as f: + manifest = json.load(f) + return manifest + else: + return None + + +def getManifest(): + global manifest + + if manifest is None: + manifest = loadManifest() + return manifest + + +def fetchAndSaveManifest(): + global manifest + # Fetch from server: https://dcrubro.com/files/d2toolbox_manifest.json ; TODO: This is my personal server, and I should maybe allow people to use their own server. + # Will hardcode for now + # Blender extensions should be "self-contained", meaning that they shouldn't use non-default libraries. So, we will use urllib.request instead of requests. + url = "https://dcrubro.com/files/d2toolbox_manifest.json" + request = urllib.request.Request(url, headers={"User-Agent": "D2Toolbox (Blender add-on)"}) + with urllib.request.urlopen(request) as response: + manifest = json.loads(response.read().decode()) + + if manifest is None: + raise Exception("Failed to fetch manifest from server.") + + if (manifest.get("version") is None) or (manifest.get("version") != 1): + raise Exception("Invalid manifest version.") + + manifestPath = getManifestPath() + + with open(manifestPath, "w") as f: + json.dump(manifest, f) + return manifest diff --git a/d2toolbox/operators.py b/d2toolbox/operators.py index f0c88fc..5c4667f 100644 --- a/d2toolbox/operators.py +++ b/d2toolbox/operators.py @@ -1,4 +1,5 @@ import bpy +from . import globals class D2TOOLBOX_OT_hello(bpy.types.Operator): """Example operator - replace with real functionality""" @@ -10,6 +11,19 @@ class D2TOOLBOX_OT_hello(bpy.types.Operator): self.report({"INFO"}, "D2Toolbox says hello") return {"FINISHED"} +class D2TOOLBOX_OT_refetch_manifest(bpy.types.Operator): + """Refetch the Destiny 2 model manifest (run every once in a while to get the latest models).""" + bl_idname = "d2toolbox.refetch_manifest" + bl_label = "Refetch Manifest" + bl_options = {"REGISTER"} + + def execute(self, context): + # Placeholder for manifest refresh logic + globals.fetchAndSaveManifest() + self.report({"INFO"}, "Manifest refreshed") + return {"FINISHED"} + classes = ( D2TOOLBOX_OT_hello, + D2TOOLBOX_OT_refetch_manifest ) diff --git a/d2toolbox/panels.py b/d2toolbox/panels.py index cd0359e..8ef1c22 100644 --- a/d2toolbox/panels.py +++ b/d2toolbox/panels.py @@ -7,9 +7,18 @@ class D2TOOLBOX_PT_main(bpy.types.Panel): bl_region_type = "UI" bl_category = "D2Toolbox" + # Check if blender allows internet access + allowsInternet = bpy.app.online_access + def draw(self, context): + if not self.allowsInternet: + self.layout.label(text="Online access is disabled in Blender preferences.") + self.layout.label(text="D2Toolbox requires online access to fetch models and assets.") + return + layout = self.layout - layout.operator("d2toolbox.hello") + layout.label(text="Miscellaneous") + layout.operator("d2toolbox.refetch_manifest") classes = ( D2TOOLBOX_PT_main,