1 module unecht.core.serialization.sceneSerialization;
2 
3 import 
4     unecht.core.components.sceneNode,
5     unecht.core.serialization.serializer;
6 
7 import sdlang;
8 
9 import std.uuid;
10 
11 ///
12 struct UESceneSerializer
13 {
14     private UESerializer baseSerializer;
15 
16     ///
17     alias baseSerializer this;
18     
19     private Tag sceneNodesTag;
20 
21     ///
22     public void serialize(UESceneNode root, UUID[] externals=null)
23     {
24         if(!sceneNodesTag)
25         {
26             sceneNodesTag = new Tag();
27             sceneNodesTag.name = "nodes";
28         }
29 
30         if(externals)
31             baseSerializer.externals = externals;
32         
33         baseSerializer.blacklist ~= root.instanceId;
34 
35         foreach(rootChild; root.children)
36         {
37             serializeNode(rootChild);
38         }
39     }
40 
41     private void serializeNode(UESceneNode node)
42     {
43         import unecht.core.hideFlags;
44         if(!node.hideFlags.isSet(HideFlags.hideInHirarchie))
45         {
46             node.serialize(baseSerializer);
47             
48             auto nodeTag = new Tag(sceneNodesTag);
49             nodeTag.add(Value(node.instanceId.toString()));
50         }
51     }
52 
53     ///
54     public string toString()
55     {
56         auto root = new Tag;
57         
58         root.add(sceneNodesTag);
59         root.add(baseSerializer.content);
60         
61         return root.toSDLDocument();
62     }
63 }
64 
65 ///
66 struct UESceneDeserializer
67 {
68     UEDeserializer base;
69 
70     ///
71     alias base this;
72     
73     private Tag sceneNodesTag;
74 
75     ///
76     this(string input)
77     {
78         base = UEDeserializer(input);
79 
80         sceneNodesTag = root.all.tags["nodes"][0];
81         assert(sceneNodesTag !is null);
82     }
83 
84     ///
85     public void deserialize(UESceneNode root)
86     {
87         assert(root);
88 
89         import unecht.core.logger;
90 
91         foreach(Tag node; sceneNodesTag.all.tags)
92         {
93             auto id = node.values[0].get!string;
94 
95             auto scenenode = cast(UESceneNode)base.findLoadedRef(id);
96 
97             if(scenenode is null)
98             {
99                 scenenode = new UESceneNode;
100                 base.storeLoadedRef(scenenode,id);
101                 scenenode.deserialize(this,id);
102                 assert(scenenode.parent is null);
103                 scenenode.parent = root;
104 
105                 /+log.logf("new node added: '%s' (%s,%s)", 
106                     scenenode.entity.name, 
107                     scenenode.parent.children.length, 
108                     scenenode.children.length);
109                 log.logf("->: %s parent: %s", scenenode.instanceId, scenenode.parent.instanceId);+/
110             }
111             else
112             {
113                 //log.logf("node already created: '%s' (%s)", scenenode.entity.name, scenenode.instanceId);
114 
115                 assert(scenenode.parent is root || scenenode.parent is null);
116                 if(scenenode.parent is null)
117                     scenenode.parent = root;
118             }
119         }
120 
121         void recursiveCreate(UESceneNode _node)
122         {
123             foreach(child; _node.children)
124             {
125                 recursiveCreate(child);
126             }
127 
128             foreach(comp; _node.entity.components)
129             {
130                 comp.onCreate();
131             }
132         }
133         
134         foreach(Tag node; sceneNodesTag.all.tags)
135         {
136             auto id = node.values[0].get!string;
137 
138             auto scenenode = cast(UESceneNode)base.findLoadedRef(id);
139 
140             assert(scenenode);
141 
142             recursiveCreate(scenenode);
143         }
144 
145         foreach(i,lo; base.objectsLoaded)
146         {
147             import unecht.core.object;
148             import unecht.core.entity;
149             UEObject o = lo.o;
150             assert(o);
151 
152             //import std.stdio;
153             //writefln("loaded [%s]: %s", i, o.instanceId);
154 
155             if(cast(UESceneNode)o)
156             {
157                 UESceneNode n = cast(UESceneNode)o;
158                 assert(n.entity);
159                 //writefln(" sceneNode -> %s ('%s')", n.children.length, n.entity.name);
160                 //if(n.parent)
161                 //    writefln(" parent -> %s", n.parent.instanceId);
162             }
163             if(cast(UEEntity)o)
164             {
165                 UEEntity e = cast(UEEntity)o;
166                 assert(e.sceneNode);
167                 //writefln(" entity '%s': %s", e.name, e.sceneNode.instanceId);
168             }
169         }
170         
171         void val(UESceneNode n,UESceneNode root)
172         {
173             import std.format:format;
174 
175             assert(n);
176 
177             if(n !is root)
178             {
179                 assert(n.parent, format("no parent: %s",n.instanceId));
180                 assert(n.parent.hasChild(n));
181             }
182 
183             foreach(sn; n.children)
184             {
185                 assert(sn.parent is n, format("'%s'.%s !is '%s'.%s", sn.entity.name, sn.parent.instanceId, n.entity.name,n.instanceId));
186                 val(sn,root);
187             }
188         }
189 
190         // validity check
191         val(root,root);
192     }
193 }