summaryrefslogtreecommitdiffstats
path: root/src/Authoring/QT3DSIMP/Qt3DSImportLib/Qt3DSImport.h
blob: 02bbbe2ead7f728c79eccfc98f82380c528023fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
/****************************************************************************
**
** Copyright (C) 1993-2009 NVIDIA Corporation.
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt 3D Studio.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#pragma once
#ifndef QT3DS_IMPORT_H
#define QT3DS_IMPORT_H
#include "Qt3DSImportLibPrecompile.h"
#include "Qt3DSImportMesh.h"
#include "Qt3DSImportPath.h"
#include "Qt3DSImportPerformImport.h"
#include "Qt3DSDMStringTable.h"
#include "Qt3DSImportComposerTypes.h"

namespace qt3dsimp {
using namespace std;
typedef QT3DSU64 TIMPHandle;

struct InstanceDesc
{
    TCharPtr m_Id;
    TIMPHandle m_Parent;
    TIMPHandle m_Handle;
    ComposerObjectTypes::Enum m_Type;
    InstanceDesc()
        : m_Id(NULL)
        , m_Parent(0)
        , m_Handle(0)
        , m_Type(ComposerObjectTypes::Unknown)
    {
    }
};

struct Animation
{
    TCharPtr m_InstanceId;
    TCharPtr m_PropertyName;
    QT3DSU32 m_SubPropertyIndex;
    EAnimationType m_Type;
    NVConstDataRef<QT3DSF32> m_Keyframes;
    Animation(TCharPtr iid, TCharPtr pname, QT3DSU32 subPropIndex, EAnimationType bufType,
              NVConstDataRef<QT3DSF32> keyframes)
        : m_InstanceId(iid)
        , m_PropertyName(pname)
        , m_SubPropertyIndex(subPropIndex)
        , m_Type(bufType)
        , m_Keyframes(keyframes)
    {
    }
    Animation()
        : m_InstanceId(L"")
        , m_PropertyName(L"")
        , m_SubPropertyIndex(0)
        , m_Type(EAnimationTypeNone)
    {
    }
};

struct AddRemoveInfo
{
    QT3DSU32 m_Existing; // intersection of new and old
    QT3DSU32 m_NumAdded; // new that doesn't exist in old
    QT3DSU32 m_NumRemoved; // old that doesn't exist in new
    AddRemoveInfo()
        : m_Existing(0)
        , m_NumAdded(0)
        , m_NumRemoved(0)
    {
    }
    AddRemoveInfo(QT3DSU32 exist, QT3DSU32 add, QT3DSU32 remove)
        : m_Existing(exist)
        , m_NumAdded(add)
        , m_NumRemoved(remove)
    {
    }
};

struct ParentChildLink
{
    TCharPtr m_Parent;
    TCharPtr m_Child;
    TCharPtr m_NextSibling;

    ParentChildLink(TCharPtr p, TCharPtr c, TCharPtr ns)
        : m_Parent(p)
        , m_Child(c)
        , m_NextSibling(ns)
    {
    }
    ParentChildLink() {}
    bool operator<(const ParentChildLink &other) const
    {
        // This works because at this point id's are in the string table
        // so equal strings are pointed to by the same pointer.
        return m_Parent < other.m_Parent;
    }
};

template <typename TDataType>
struct AddRemoveData
{
    NVConstDataRef<TDataType> m_Existing;
    NVConstDataRef<TDataType> m_Added;
    NVConstDataRef<TDataType> m_Removed;
    AddRemoveData() {}
    AddRemoveData(NVConstDataRef<TDataType> exist, NVConstDataRef<TDataType> add,
                  NVConstDataRef<TDataType> rem)
        : m_Existing(exist)
        , m_Added(add)
        , m_Removed(rem)
    {
    }
};

// Contains the basic information to perform an import or a refresh.
// Note that during an import or refresh, the user-id information on the
// descriptors may change.  So you can't ever use exactly this information
// on the descriptors.  You have to always query the descriptor.  Specifically,
// Create instance, delete instance, and update instance can change user id
// information.
struct ImportReport
{
    // There is a precondition you can rely on that parents are added
    // before children.  Furthermore, instances that are added won't
    // appear in the below parent child link added section.
    AddRemoveData<InstanceDesc> m_Instances;
    // For children, existing does tell you the intersection of the two
    // sets *but* existing is in the order of the new set.
    // This allows clients to detect child reordering where it may have
    // a substantial effect (such as materials which would then get mapped
    // to a different mesh instance).
    AddRemoveData<ParentChildLink> m_Links;

    AddRemoveData<Pair<TCharPtr, TCharPtr>> m_Images;
    AddRemoveData<Pair<TCharPtr, TCharPtr>> m_Meshes;
    AddRemoveData<Pair<TCharPtr, TCharPtr>> m_PathBuffers;
    AddRemoveData<Animation> m_Animations;

    ImportReport() {}
    ImportReport(AddRemoveData<InstanceDesc> instances, AddRemoveData<ParentChildLink> links,
                 AddRemoveData<Pair<TCharPtr, TCharPtr>> imageBuffers,
                 AddRemoveData<Pair<TCharPtr, TCharPtr>> meshes,
                 AddRemoveData<Pair<TCharPtr, TCharPtr>> pathBuffers,
                 AddRemoveData<Animation> animBuffers)
        : m_Instances(instances)
        , m_Links(links)
        , m_Images(imageBuffers)
        , m_Meshes(meshes)
        , m_PathBuffers(pathBuffers)
        , m_Animations(animBuffers)
    {
    }
};

template <typename TDataType>
struct DatatypeOrError
{
    bool m_Error;
    ImportErrorData m_ErrorData;
    TDataType m_Value;
    DatatypeOrError(const TDataType &value)
        : m_Error(false)
        , m_Value(value)
    {
    }
    DatatypeOrError(const ImportErrorData &error, const TDataType &badValue = TDataType())
        : m_Error(true)
        , m_ErrorData(error)
        , m_Value(badValue)
    {
    }

    TDataType &operator->()
    {
        QT3DS_ASSERT(m_Error == false);
        return m_Value;
    }
    TDataType &operator*()
    {
        QT3DS_ASSERT(m_Error == false);
        return m_Value;
    }
    operator TDataType()
    {
        QT3DS_ASSERT(m_Error == false);
        return m_Value;
    }
};
class Import;
typedef DatatypeOrError<Import *> ImportPtrOrError;
typedef DatatypeOrError<TCharPtr> CharPtrOrError;

template <typename TDataType>
struct SImportConverter
{
    TImportModelValue Convert(const TDataType &inType) { return inType; }
};

template <>
struct SImportConverter<TDataStrPtr>
{
    const wchar_t *Convert(const wchar_t *inValue) { return inValue; }
};
// Long4s are string refs, so they are set by string
template <>
struct SImportConverter<SLong4>
{
    SValue Convert(const wchar_t *inValue) { return SStringRef(inValue); }
};

class Import
{
protected:
    virtual ~Import(){}

public:
    // So users can check if a file is an import file.
    //<UICImportLib version="${fileversion}"
    static QT3DSU32 GetImportFileVersion() { return 1; }

    // Cache this string in the string table and return
    // a representation that will be around until this import object
    // is destroyed.
    virtual TCharPtr RegisterStr(TCharPtr data) = 0;
    // Returns the source directory relative to the dest directory
    // or the full path if it is on a different drive
    virtual QString GetSrcFile() const = 0;
    // Returns the full path of the destination directory
    virtual QString GetDestDir() const = 0;
    // Returns the full path of the image directory
    virtual QString GetImageDir() const = 0;
    // Returns the full path of the mesh directory
    virtual QString GetMeshDir() const = 0;
    // Returns the full path to the path buffer directory
    virtual QString GetPathBufferDir() const = 0;
    virtual void Release() = 0;
    // returns false if fname couldn't be opened for write
    // Fname is appended to the directory this object was created with.
    // This is necessary in order to keep relative paths valid within
    // the import file.  Returns an ID that uniquely identifies this import
    // object within the final document.
    virtual QT3DSU32 Save(TCharPtr fname) const = 0;

    // Add a mapping from an named id to a handle
    virtual Option<InstanceDesc> GetInstanceByHandle(TIMPHandle inst) const = 0;
    virtual Option<InstanceDesc> FindInstanceById(TCharPtr inst) const = 0;
    virtual Option<InstanceDesc> FindAnyInstanceById(TCharPtr inst) const = 0;
    virtual QT3DSU32 GetNumInstances() const = 0;
    virtual QT3DSU32 GetInstances(NVDataRef<InstanceDesc> outDescs) const = 0;
    virtual QT3DSU32 GetNumProperties(TIMPHandle instance) const = 0;
    virtual QT3DSU32 GetProperties(TIMPHandle inst, NVDataRef<PropertyValue> outBuffer) const = 0;
    virtual Option<SValue> GetInstancePropertyValue(TIMPHandle inst,
                                                    ComposerPropertyNames::Enum val) const = 0;
    virtual QT3DSU32 GetNumChildren(TIMPHandle instance) const = 0;
    virtual QT3DSU32 GetChildren(TIMPHandle instance, NVDataRef<InstanceDesc> childBuffer) const = 0;
    // Invalid instances will not be saved out to the import file and should be ignored
    // in the import report.
    virtual void MarkInstanceInvalid(TIMPHandle inst) = 0;

    virtual TIMPHandle CreateInstance(TCharPtr id, ComposerObjectTypes::Enum inType) = 0;
    // The new instance ends up attached to the same parent
    // and just after inSource in the parent's children lists.
    // This performs a deep copy and fixes up references if they occur in the
    // new hierarchy.
    virtual TIMPHandle CopyInstance(TIMPHandle inSource) = 0;

    // Returns true if inst exists, false otherwise.

    virtual bool SetInstanceProperties(TIMPHandle inst, NVConstDataRef<PropertyValue> inBuffer) = 0;

    template <typename TPropertyType, typename TDataType>
    void SetInstancePropertyValue(TIMPHandle inst,
                                  const SImportPropertyDefinition<TPropertyType> &inProperty,
                                  const TDataType &val)
    {
        DoSetInstancePropertyValue(inst, inProperty.m_Name,
                                   SImportConverter<TPropertyType>().Convert(val));
    }

    virtual bool AddChild(TIMPHandle inst, TIMPHandle child) = 0;

    virtual QT3DSU32 GetNumImages() const = 0;
    // Returns imgOriginalPath,imgDestPath pair
    virtual QT3DSU32 GetImages(NVDataRef<Pair<TCharPtr, TCharPtr>> imgPaths) const = 0;
    // Copies the an appropriate location in our import directory
    // Returns the path of the added image.  This may mangle the name slightly
    // In case of a conflict.
    // If this function returns L"", there was a problem copying the data
    // and you need to abort the import process immediately.  For a new import,
    // then delete the existing imported images.  For refresh, the user may just
    // be stuck with a half-updated dataset.
    // This path is relative to the current working directory when this object was created
    // or absolute.
    // Returns a relative path, from dest directory, where the image was saved out to.
    virtual CharPtrOrError AddImage(TCharPtr imgPath) = 0;
    // Assuming this image path is relative to the current working directory, find the image
    virtual Option<TCharPtr> FindImageByPath(TCharPtr imgPath) const = 0;
    // Assuming this path is relative to the import source document, find the image.
    virtual Option<TCharPtr> FindImageByRelativePath(TCharPtr imgPath) const = 0;

    virtual QT3DSU32 GetNumMeshes() const = 0;
    // Returns meshName,meshDestPath pair
    virtual QT3DSU32 GetMeshes(NVDataRef<Pair<TCharPtr, TCharPtr>> bufferPaths) const = 0;

    // Copies the vertex buffer into the appropriate location, renaming if necessary.
    // Mesh name is used to write out a reasonable buffer *and* on refresh to know
    // if a buffer is changed/updated or not
    // If this function returns L"", there was a problem copying the data
    // and you need to abort the import process immediately. For a new import,
    // then delete the existing imported images.  For refresh, the user may just
    // be stuck with a half-updated dataset.
    // Returns a relative path, from the mesh directory, where the mesh was saved out
    // to.
    virtual CharPtrOrError AddMesh(const Mesh &meshBuffer, TCharPtr meshName) = 0;
    virtual bool HasMesh(TCharPtr meshName) const = 0;
    // Return the mesh path with the current version number
    virtual Option<TCharPtr> FindMeshReferencePathByName(TCharPtr meshName) const = 0;
    virtual Option<TCharPtr> FindMeshFilePathByName(TCharPtr meshName) const = 0;

    virtual QT3DSU32 GetNumPathBuffers() const = 0;
    // Returns imgOriginalPath,imgDestPath pair
    virtual QT3DSU32 GetPathBuffers(NVDataRef<Pair<TCharPtr, TCharPtr>> pathBufferPaths) const = 0;
    virtual CharPtrOrError AddPathBuffer(const SPathBuffer &pathBuffer, TCharPtr pathName) = 0;
    // Assuming this Path path is relative to the current working directory, find the Path
    virtual Option<TCharPtr> FindPathBufferByPath(TCharPtr pathBufferPath) const = 0;
    // Assuming this path is relative to the import source document, find the Path.
    virtual Option<TCharPtr> FindPathBufferByRelativePath(TCharPtr pathBufferPath) const = 0;

    virtual QT3DSU32 GetNumAnimations() const = 0;
    virtual QT3DSU32 GetAnimations(NVDataRef<Animation> outBuffers) const = 0;
    // Data is copied into this object, you can release the anim buffer data after this
    virtual Option<Animation> FindAnimation(TCharPtr instance, TCharPtr propName,
                                            QT3DSU32 subPropIndex) const = 0;
    template <typename TDataType>
    void AddAnimation(TCharPtr instance, const SImportPropertyDefinition<TDataType> &inProperty,
                      QT3DSU32 subPropIndex, EAnimationType type, NVConstDataRef<QT3DSF32> values)
    {
        size_t arity = getDatatypeAnimatableArity(TypeToDataType<TDataType>());
        if (arity) {
            if (subPropIndex >= arity) {
                QT3DS_ASSERT(false);
                subPropIndex = 0;
            }
            DoAddAnimation(instance, ComposerPropertyNames::Convert(inProperty.GetName()),
                           subPropIndex, type, values);
        } else {
            QT3DS_ASSERT(false);
        }
    }

    // Call after the import process is complete in order to get all the new items.
    virtual ImportReport CompileReport() const = 0;

protected:
    // Careful with this.  If the property value contains heap memory
    // Then this may crash if you are coming from a dll.
    virtual void DoAddAnimation(TCharPtr instance, TCharPtr propName, QT3DSU32 subPropIndex,
                                EAnimationType type, NVConstDataRef<QT3DSF32> values) = 0;
    virtual bool DoSetInstancePropertyValue(TIMPHandle inst, ComposerPropertyNames::Enum pname,
                                            const TImportModelValue &val) = 0;
    virtual bool DoSetInstancePropertyValue(TIMPHandle inst, ComposerPropertyNames::Enum pname,
                                            TCharPtr val) = 0;

public:
    // Create blank import object
    // It is the caller's responsibility to ensure that imgPath and meshBufPath exist and
    // are writable.
    // Of srcDirectoryOrFile is a file, we get the directory of that file using
    // FilePath::GetDirName( srcDirectoryOrFile )
    // We then get its absolute path, get our absolute path, and attempt to create
    // a relative path from dest directory to src directory.
    static ImportPtrOrError Create(TCharPtr srcFile, TCharPtr destDirectory);

    // Load an import object from a file.  This can obviously fail
    // Also, an import file can contain multiple documents so you need to identify
    // which document you are talking about.
    // 0 means load the latest document.
    static ImportPtrOrError Load(TCharPtr pathToFile, QT3DSU32 inDocumentId = 0);

    // Create an import object that will update heavy resources (like images and mesh objects)
    // and it CompileReport will return objects that indicate the differences between the new
    // document and the existing document.
    // You have a chance to refresh from a document that isn't in the same location.
    // We use relative paths throughout the system so that image src paths are relative
    // to the src document directory and such, so we can still import sanely.
    // Dest directory is set to where original's dest directory was set to.
    static ImportPtrOrError CreateForRefresh(Import &original, TCharPtr srcFile);

    // Return the highest import version in a given document.  Returns zero upon
    // failure, else an integer that is valid for load.
    static QT3DSU32 GetHighestImportRevision(TCharPtr pathToFile);
};
}

#endif