1 module sbylib.wrapper.assimp.metadata;
2 
3 import bindbc.assimp.types;
4 import sbylib.wrapper.assimp.constants : MetaDataType;
5 import sbylib.wrapper.assimp.functions : toRegularString, toSbylibVector, toEnum;
6 import sbylib.math : vec3;
7 
8 struct MetaData {
9 
10     private const(aiMetadata)* data;
11 
12     auto keys() {
13         import std.algorithm : map;
14 
15         return data.mKeys[0..data.mNumProperties].map!(key => key.toRegularString);
16     }
17 
18     auto values() {
19         import std.algorithm : map;
20 
21         return data.mValues[0..data.mNumProperties].map!(value => MetaDataEntry(value));
22     }
23 
24     auto opIndex(string key) {
25         import std.algorithm : countUntil;
26         import std.range : drop;
27 
28         auto idx = this.keys.countUntil(key);
29         return values.drop(idx).front;
30     }
31 
32     string toString() {
33         import std.algorithm : map;
34         import std.array : array;
35         import std.range : zip;
36         import std.format : format;
37         import sbylib.wrapper.assimp.functions : tree;
38 
39         return tree("Material", zip(keys, values).map!(t => format!"%s : %s"(t[0], t[1].toString())).array);
40     }
41 }
42 
43 struct MetaDataEntry {
44 
45     private const aiMetadataEntry entry;
46 
47     MetaDataType type() {
48         return entry.mType.toEnum!MetaDataType;
49     }
50 
51     auto data(Type)() {
52         static if (is(Type == bool)) {
53             assert(this.type == MetaDataType.Bool);
54             return *cast(bool*)entry.mData;
55         } else static if (is(Type == int)) {
56             assert(this.type == MetaDataType.Int);
57             return *cast(int*)entry.mData;
58         } else static if (is(Type == ulong)) {
59             assert(this.type == MetaDataType.Ulong);
60             return *cast(ulong*)entry.mData;
61         } else static if (is(Type == float)) {
62             assert(this.type == MetaDataType.Float);
63             return *cast(float*)entry.mData;
64         } else static if (is(Type == string)) {
65             import std.conv : to;
66             assert(this.type == MetaDataType.String);
67             return to!string(cast(char*)(entry.mData+4));
68         } else static if (is(Type == vec3)) {
69             assert(this.type == MetaDataType.Vec3);
70             return toSbylibVector(*cast(aiVector3D*)entry.mData);
71         } else {
72             import std.format : format;
73             static assert(false, format!"Invalid type specification: %s"(Type.stringof));
74         }
75     }
76 
77     string toString() {
78         import std.conv : to;
79         import std.format : format;
80 
81         final switch (type) {
82             case MetaDataType.Bool:
83                 return this.data!bool.to!string;
84             case MetaDataType.Int:
85                 return this.data!int.to!string;
86             case MetaDataType.Ulong:
87                 return this.data!ulong.to!string;
88             case MetaDataType.Float:
89                 return this.data!float.to!string;
90             case MetaDataType.String:
91                 return this.data!string;
92             case MetaDataType.Vec3:
93                 return this.data!vec3.to!string;
94         }
95     }
96 }