163 lines
5.3 KiB
Python
163 lines
5.3 KiB
Python
# ***************************************************************************
|
|
# * Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
|
|
# * *
|
|
# * This file is part of FreeCAD. *
|
|
# * *
|
|
# * FreeCAD is free software: you can redistribute it and/or modify it *
|
|
# * under the terms of the GNU Lesser General Public License as *
|
|
# * published by the Free Software Foundation, either version 2.1 of the *
|
|
# * License, or (at your option) any later version. *
|
|
# * *
|
|
# * FreeCAD is distributed in the hope that it will be useful, but *
|
|
# * WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
# * Lesser General Public License for more details. *
|
|
# * *
|
|
# * You should have received a copy of the GNU Lesser General Public *
|
|
# * License along with FreeCAD. If not, see *
|
|
# * <https://www.gnu.org/licenses/>. *
|
|
# * *
|
|
# **************************************************************************/
|
|
|
|
__title__ = "material model utilities"
|
|
__author__ = "David Carter"
|
|
__url__ = "https://www.freecad.org"
|
|
|
|
import os
|
|
import io
|
|
from pathlib import Path
|
|
import yaml
|
|
|
|
import FreeCAD
|
|
|
|
|
|
unicode = str
|
|
|
|
__models = {}
|
|
__modelsByPath = {}
|
|
|
|
def _dereference(parent, child):
|
|
# Add the child parameters to the parent
|
|
parentModel = parent["model"]
|
|
parentBase = parent["base"]
|
|
childModel = child["model"]
|
|
childBase = child["base"]
|
|
for name, value in childModel[childBase].items():
|
|
if name not in ["Name", "UUID", "URL", "Description", "DOI", "Inherits"] and \
|
|
name not in parentModel[parentBase]: # Don't add if it's already there
|
|
parentModel[parentBase][name] = value
|
|
|
|
print("dereferenced:")
|
|
print(parentModel)
|
|
|
|
def _dereferenceInheritance(data):
|
|
if not data["dereferenced"]:
|
|
data["dereferenced"] = True # Prevent recursion loops
|
|
|
|
model = data["model"]
|
|
base = data["base"]
|
|
if "Inherits" in model[base]:
|
|
print("Model '{0}' inherits from:".format(data["name"]))
|
|
for parent in model[base]["Inherits"]:
|
|
print("\t'{0}'".format(parent))
|
|
print("\t\t'{0}'".format(parent.keys()))
|
|
print("\t\t'{0}'".format(parent["UUID"]))
|
|
|
|
# This requires that all models have already been loaded undereferenced
|
|
child = __models[parent["UUID"]]
|
|
if child is not None:
|
|
_dereference(data, child)
|
|
|
|
def _dereferenceAll():
|
|
for data in __models.values():
|
|
_dereferenceInheritance(data)
|
|
|
|
def _scanFolder(folder):
|
|
print("Scanning folder '{0}'".format(folder.absolute()))
|
|
for child in folder.iterdir():
|
|
if child.is_dir():
|
|
_scanFolder(child)
|
|
else:
|
|
if child.suffix.lower() == ".yml":
|
|
data = getModelFromPath(child)
|
|
|
|
if data is not None:
|
|
__models[data["uuid"]] = data
|
|
__modelsByPath[data["path"]] = data
|
|
# print(data["model"])
|
|
else:
|
|
print("Extension '{0}'".format(child.suffix.lower()))
|
|
|
|
def _scanModels(libraries):
|
|
__models = {} # Clear the current library
|
|
__modelsByPath = {}
|
|
print("_scanModels")
|
|
print(libraries)
|
|
for library in libraries:
|
|
_scanFolder(Path(library))
|
|
|
|
# Satisfy aany inheritances
|
|
_dereferenceAll()
|
|
|
|
def getPreferredSaveDirectory():
|
|
pass
|
|
|
|
def getModelLibraries():
|
|
|
|
libraries = []
|
|
|
|
# TODO: Expand beyond the standard models as we do for material paths
|
|
path = Path(FreeCAD.getResourceDir()) / "Mod/Material/Resources/Models"
|
|
libraries.append(path)
|
|
|
|
_scanModels(libraries)
|
|
|
|
return libraries
|
|
|
|
def getModel(uuid):
|
|
"""
|
|
Retrieve the specified model.
|
|
"""
|
|
if len(__models) < 1:
|
|
getModelLibraries()
|
|
|
|
if uuid not in __models:
|
|
return None
|
|
return __models[uuid]
|
|
|
|
def getModelFromPath(filePath):
|
|
"""
|
|
Retrieve the model at the specified path.
|
|
|
|
This may not need public exposure?
|
|
"""
|
|
try:
|
|
path = Path(filePath)
|
|
stream = open(path.absolute(), "r")
|
|
model = yaml.safe_load(stream)
|
|
|
|
base = "Model"
|
|
if "AppearanceModel" in model:
|
|
base = "AppearanceModel"
|
|
|
|
uuid = model[base]["UUID"]
|
|
name = model[base]["Name"]
|
|
|
|
data = {}
|
|
data["base"] = base
|
|
data["name"] = name
|
|
data["path"] = path.absolute()
|
|
data["uuid"] = uuid
|
|
data["model"] = model
|
|
data["dereferenced"] = False
|
|
return data
|
|
except Exception as ex:
|
|
print("Unable to load '{0}'".format(path.absolute()))
|
|
print(ex)
|
|
|
|
return None
|
|
|
|
def saveModel(model, path):
|
|
"""
|
|
Write the model to the specified path
|
|
""" |