226 lines
5.4 KiB
Python
226 lines
5.4 KiB
Python
from pathlib import Path
|
|
from typing import Any
|
|
import bpy
|
|
import os
|
|
import subprocess
|
|
import json
|
|
|
|
from bpy.props import (
|
|
BoolProperty,
|
|
EnumProperty,
|
|
FloatProperty,
|
|
IntProperty,
|
|
PointerProperty,
|
|
StringProperty,
|
|
)
|
|
|
|
|
|
id_type = {
|
|
"Action": "actions",
|
|
"Armature": "armatures",
|
|
"Brush": "brushes",
|
|
"CacheFile": "cache_files",
|
|
"Camera": "cameras",
|
|
"Curve": "curves",
|
|
"FreestyleLineStyle": "linestyles",
|
|
"GreasePencil": "grease_pencil",
|
|
"Group": "groups",
|
|
"Image": "images",
|
|
"Key": "shape_keys",
|
|
"Light": "lights",
|
|
"Lattice": "lattices",
|
|
"Library": "librairies",
|
|
"Mask": "masks",
|
|
"Material": "materials",
|
|
"Mesh": "meshes",
|
|
"MetaBall": "metaballs",
|
|
"MovieClip": "movieclips",
|
|
"NodeTree": "node_groups",
|
|
"Object": "objects",
|
|
"PaintCurve": "paint_curves",
|
|
"Palette": "palettes",
|
|
"ParticleSettings": "particles",
|
|
"Scene": "scenes",
|
|
"Screen": "screens",
|
|
"Sound": "sounds",
|
|
"Speaker": "speakers",
|
|
"Text": "texts",
|
|
"Texture": "textures",
|
|
"Collection": "collections",
|
|
"VectorFont": "fonts",
|
|
"WindowManager": "window_managers",
|
|
"World": "worlds",
|
|
}
|
|
|
|
|
|
def read_json(path: Path):
|
|
jsonFile = path
|
|
if os.path.exists(jsonFile):
|
|
try:
|
|
with open(jsonFile) as data_file:
|
|
return json.load(data_file)
|
|
except Exception:
|
|
print("the file %s not json readable" % jsonFile)
|
|
return
|
|
|
|
|
|
def search_filter(search: str, str: str):
|
|
return search.lower() in str.lower()
|
|
|
|
|
|
def title(string: str):
|
|
return string.replace("_", " ").replace("-", " ").title()
|
|
|
|
|
|
def arg_name(string: str):
|
|
return string.replace(" ", "_").replace("-", "_").lower().strip("_")
|
|
|
|
|
|
def open_folder(path: Path):
|
|
try:
|
|
os.startfile(path)
|
|
except Exception:
|
|
_ = subprocess.Popen(["xdg-open", path])
|
|
|
|
|
|
def dic_to_args(dic):
|
|
import collections
|
|
|
|
args = collections.OrderedDict()
|
|
|
|
prop_type = {
|
|
str: StringProperty,
|
|
bool: BoolProperty,
|
|
float: FloatProperty,
|
|
int: IntProperty,
|
|
}
|
|
|
|
for k, v in dic.items():
|
|
if k in ("icon", "description") or not isinstance(k, str):
|
|
continue
|
|
|
|
if isinstance(v, str):
|
|
if "/" in v or "\\" in v:
|
|
args[k] = StringProperty(default=v, subtype="FILE_PATH")
|
|
else:
|
|
args[k] = StringProperty(default=v)
|
|
|
|
elif isinstance(v, bool):
|
|
args[k] = BoolProperty(default=v)
|
|
|
|
elif isinstance(v, float):
|
|
args[k] = FloatProperty(default=v, precision=3)
|
|
|
|
elif isinstance(v, int):
|
|
args[k] = IntProperty(default=v)
|
|
|
|
elif isinstance(v, dict):
|
|
if v.get("items") and isinstance(v["items"], (tuple, list)):
|
|
args[k] = EnumProperty(items=[(i, i, "") for i in v["items"]])
|
|
|
|
elif v.get("collection") and isinstance(v["collection"], str):
|
|
if v["collection"] not in id_type:
|
|
print(
|
|
"Collection %s not supported must be in %s"
|
|
% (v["collection"], id_type)
|
|
)
|
|
# args[k] = PointerProperty(type = getattr(bpy.types,v["collection"]))
|
|
else:
|
|
args[k] = PointerProperty(
|
|
type=getattr(bpy.types, v["collection"]), poll=v.get("poll")
|
|
)
|
|
else:
|
|
args[k] = prop_type[type(v["default"])](**v)
|
|
|
|
return args
|
|
|
|
|
|
def read_info(script_path: Path):
|
|
import collections
|
|
|
|
if isinstance(script_path, list):
|
|
lines = script_path
|
|
else:
|
|
with open(script_path, encoding="utf-8") as f:
|
|
lines = f.read().splitlines()
|
|
|
|
info = {}
|
|
for i, line in enumerate(lines):
|
|
if i >= 10:
|
|
return info, lines
|
|
|
|
if line.startswith("info"):
|
|
info_start = i
|
|
info_str = line
|
|
|
|
while (
|
|
info_str.endswith(",")
|
|
or not info_str.endswith("}")
|
|
or i == len(lines) - 1
|
|
):
|
|
i += 1
|
|
info_str += lines[i]
|
|
|
|
info_end = i
|
|
|
|
opening_brace_index = info_str.find("{")
|
|
|
|
try:
|
|
info = eval(info_str[opening_brace_index:])
|
|
except:
|
|
print("The info header in the file %s cannot be read" % script_path)
|
|
break
|
|
|
|
info = [(k, v) for k, v in info.items()]
|
|
info.sort(key=lambda x: info_str.find(x[0]))
|
|
|
|
info = collections.OrderedDict(info)
|
|
|
|
del lines[info_start : info_end + 1]
|
|
|
|
break
|
|
|
|
# remove backspace
|
|
for i in range(len(lines)):
|
|
if lines[0]:
|
|
break
|
|
else:
|
|
lines.pop(0)
|
|
|
|
for i in range(len(lines)):
|
|
if lines[-1]:
|
|
break
|
|
else:
|
|
lines.pop(-1)
|
|
|
|
return info, lines
|
|
|
|
|
|
def dic_to_str(dic: dict[str, Any], keys: list[str] | None = None, spaces: int = 4): # pyright: ignore[reportExplicitAny]
|
|
if not keys:
|
|
keys = sorted(dic)
|
|
|
|
line = "{\n"
|
|
for k in keys:
|
|
v = dic[k]
|
|
|
|
line += " " * spaces
|
|
|
|
if isinstance(k, str):
|
|
line += "'%s'" % k
|
|
else:
|
|
line += "%s" % k
|
|
|
|
line += " : "
|
|
|
|
if isinstance(v, str):
|
|
line += "'%s'" % v
|
|
else:
|
|
line += "%s" % v
|
|
|
|
line += ",\n"
|
|
|
|
line += "}\n\n"
|
|
|
|
return line
|