FreeCAD
163 строки · 5.3 Кб
1# ***************************************************************************
2# * Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
3# * *
4# * This file is part of FreeCAD. *
5# * *
6# * FreeCAD is free software: you can redistribute it and/or modify it *
7# * under the terms of the GNU Lesser General Public License as *
8# * published by the Free Software Foundation, either version 2.1 of the *
9# * License, or (at your option) any later version. *
10# * *
11# * FreeCAD is distributed in the hope that it will be useful, but *
12# * WITHOUT ANY WARRANTY; without even the implied warranty of *
13# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14# * Lesser General Public License for more details. *
15# * *
16# * You should have received a copy of the GNU Lesser General Public *
17# * License along with FreeCAD. If not, see *
18# * <https://www.gnu.org/licenses/>. *
19# * *
20# **************************************************************************/
21
22__title__ = "material model utilities"
23__author__ = "David Carter"
24__url__ = "https://www.freecad.org"
25
26import os
27import io
28from pathlib import Path
29import yaml
30
31import FreeCAD
32
33
34unicode = str
35
36__models = {}
37__modelsByPath = {}
38
39def _dereference(parent, child):
40# Add the child parameters to the parent
41parentModel = parent["model"]
42parentBase = parent["base"]
43childModel = child["model"]
44childBase = child["base"]
45for name, value in childModel[childBase].items():
46if name not in ["Name", "UUID", "URL", "Description", "DOI", "Inherits"] and \
47name not in parentModel[parentBase]: # Don't add if it's already there
48parentModel[parentBase][name] = value
49
50print("dereferenced:")
51print(parentModel)
52
53def _dereferenceInheritance(data):
54if not data["dereferenced"]:
55data["dereferenced"] = True # Prevent recursion loops
56
57model = data["model"]
58base = data["base"]
59if "Inherits" in model[base]:
60print("Model '{0}' inherits from:".format(data["name"]))
61for parent in model[base]["Inherits"]:
62print("\t'{0}'".format(parent))
63print("\t\t'{0}'".format(parent.keys()))
64print("\t\t'{0}'".format(parent["UUID"]))
65
66# This requires that all models have already been loaded undereferenced
67child = __models[parent["UUID"]]
68if child is not None:
69_dereference(data, child)
70
71def _dereferenceAll():
72for data in __models.values():
73_dereferenceInheritance(data)
74
75def _scanFolder(folder):
76print("Scanning folder '{0}'".format(folder.absolute()))
77for child in folder.iterdir():
78if child.is_dir():
79_scanFolder(child)
80else:
81if child.suffix.lower() == ".yml":
82data = getModelFromPath(child)
83
84if data is not None:
85__models[data["uuid"]] = data
86__modelsByPath[data["path"]] = data
87# print(data["model"])
88else:
89print("Extension '{0}'".format(child.suffix.lower()))
90
91def _scanModels(libraries):
92__models = {} # Clear the current library
93__modelsByPath = {}
94print("_scanModels")
95print(libraries)
96for library in libraries:
97_scanFolder(Path(library))
98
99# Satisfy aany inheritances
100_dereferenceAll()
101
102def getPreferredSaveDirectory():
103pass
104
105def getModelLibraries():
106
107libraries = []
108
109# TODO: Expand beyond the standard models as we do for material paths
110path = Path(FreeCAD.getResourceDir()) / "Mod/Material/Resources/Models"
111libraries.append(path)
112
113_scanModels(libraries)
114
115return libraries
116
117def getModel(uuid):
118"""
119Retrieve the specified model.
120"""
121if len(__models) < 1:
122getModelLibraries()
123
124if uuid not in __models:
125return None
126return __models[uuid]
127
128def getModelFromPath(filePath):
129"""
130Retrieve the model at the specified path.
131
132This may not need public exposure?
133"""
134try:
135path = Path(filePath)
136stream = open(path.absolute(), "r")
137model = yaml.safe_load(stream)
138
139base = "Model"
140if "AppearanceModel" in model:
141base = "AppearanceModel"
142
143uuid = model[base]["UUID"]
144name = model[base]["Name"]
145
146data = {}
147data["base"] = base
148data["name"] = name
149data["path"] = path.absolute()
150data["uuid"] = uuid
151data["model"] = model
152data["dereferenced"] = False
153return data
154except Exception as ex:
155print("Unable to load '{0}'".format(path.absolute()))
156print(ex)
157
158return None
159
160def saveModel(model, path):
161"""
162Write the model to the specified path
163"""