Symbole-Tab in Project-Settings (Library-Item-Management)
Project-Settings hat jetzt 5 Tabs. Neuer 'Symbole'-Tab managt die Dossier-Library: List/Detail wie Materialien, mit 2D + 3D Slot pro Item. Backend (library.py): - save_manifest, update_item, delete_item, add_item — full CRUD aufs library.json - copy_to_assets: kopiert User-Dateien in library/assets/ mit Konflikt-Resolution (auto-suffix) Backend (rhinopanel.py / ProjectSettingsBridge): - _send_library: aktuelle Items + libraryRoot an Frontend - _add_library_file: File-Picker (.3dm direkt; .dwg/.obj/etc. zeigt Hinweis fuer kuenftige Konvertierung), kopiert + appended ans Item (variant 2d/3d) oder erstellt neues Item - _update_library_item: patch by id - _delete_library_item: entfernt Eintrag aus Manifest - LIBRARY_ITEMS + LIBRARY_ERROR Messages ans Frontend Frontend: - Neuer 'Symbole'-Tab mit List/Detail - Liste: Name, Type-Icon, '2D'/'3D' Status-Badge - Detail rechts: Name-Edit (live persist on blur), Type-Toggle (Symbol/Objekt), 2D/3D-File-Slots mit Datei-Picker, Tags-Editor - 'Neues Objekt' Button im Listen-Footer Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -888,13 +888,25 @@ class EbenenBridge(panel_base.BaseBridge):
|
||||
})
|
||||
except Exception:
|
||||
built_in = []
|
||||
# Library-Items initial laden (Symbole/Objekte fuer den
|
||||
# Symbole-Tab; Materialien sind separat).
|
||||
try:
|
||||
import library
|
||||
lib_manifest = library.load_manifest()
|
||||
lib_items = lib_manifest.get("items", [])
|
||||
lib_root = library.library_root()
|
||||
except Exception:
|
||||
lib_items = []; lib_root = ""
|
||||
params = {
|
||||
"defaults": current.get("defaults", {}),
|
||||
"project": current.get("project", {}),
|
||||
"materials": current.get("materials", []),
|
||||
"builtinMaterials": built_in,
|
||||
"hatchPatterns": _hatch_pattern_names(doc),
|
||||
"hatchPatternsFull": _list_hatch_patterns_full(doc),
|
||||
"linetypes": _list_linetypes_full(doc),
|
||||
"libraryItems": lib_items,
|
||||
"libraryRoot": lib_root,
|
||||
}
|
||||
def on_save(updated):
|
||||
doc2 = Rhino.RhinoDoc.ActiveDoc
|
||||
@@ -992,6 +1004,14 @@ class EbenenBridge(panel_base.BaseBridge):
|
||||
self._delete_hatch(p)
|
||||
elif t == "IMPORT_HATCH_FILE":
|
||||
self._import_hatch_file()
|
||||
elif t == "LIST_LIBRARY_ITEMS":
|
||||
self._send_library()
|
||||
elif t == "ADD_LIBRARY_FILE":
|
||||
self._add_library_file(p)
|
||||
elif t == "UPDATE_LIBRARY_ITEM":
|
||||
self._update_library_item(p)
|
||||
elif t == "DELETE_LIBRARY_ITEM":
|
||||
self._delete_library_item(p)
|
||||
def _pick_texture(self, payload):
|
||||
slot = payload.get("slot") or "diffuse"
|
||||
try:
|
||||
@@ -1157,6 +1177,117 @@ class EbenenBridge(panel_base.BaseBridge):
|
||||
"linetypes": _list_linetypes_full(d),
|
||||
"hatchPatternsFull": _list_hatch_patterns_full(d),
|
||||
})
|
||||
|
||||
# ---- Library-Item CRUD ----
|
||||
def _send_library(self):
|
||||
"""Sendet aktuelle Library-Items ans Frontend
|
||||
(LIBRARY_ITEMS-Message)."""
|
||||
try:
|
||||
import library
|
||||
m = library.load_manifest()
|
||||
self.send("LIBRARY_ITEMS", {
|
||||
"items": m.get("items", []),
|
||||
"libraryRoot": library.library_root(),
|
||||
})
|
||||
except Exception as ex:
|
||||
print("[PROJECT-SETTINGS] _send_library:", ex)
|
||||
|
||||
def _add_library_file(self, payload):
|
||||
"""Datei-Picker → kopieren in library/assets/ → Item zum
|
||||
Manifest hinzufuegen. Payload: {variant: '2d'|'3d',
|
||||
targetId: ?, itemType: 'symbol'|'object'}.
|
||||
Wenn targetId gesetzt: bestehendes Item updaten (Datei
|
||||
wird seinem files2d/3d zugewiesen). Sonst: neues Item."""
|
||||
try:
|
||||
import library
|
||||
import Eto.Forms as forms
|
||||
variant = (payload.get("variant") or "2d").lower()
|
||||
if variant not in ("2d", "3d"): variant = "2d"
|
||||
target_id = (payload.get("targetId") or "").strip() or None
|
||||
item_type = payload.get("itemType") or "object"
|
||||
if item_type not in ("symbol", "object"):
|
||||
item_type = "object"
|
||||
dlg = forms.OpenFileDialog()
|
||||
dlg.Title = ("Datei waehlen ({})".format(variant.upper()))
|
||||
dlg.MultiSelect = False
|
||||
dlg.Filters.Add(forms.FileFilter(
|
||||
"Rhino 3DM", ".3dm"))
|
||||
dlg.Filters.Add(forms.FileFilter(
|
||||
"Andere CAD-Formate", ".dwg", ".obj", ".fbx", ".dae", ".stl"))
|
||||
dlg.Filters.Add(forms.FileFilter("Alle", ".*"))
|
||||
parent = bridge_holder.get("form")
|
||||
res = dlg.ShowDialog(parent) if parent else dlg.ShowDialog(None)
|
||||
if str(res) != "Ok":
|
||||
return
|
||||
path = dlg.FileName or ""
|
||||
if not path: return
|
||||
ext = (path.split(".")[-1] if "." in path else "").lower()
|
||||
if ext != "3dm":
|
||||
# TODO: konvertieren via temporaerer RhinoDoc-Import
|
||||
# Phase 1: nur .3dm direkt unterstuetzt
|
||||
print("[PROJECT-SETTINGS] Format '.{}' wird in dieser "
|
||||
"Version noch nicht konvertiert — bitte in Rhino "
|
||||
"oeffnen + als .3dm speichern".format(ext))
|
||||
self.send("LIBRARY_ERROR", {
|
||||
"msg": "Format .{} noch nicht unterstuetzt. "
|
||||
"Konvertiere in Rhino zu .3dm.".format(ext),
|
||||
})
|
||||
return
|
||||
rel = library.copy_to_assets(path)
|
||||
if not rel:
|
||||
print("[PROJECT-SETTINGS] copy_to_assets failed")
|
||||
return
|
||||
if target_id:
|
||||
# Bestehendes Item updaten
|
||||
m = library.load_manifest()
|
||||
for it in m.get("items", []):
|
||||
if it.get("id") == target_id:
|
||||
key = "files" + variant
|
||||
it[key] = [rel]
|
||||
if not it.get("type"): it["type"] = item_type
|
||||
break
|
||||
library.save_manifest(m)
|
||||
else:
|
||||
# Neues Item
|
||||
import os
|
||||
base = os.path.basename(path)
|
||||
stem = os.path.splitext(base)[0]
|
||||
import uuid as _uuid
|
||||
new_id = "obj-" + _uuid.uuid4().hex[:10]
|
||||
item = {
|
||||
"id": new_id,
|
||||
"type": item_type,
|
||||
"name": stem,
|
||||
"version": 1,
|
||||
"tags": [],
|
||||
"files" + variant: [rel],
|
||||
}
|
||||
library.add_item(item)
|
||||
self._send_library()
|
||||
except Exception as ex:
|
||||
print("[PROJECT-SETTINGS] _add_library_file:", ex)
|
||||
|
||||
def _update_library_item(self, payload):
|
||||
"""Patcht ein Item per id. payload: {id, patch: {...}}"""
|
||||
try:
|
||||
import library
|
||||
item_id = (payload.get("id") or "").strip()
|
||||
patch = payload.get("patch") or {}
|
||||
if not item_id or not isinstance(patch, dict): return
|
||||
library.update_item(item_id, patch)
|
||||
self._send_library()
|
||||
except Exception as ex:
|
||||
print("[PROJECT-SETTINGS] _update_library_item:", ex)
|
||||
|
||||
def _delete_library_item(self, payload):
|
||||
try:
|
||||
import library
|
||||
item_id = (payload.get("id") or "").strip()
|
||||
if not item_id: return
|
||||
library.delete_item(item_id)
|
||||
self._send_library()
|
||||
except Exception as ex:
|
||||
print("[PROJECT-SETTINGS] _delete_library_item:", ex)
|
||||
b = _ProjectSettingsBridge()
|
||||
bridge_holder["form"] = panel_base.open_satellite_window(
|
||||
"project_settings",
|
||||
|
||||
Reference in New Issue
Block a user