FreeCAD

Форк
0
/
VRMLObject.cpp 
236 строк · 7.7 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2009 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23

24
#include "PreCompiled.h"
25

26
#include "VRMLObject.h"
27
#include "Document.h"
28
#include "DocumentObjectPy.h"
29
#include <Base/FileInfo.h>
30
#include <Base/Reader.h>
31
#include <Base/Stream.h>
32
#include <Base/Tools.h>
33
#include <Base/Writer.h>
34

35

36
using namespace App;
37

38
PROPERTY_SOURCE(App::VRMLObject, App::GeoFeature)
39

40

41
VRMLObject::VRMLObject()
42
{
43
    ADD_PROPERTY_TYPE(VrmlFile,(nullptr),"",Prop_None,"Included file with the VRML definition");
44
    ADD_PROPERTY_TYPE(Urls,(""),"",static_cast<PropertyType>(Prop_ReadOnly|Prop_Output|Prop_Transient),
45
        "Resource files loaded by the VRML file");
46
    ADD_PROPERTY_TYPE(Resources,(""),"",static_cast<PropertyType>(Prop_ReadOnly|Prop_Output),
47
        "Resource files loaded by the VRML file");
48
    Urls.setSize(0);
49
    Resources.setSize(0);
50
}
51

52
short VRMLObject::mustExecute() const
53
{
54
    return 0;
55
}
56

57
void VRMLObject::onChanged(const App::Property* prop)
58
{
59
    if (restoreData) {
60
        return;
61
    }
62

63
    if (prop == &VrmlFile) {
64
        std::string orig = VrmlFile.getOriginalFileName();
65
        if (!orig.empty()) {
66
            // store the path name of the VRML file
67
            Base::FileInfo fi(orig);
68
            this->vrmlPath = fi.dirPath();
69
        }
70
    }
71
    else if (prop == &Urls) {
72
        // save the relative paths to the resource files in the project file
73
        Resources.setSize(Urls.getSize());
74
        const std::vector<std::string>& urls = Urls.getValues();
75
        int index = 0;
76
        for (const auto& it : urls) {
77
            std::string output = getRelativePath(this->vrmlPath, it);
78
            Resources.set1Value(index, output);
79
            ++index;
80
        }
81
    }
82
    GeoFeature::onChanged(prop);
83
}
84

85
PyObject *VRMLObject::getPyObject()
86
{
87
    if (PythonObject.is(Py::_None())){
88
        // ref counter is set to 1
89
        PythonObject = Py::Object(new DocumentObjectPy(this),true);
90
    }
91
    return Py::new_reference_to(PythonObject); 
92
}
93

94
std::string VRMLObject::getRelativePath(const std::string& prefix, const std::string& resource) const
95
{
96
    std::string str;
97
    std::string intname = this->getNameInDocument();
98
    if (!prefix.empty()) {
99
        if (resource.substr(0, prefix.size()) == prefix) {
100
            std::string suffix = resource.substr(prefix.size());
101
            str = intname + suffix;
102
        }
103
    }
104

105
    if (str.empty()) {
106
        Base::FileInfo fi(resource);
107
        str = intname + "/" + fi.fileName();
108
    }
109

110
    return str;
111
}
112

113
std::string VRMLObject::fixRelativePath(const std::string& name, const std::string& resource)
114
{
115
    // the part before the first '/' must match with object's internal name
116
    std::string::size_type pos = resource.find('/');
117
    if (pos != std::string::npos) {
118
        std::string prefix = resource.substr(0, pos);
119
        std::string suffix = resource.substr(pos);
120
        if (prefix != name) {
121
            return name + suffix;
122
        }
123
    }
124
    return resource;
125
}
126

127
void VRMLObject::makeDirectories(const std::string& path, const std::string& subdir)
128
{
129
    std::string::size_type pos = subdir.find('/');
130
    while (pos != std::string::npos) {
131
        std::string sub = subdir.substr(0, pos);
132
        std::string dir = path;
133
        dir += '/';
134
        dir += sub;
135
        Base::FileInfo fi(dir);
136
        if (!fi.createDirectory()) {
137
            break;
138
        }
139
        pos = subdir.find('/', pos+1);
140
    }
141
}
142

143
void VRMLObject::Save (Base::Writer &writer) const
144
{
145
    App::GeoFeature::Save(writer);
146

147
    // save also the inline files if there
148
    const std::vector<std::string>& urls = Resources.getValues();
149
    for (const auto & url : urls) {
150
        writer.addFile(url.c_str(), this);
151
    }
152

153
    this->indexSave = 0;
154
}
155

156
void VRMLObject::Restore(Base::XMLReader &reader)
157
{
158
    App::GeoFeature::Restore(reader);
159
    Urls.setSize(Resources.getSize());
160

161
    // restore also the inline files if there
162
    const std::vector<std::string>& urls = Resources.getValues();
163
    for(const auto & url : urls) {
164
        reader.addFile(url.c_str(), this);
165
    }
166

167
    this->indexRestore = 0;
168
}
169

170
void VRMLObject::SaveDocFile (Base::Writer &writer) const
171
{
172
    // store the inline files of the VRML file
173
    if (this->indexSave < Urls.getSize()) {
174
        std::string url = Urls[this->indexSave];
175

176
        Base::FileInfo fi(url);
177
        // it can happen that the transient directory has changed after
178
        // saving the 'URLs' in RestoreDocFile() and then we have to
179
        // try again with the new transient directory.
180
        if (!fi.exists()) {
181
            std::string path = getDocument()->TransientDir.getValue();
182
            url = Resources[this->indexSave];
183
            url = path + "/" + url;
184
            fi.setFile(url);
185
        }
186

187
        this->indexSave++;
188
        Base::ifstream file(fi, std::ios::in | std::ios::binary);
189
        if (file) {
190
            writer.Stream() << file.rdbuf();
191
        }
192
    }
193
}
194

195
bool VRMLObject::restoreTextureFinished(Base::Reader &reader)
196
{
197
    Base::StateLocker locker(restoreData, true);
198
    if (this->indexRestore < Resources.getSize()) {
199
        std::string path = getDocument()->TransientDir.getValue();
200
        std::string url = Resources[this->indexRestore];
201
        std::string intname = this->getNameInDocument();
202
        url = fixRelativePath(intname, url);
203
        Resources.set1Value(this->indexRestore, url);
204
        makeDirectories(path, url);
205

206
        url = path + "/" + url;
207
        Base::FileInfo fi(url);
208
        Urls.set1Value(this->indexRestore, url);
209
        this->indexRestore++;
210

211
        Base::ofstream file(fi, std::ios::out | std::ios::binary);
212
        if (file) {
213
            reader >> file.rdbuf();
214
            file.close();
215
        }
216

217
        return (this->indexRestore == Urls.getSize());
218
    }
219

220
    return false;
221
}
222

223
void VRMLObject::reloadFile()
224
{
225
    // after restoring all inline files reload the VRML file
226
    VrmlFile.touch();
227
    Base::FileInfo fi(VrmlFile.getValue());
228
    this->vrmlPath = fi.dirPath();
229
}
230

231
void VRMLObject::RestoreDocFile(Base::Reader &reader)
232
{
233
    if (restoreTextureFinished(reader)) {
234
        reloadFile();
235
    }
236
}
237

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

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

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

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