FreeCAD

Форк
0
/
MaterialManagerPyImp.cpp 
350 строк · 11.7 Кб
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
#include "PreCompiled.h"
23

24
#include "Exceptions.h"
25
#include "MaterialFilter.h"
26
#include "MaterialFilterPy.h"
27
#include "MaterialManager.h"
28
#include "MaterialManagerPy.h"
29
#include "MaterialPy.h"
30
#include "Materials.h"
31

32
#include "MaterialManagerPy.cpp"
33

34
#include <Base/PyWrapParseTupleAndKeywords.h>
35

36
using namespace Materials;
37

38
// returns a string which represents the object e.g. when printed in python
39
std::string MaterialManagerPy::representation() const
40
{
41
    std::stringstream str;
42
    str << "<MaterialManager object at " << getMaterialManagerPtr() << ">";
43

44
    return str.str();
45
}
46

47
PyObject* MaterialManagerPy::PyMake(struct _typeobject*, PyObject*, PyObject*)  // Python wrapper
48
{
49
    // never create such objects with the constructor
50
    return new MaterialManagerPy(new MaterialManager());
51
}
52

53
// constructor method
54
int MaterialManagerPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
55
{
56
    return 0;
57
}
58

59
PyObject* MaterialManagerPy::getMaterial(PyObject* args)
60
{
61
    char* uuid {};
62
    if (!PyArg_ParseTuple(args, "s", &uuid)) {
63
        return nullptr;
64
    }
65

66
    try {
67
        auto material = getMaterialManagerPtr()->getMaterial(QString::fromStdString(uuid));
68
        return new MaterialPy(new Material(*material));
69
    }
70
    catch (const MaterialNotFound&) {
71
        PyErr_SetString(PyExc_LookupError, "Material not found");
72
        return nullptr;
73
    }
74
}
75

76
PyObject* MaterialManagerPy::getMaterialByPath(PyObject* args)
77
{
78
    char* path {};
79
    const char* lib = "";
80
    if (!PyArg_ParseTuple(args, "et|s", "utf-8", &path, &lib)) {
81
        return nullptr;
82
    }
83

84
    std::string utf8Path = std::string(path);
85
    PyMem_Free(path);
86

87
    QString libPath(QString::fromStdString(lib));
88
    if (!libPath.isEmpty()) {
89
        try {
90
            auto material =
91
                getMaterialManagerPtr()->getMaterialByPath(QString::fromUtf8(utf8Path.c_str()),
92
                                                           libPath);
93
            return new MaterialPy(new Material(*material));
94
        }
95
        catch (const MaterialNotFound&) {
96
            PyErr_SetString(PyExc_LookupError, "Material not found");
97
            return nullptr;
98
        }
99
        catch (const LibraryNotFound&) {
100
            PyErr_SetString(PyExc_LookupError, "Library not found");
101
            return nullptr;
102
        }
103
    }
104

105
    try {
106
        auto material =
107
            getMaterialManagerPtr()->getMaterialByPath(QString::fromUtf8(utf8Path.c_str()));
108
        return new MaterialPy(new Material(*material));
109
    }
110
    catch (const MaterialNotFound&) {
111
        PyErr_SetString(PyExc_LookupError, "Material not found");
112
        return nullptr;
113
    }
114
}
115

116
PyObject* MaterialManagerPy::inheritMaterial(PyObject* args)
117
{
118
    char* uuid {};
119
    if (!PyArg_ParseTuple(args, "s", &uuid)) {
120
        return nullptr;
121
    }
122

123
    try {
124
        auto parent = getMaterialManagerPtr()->getMaterial(QString::fromStdString(uuid));
125

126
        // Found the parent. Create a new material with this as parent
127
        auto material = new Material();
128
        material->setParentUUID(QString::fromLatin1(uuid));
129
        return new MaterialPy(material); // Transfers ownership
130
    }
131
    catch (const MaterialNotFound&) {
132
        PyErr_SetString(PyExc_LookupError, "Material not found");
133
        return nullptr;
134
    }
135
}
136

137
Py::List MaterialManagerPy::getMaterialLibraries() const
138
{
139
    auto libraries = getMaterialManagerPtr()->getMaterialLibraries();
140
    Py::List list;
141

142
    for (auto it = libraries->begin(); it != libraries->end(); it++) {
143
        auto lib = *it;
144
        Py::Tuple libTuple(3);
145
        libTuple.setItem(0, Py::String(lib->getName().toStdString()));
146
        libTuple.setItem(1, Py::String(lib->getDirectoryPath().toStdString()));
147
        libTuple.setItem(2, Py::String(lib->getIconPath().toStdString()));
148

149
        list.append(libTuple);
150
    }
151

152
    return list;
153
}
154

155
Py::Dict MaterialManagerPy::getMaterials() const
156
{
157
    Py::Dict dict;
158

159
    auto materials = getMaterialManagerPtr()->getMaterials();
160

161
    for (auto it = materials->begin(); it != materials->end(); it++) {
162
        QString key = it->first;
163
        auto material = it->second;
164

165
        PyObject* materialPy = new MaterialPy(new Material(*material));
166
        dict.setItem(Py::String(key.toStdString()), Py::Object(materialPy, true));
167
    }
168

169
    // return Py::new_reference_to(dict);
170
    return dict;
171
}
172

173
PyObject* MaterialManagerPy::getCustomAttributes(const char* /*attr*/) const
174
{
175
    return nullptr;
176
}
177

178
int MaterialManagerPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
179
{
180
    return 0;
181
}
182

183
PyObject* MaterialManagerPy::materialsWithModel(PyObject* args)
184
{
185
    char* uuid {};
186
    if (!PyArg_ParseTuple(args, "s", &uuid)) {
187
        return nullptr;
188
    }
189

190
    auto materials = getMaterialManagerPtr()->materialsWithModel(QString::fromStdString(uuid));
191
    Py::Dict dict;
192

193
    for (auto it = materials->begin(); it != materials->end(); it++) {
194
        QString key = it->first;
195
        auto material = it->second;
196

197
        PyObject* materialPy = new MaterialPy(new Material(*material));
198
        dict.setItem(key.toStdString(), Py::asObject(materialPy));
199
    }
200

201
    return Py::new_reference_to(dict);
202
}
203

204
PyObject* MaterialManagerPy::materialsWithModelComplete(PyObject* args)
205
{
206
    char* uuid {};
207
    if (!PyArg_ParseTuple(args, "s", &uuid)) {
208
        return nullptr;
209
    }
210

211
    auto materials =
212
        getMaterialManagerPtr()->materialsWithModelComplete(QString::fromStdString(uuid));
213
    Py::Dict dict;
214

215
    for (auto it = materials->begin(); it != materials->end(); it++) {
216
        QString key = it->first;
217
        auto material = it->second;
218

219
        PyObject* materialPy = new MaterialPy(new Material(*material));
220
        dict.setItem(key.toStdString(), Py::asObject(materialPy));
221
    }
222

223
    return Py::new_reference_to(dict);
224
}
225

226
PyObject* MaterialManagerPy::save(PyObject* args, PyObject* kwds)
227
{
228
    char* libraryName {};
229
    PyObject* obj {};
230
    char* path {};
231
    PyObject* overwrite = Py_False;
232
    PyObject* saveAsCopy = Py_False;
233
    PyObject* saveInherited = Py_False;
234
    static const std::array<const char *, 7> kwlist { "library", "material", "path", "overwrite", "saveAsCopy", "saveInherited", nullptr };
235
    if (!Base::Wrapped_ParseTupleAndKeywords(args,
236
                                     kwds,
237
                                     "etOet|O!O!O!",
238
                                     kwlist,
239
                                     "utf-8", &libraryName,
240
                                     &obj,
241
                                     "utf-8", &path,
242
                                     &PyBool_Type, &overwrite,
243
                                     &PyBool_Type, &saveAsCopy,
244
                                     &PyBool_Type, &saveInherited)) {
245
        return nullptr;
246
    }
247

248
    Base::Console().Log("library name %s\n", libraryName);
249
    Base::Console().Log("path %s\n", path);
250

251
    MaterialPy* material;
252
    if (QLatin1String(obj->ob_type->tp_name) == QLatin1String("Materials.Material")) {
253
        material = static_cast<MaterialPy*>(obj);
254
    }
255
    else {
256
        PyErr_Format(PyExc_TypeError, "Material expected not '%s'", obj->ob_type->tp_name);
257
        return nullptr;
258
    }
259
    if (!material) {
260
        PyErr_SetString(PyExc_TypeError, "Invalid material object");
261
        return nullptr;
262
    }
263
    auto sharedMaterial = std::make_shared<Material>(*(material->getMaterialPtr()));
264

265
    std::shared_ptr<MaterialLibrary> library;
266
    try {
267
        library = getMaterialManagerPtr()->getLibrary(QString::fromUtf8(libraryName));
268
    }
269
    catch (const LibraryNotFound&) {
270
        PyErr_SetString(PyExc_LookupError, "Unknown library");
271
        return nullptr;
272
    }
273

274

275
    getMaterialManagerPtr()->saveMaterial(library,
276
                                          sharedMaterial,
277
                                          QString::fromUtf8(path),
278
                                          PyObject_IsTrue(overwrite),
279
                                          PyObject_IsTrue(saveAsCopy),
280
                                          PyObject_IsTrue(saveInherited));
281
    material->getMaterialPtr()->setUUID(sharedMaterial->getUUID()); // Make sure they match
282

283
    Py_INCREF(Py_None);
284
    return Py_None;
285
}
286

287
void addMaterials(Py::List& list,
288
                  const std::shared_ptr<std::map<QString, std::shared_ptr<MaterialTreeNode>>>& tree)
289
{
290
    for (auto& node : *tree) {
291
        if (node.second->getType() == MaterialTreeNode::DataNode) {
292
            auto material = node.second->getData();
293
            PyObject* materialPy = new MaterialPy(new Material(*material));
294
            list.append(Py::Object(materialPy, true));
295
        }
296
        else {
297
            addMaterials(list, node.second->getFolder());
298
        }
299
    }
300
}
301

302
PyObject* MaterialManagerPy::filterMaterials(PyObject* args, PyObject* kwds)
303
{
304
    PyObject* filterPy {};
305
    PyObject* includeLegacy = Py_False;
306
    static const std::array<const char*, 3> kwds_save{ "filter",
307
                                                       "includeLegacy",
308
                                                       nullptr };
309
    if (!Base::Wrapped_ParseTupleAndKeywords(args,
310
                                             kwds,
311
                                             //  "O|O!",
312
                                             "O!|O!",
313
                                             kwds_save,
314
                                             &MaterialFilterPy::Type,
315
                                             &filterPy,
316
                                             &PyBool_Type,
317
                                             &includeLegacy)) {
318
        return nullptr;
319
    }
320

321
    MaterialFilterOptions options;
322
    options.setIncludeFavorites(false);
323
    options.setIncludeRecent(false);
324
    options.setIncludeEmptyFolders(false);
325
    options.setIncludeEmptyLibraries(false);
326
    options.setIncludeLegacy(PyObject_IsTrue(includeLegacy));
327

328
    auto filter = std::make_shared<MaterialFilter>(*(static_cast<MaterialFilterPy*>(filterPy)->getMaterialFilterPtr()));
329

330
    auto libraries = getMaterialManagerPtr()->getMaterialLibraries();
331
    Py::List list;
332

333
    for (auto lib : *libraries) {
334
        auto tree = getMaterialManagerPtr()->getMaterialTree(lib, filter, options);
335
        if (tree->size() > 0) {
336
            addMaterials(list, tree);
337
        }
338
    }
339

340
    Py_INCREF(*list);
341
    return *list;
342
}
343

344
PyObject* MaterialManagerPy::refresh(PyObject* /*args*/)
345
{
346
    getMaterialManagerPtr()->refresh();
347

348
    Py_INCREF(Py_None);
349
    return Py_None;
350
}
351

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.