| 227 | } |
| 228 | |
| 229 | bool Animation::SaveTimeline(BytesContainer& data) |
| 230 | { |
| 231 | if (OnCheckSave()) |
| 232 | return true; |
| 233 | ScopeLock lock(Locker); |
| 234 | MemoryReadStream stream(data.Get(), data.Length()); |
| 235 | |
| 236 | // Version |
| 237 | int32 version; |
| 238 | stream.Read(version); |
| 239 | switch (version) |
| 240 | { |
| 241 | case 3: // [Deprecated on 03.09.2021 expires on 03.09.2023] |
| 242 | case 4: |
| 243 | { |
| 244 | // Meta |
| 245 | float fps; |
| 246 | stream.Read(fps); |
| 247 | Data.FramesPerSecond = static_cast<double>(fps); |
| 248 | int32 duration; |
| 249 | stream.Read(duration); |
| 250 | Data.Duration = static_cast<double>(duration); |
| 251 | int32 tracksCount; |
| 252 | stream.Read(tracksCount); |
| 253 | |
| 254 | // Tracks |
| 255 | Data.Channels.Clear(); |
| 256 | Events.Clear(); |
| 257 | NestedAnims.Clear(); |
| 258 | Dictionary<int32, int32> animationChannelTrackIndexToChannelIndex; |
| 259 | animationChannelTrackIndexToChannelIndex.EnsureCapacity(tracksCount); |
| 260 | for (int32 trackIndex = 0; trackIndex < tracksCount; trackIndex++) |
| 261 | { |
| 262 | const byte trackType = stream.ReadByte(); |
| 263 | const byte trackFlags = stream.ReadByte(); |
| 264 | int32 parentIndex, childrenCount; |
| 265 | stream.Read(parentIndex); |
| 266 | stream.Read(childrenCount); |
| 267 | String name; |
| 268 | stream.Read(name, -13); |
| 269 | Color32 color; |
| 270 | stream.Read(color); |
| 271 | switch (trackType) |
| 272 | { |
| 273 | case 17: |
| 274 | { |
| 275 | // Animation Channel track |
| 276 | const int32 channelIndex = Data.Channels.Count(); |
| 277 | animationChannelTrackIndexToChannelIndex[trackIndex] = channelIndex; |
| 278 | auto& channel = Data.Channels.AddOne(); |
| 279 | channel.NodeName = name; |
| 280 | break; |
| 281 | } |
| 282 | case 18: |
| 283 | { |
| 284 | // Animation Channel Data track |
| 285 | const byte type = stream.ReadByte(); |
| 286 | int32 keyframesCount; |
nothing calls this directly
no test coverage detected