/// <summary> /// Load an Animation node /// </summary> /// <param name="node"></param> private static void LoadAnimation(XFileData node) { JointFrame frame = null; int f = 0; // Debug.WriteLine("\tReading Animation "+node.Name); // Find the subnode that's a REFERENCE to a frame, then find the frame with that name XFileData frameRef = null; for (f = 0; f < node.NumberChildren; f++) { if (node.GetChild(f).Type == XFileGuid.Frame) { frameRef = node.GetChild(f); break; } } if (frameRef==null) throw new Exception("XFile animation node " + node.Name + "doesn't refer to a frame"); frame = JointFrame.Find(rootFrame, frameRef.Name); if (frame == null) throw new Exception("XFile Animation node " + node.Name + " refers to unknown frame " + frameRef.Name); // If this frame is animatable, create a motion controller and load in the limits. // Non-animatable frames have no motion controller. if (frame.Type==JointFrame.FrameType.Animating) { // Create a motion controller in which to store the limit data motion = new MotionController(); rmin = tmin = smin = false; // We haven't filled any motion members yet // Now iterate through the remaining AnimationKey and AnimationOptions nodes... for (int i=0; i<node.NumberChildren; i++) { using (XFileData child = node.GetChild(i)) { // **** Frame nested inside this frame if (child.Type==XFileGuid.AnimationKey) { LoadKeyframes(child, frame); } // We don't care about AnimationOptions & we skip the frame reference } } // Store the new motion controller in the frame frame.Motion = motion; // Debug.WriteLine("\t\tFrame "+frame.Name+" is animated"); } }
private FrameType type = FrameType.General; // this frame's type #endregion Fields #region Constructors /// <summary> /// Create a new blank JointFrame /// </summary> /// <param name="name"></param> public JointFrame(string name) { this.name = name; // Establish frame's type and index (and direction too, if cell has upstream and downstream variants) try { // Sockets if (name.StartsWith("skt")) { type = FrameType.Socket; index = Convert.ToInt32(Strip(name).Substring(3)); } // Hotspots else if (name.StartsWith("hot")) { type = FrameType.Hotspot; index = Convert.ToInt32(Strip(name).Substring(3)); } // Animating frames else if (name.StartsWith("anim")) { type = FrameType.Animating; index = Convert.ToInt32(Strip(name).Substring(4)); // Create a default motion controller in case this anim# frame is only colour-animated (no keyframes exist). Otherwise it'll crash when I try to update its joints Motion = new MotionController(); } // ordinary channels (or channels that are used in both upstream and downstream variants) else if (name.StartsWith("chan")) { type = FrameType.Channel; index = Convert.ToInt32(Strip(name).Substring(4)); direction = JointFrame.Direction.Both; } // upstream channels else if (name.StartsWith("up")) // upstream channels are like ordinary channels, except their direction is .Up { type = FrameType.Channel; index = Convert.ToInt32(Strip(name).Substring(2)); direction = JointFrame.Direction.Up; } // downstream channels else if (name.StartsWith("down")) { type = FrameType.Channel; index = Convert.ToInt32(Strip(name).Substring(4)); direction = JointFrame.Direction.Down; } // functional blocks else if (name.StartsWith("func")) { type = FrameType.Function; if (name.Length>4) // legacy: some cells use "func" instead of "func0". Indices are needed for Core to display global chems index = Convert.ToInt32(Strip(name).Substring(4)); direction = JointFrame.Direction.Both; } // upstream functional blocks else if (name.StartsWith("fup")) { type = FrameType.Function; if (name.Length > 2) // legacy index = Convert.ToInt32(Strip(name).Substring(3)); direction = JointFrame.Direction.Up; } // downstream functional blocks else if (name.StartsWith("fdown")) { type = FrameType.Function; if (name.Length > 5) // legacy index = Convert.ToInt32(Strip(name).Substring(5)); direction = JointFrame.Direction.Down; } } catch(Exception) { Debug.WriteLine("Unable to extract index number from frame type: "+name); throw; } }