+ /**
+ * A frame of an animation sequence. A frame is merely an index which
+ * presumably represents a "slide" or tile which should be displayed,
+ * and the duration that is how long the slide will be shown.
+ */
+
+ struct frame
+ {
+ unsigned index; ///< Frame index.
+ scalar duration; ///< Frame duration.
+
+ /**
+ * Construction is initialization. The frame data is loaded from a
+ * frame map which is probably loaded within an animation file.
+ */
+
+ frame(serializable_ptr root) :
+ index(0),
+ duration(1.0)
+ {
+ std::map<std::string,serializable_ptr> rootObj;
+
+ if (root->get(rootObj))
+ {
+ std::map<std::string,serializable_ptr>::iterator i;
+ for (i = rootObj.begin(); i != rootObj.end(); i++)
+ {
+ std::string key = (*i).first;
+ if (key == "index")
+ {
+ long value = 0;
+ (*i).second->get(value);
+ index = unsigned(value);
+ }
+ else if (key == "duration")
+ {
+ double value = 0.0;
+ (*i).second->getNumber(value);
+ duration = scalar(value);
+ }
+ }
+ }
+ }
+ };
+
+
+ /**
+ * A sequence is just a few attributes and a list of frames in the order
+ * that they should be played.
+ */
+
+ struct sequence
+ {
+ std::vector<frame> frames; ///< List of frames.
+ scalar delay; ///< Scale frame durations.
+ bool loop; ///< Does the sequence repeat?
+ std::string next; ///< Next sequence name.
+
+ /**
+ * Construction is initialization. The constructor loads sequence
+ * data from the sequence map, presumably loaded from an animation
+ * file. The rest of the loading takes place in the frame's
+ * constructor which loads each individual frame.
+ */
+
+ sequence(serializable_ptr root) :
+ delay(0.0),
+ loop(true)
+ {
+ std::map<std::string,serializable_ptr> rootObj;
+
+ if (root->get(rootObj))
+ {
+ std::map<std::string,serializable_ptr>::iterator i;
+ for (i = rootObj.begin(); i != rootObj.end(); i++)
+ {
+ std::string key = (*i).first;
+
+ if (key == "frames")
+ {
+ std::vector<serializable_ptr> framesObj;
+
+ if ((*i).second->get(framesObj))
+ {
+ std::vector<serializable_ptr>::iterator j;
+
+ for (j = framesObj.begin();
+ j != framesObj.end(); j++)
+ {
+ if (*j)
+ {
+ frames.push_back(frame(*j));
+ }
+ }
+ }
+ }
+ else if (key == "delay")
+ {
+ double value;
+ (*i).second->getNumber(value);
+ delay = scalar(value);
+ }
+ else if (key == "loop")
+ {
+ (*i).second->get(loop);
+ }
+ else if (key == "next")
+ {
+ (*i).second->get(next);
+ }
+ }
+ }
+ }
+ };
+
+
+ /**
+ * Starts loading a file with animation data. Such a file is formatted
+ * as a map of named sequences. The sequence constructor loads each
+ * individual sequence.
+ */
+
+ void loadFromFile()
+ {
+ std::string filePath = animation::getPathToResource(getName());
+
+ deserializer in(filePath);
+
+ serializable_ptr root = in.deserialize();
+
+ if (root)
+ {
+ std::map<std::string,serializable_ptr> rootObj;
+
+ if (root->get(rootObj))
+ {
+ std::map<std::string,serializable_ptr>::iterator i;
+
+ for (i = rootObj.begin(); i != rootObj.end(); i++)
+ {
+ sequences.insert(std::pair<std::string,sequence>((*i).first,
+ sequence((*i).second)));
+ }
+ }
+ }
+ }
+
+ /**
+ * Construction is initialization. The animation class data container
+ * registers itself as a mippleton and then loads the animation data.
+ */
+
+ explicit animation_data(const std::string& name) :
+ mippleton<animation_data>(name)
+ {
+ loadFromFile();
+ }
+
+ std::map<std::string,sequence> sequences; ///< List of sequences.