private void animTimer_Tick(object sender, EventArgs e) { Anim anim = anims[selectedCellValue]; if (++animCurrentFrame == anim.frames.Count) { animCurrentFrame = 0; } AnimFrame frame = anim.frames[animCurrentFrame]; if (currentImage != null) { currentImage.Dispose(); } currentImage = Image.FromFile(frame.image); Invalidate(); animTimer.Interval = (int) ((anim.frames[animCurrentFrame].timeFrames * 1.0f / anim.frames[animCurrentFrame].timeRate) * 1000); animFrameLabel.Text = string.Format("Frame {0}/{1}", animCurrentFrame + 1, anim.frames.Count); }
void MoveNode(int id, Vector2 newOffset, bool snapToPixel = true) { if (m_playing) { return; } AnimFrame frame = GetCurrentFrame(); if (frame == null) { return; } Sprite sprite = GetSpriteAtTime(m_animTime); if (sprite != null && snapToPixel) { // Snap offset to sprite pixels newOffset = new Vector2(Utils.Snap(newOffset.x, 0.5f), Utils.Snap(newOffset.y, 0.5f)); } SetNodeOffsetAtFrame(frame, id, newOffset); m_nodePositions[id] = newOffset; // NB: Don't wanna apply changes while dragging, just apply on lift. So no ApplyChanges() here. }
// Sets the angle of a node on a particular anim frame, adding it if it didn't exist. void SetNodeAngleAtFrame(AnimFrame frame, int nodeId, float angle) { if (frame != null) { FindOrCreateNodeAtFrame(frame, nodeId).m_angle = Mathf.Repeat(angle, 360f); } }
// Updates the current frame's node pos/rot, if node isn't overriden on current frame it's set to last set position void UpdateCurrentFrameNodePositions() { // NB: Could cashe stuff to do this more efficiently than looping through every node every frame. int currFrame = GetCurrentFrameId(); if (currFrame < 0) { return; } // Work backwards through nodes to find the latest node with a value for (int nodeId = 0; nodeId < SpriteAnimNodes.NUM_NODES; ++nodeId) { m_nodePositions[nodeId] = Vector2.zero; m_nodeAngles[nodeId] = 0; for (int frameId = currFrame; frameId >= 0; --frameId) { Node node = null; AnimFrame frame = m_frames[frameId]; if (frame.m_nodes != null) { node = frame.m_nodes.Find(item => item.m_nodeId == nodeId); } if (node != null) { m_nodePositions[nodeId] = node.m_offset; m_nodeAngles[nodeId] = Mathf.Repeat(node.m_angle, 360f); break; // brake from inner loop } } } }
void Update() { if (Application.isPlaying) { return; } if (sa.isPlaying) { return; } if (Vector3.Distance(transform.localPosition, lastLocalPosition) > Mathf.Epsilon) { lastLocalPosition = transform.localPosition; sa.CurrentFrameIndex = Mathf.Clamp(sa.CurrentFrameIndex, 0, sa.CurrentSequence.frames.Length - 1); AnimFrame af = sa.CurrentSequence.frames[sa.CurrentFrameIndex]; AnimFramePoint afp = null; if (af.point.Count > 0) { afp = af.point.Find(x => x.name == transform.name); } if (afp == null) { afp = new AnimFramePoint(); afp.name = transform.name; af.point.Add(afp); } afp.point = transform.localPosition; print(name + " moved"); EditorUtility.SetDirty(sa.CurrentSequence); } }
void SetAnimation(string name) { if (CurrentAnimation != null && CurrentAnimation.Name == name) { return; } CurrentFrame = 0; switch (name) { case "WALK_LEFT": CurrentAnimation = WalkLeft; break; case "WALK_RIGHT": CurrentAnimation = WalkRight; break; case "WALK_FORWARD": CurrentAnimation = WalkForward; break; case "WALK_BACK": CurrentAnimation = WalkBack; break; case "IDLE": CurrentAnimation = Idle; break; } }
// Delete the node form the current frame, if there are no frames left, deletes the node void DeleteNode(int id) { if (m_playing) { return; } // check if on other frames bool onOtherFrames = false; AnimFrame currentFrame = GetCurrentFrame(); if (currentFrame == null) { return; } foreach (AnimFrame frame in m_frames) { if (frame != currentFrame && frame.m_nodes != null && frame.m_nodes.Exists(item => item.m_nodeId == id)) { onOtherFrames = true; break; } } if (onOtherFrames == false) { m_nodePositions[id] = Vector2.zero; m_nodeAngles[id] = 0; m_nodeMask = Utils.BitMask.UnsetAt(m_nodeMask, id); } currentFrame.m_nodes.RemoveAll(item => item.m_nodeId == id); ApplyChanges(); }
private void removeAnimFrameBtn_Click(object sender, EventArgs e) { Anim anim = anims[selectedCellValue]; int frameCount = anim.frames.Count; AnimFrame currentFrame = anim.frames[animCurrentFrame]; anim.frames.Remove(currentFrame); if (animCurrentFrame + 1 == frameCount) { LoadAnimFrameData(selectedCellValue, --animCurrentFrame); } else { LoadAnimFrameData(selectedCellValue, animCurrentFrame); } if (anim.frames.Count == 1) { nextAnimBtn.Enabled = false; prevAnimBtn.Enabled = false; removeAnimFrameBtn.Enabled = false; } SetChangesMade(true); }
private void animFrameImageBtn_Click(object sender, EventArgs e) { if (selectedCellValue == "") { return; } var result = loadImageFileDialog.ShowDialog(); if (result == DialogResult.OK) { animFrameImageTextBox.Text = loadImageFileDialog.FileName; if (currentImage != null) { currentImage.Dispose(); } currentImage = Image.FromFile(loadImageFileDialog.FileName); //ScaleCurrentImage(currentScale); Invalidate(); AnimFrame frame = anims[selectedCellValue].frames[animCurrentFrame]; frame.image = loadImageFileDialog.FileName; anims[selectedCellValue].frames[animCurrentFrame] = frame; SetChangesMade(true); } }
// Gets node at frame, creating it if it doesn't exist Node FindOrCreateNodeAtFrame(AnimFrame frame, int nodeId) { if (frame == null) { return(null); } Node node = null; if (frame.m_nodes == null) { frame.m_nodes = new List <Node>(1); } else { node = frame.m_nodes.Find(item => item.m_nodeId == nodeId); } if (node == null) { // Adding node first time, set it's id, and set offset/angle to whatever the cached one is (if it's set on a previous frame it'll use that). node = new Node() { m_nodeId = nodeId }; frame.m_nodes.Add(node); // Set defaults for frame (based on previous frames) InitNodeValues(node, frame); } return(node); }
private void addAnimFrameBtn_Click(object sender, EventArgs e) { Anim anim = anims[selectedCellValue]; int frameCount = anim.frames.Count; if (animCurrentFrame + 1 == frameCount) { // Add anim frame, duplicating the last one AnimFrame thisFrame = anim.frames[frameCount - 1]; anim.frames.Add(thisFrame); LoadAnimFrameData(selectedCellValue, ++animCurrentFrame); } else { // Insert anim frame, duplicating the current one AnimFrame thisFrame = anim.frames[animCurrentFrame]; anim.frames.Insert(animCurrentFrame + 1, thisFrame); LoadAnimFrameData(selectedCellValue, ++animCurrentFrame); } removeAnimFrameBtn.Enabled = true; prevAnimBtn.Enabled = true; SetChangesMade(true); }
// Sets the offset and angle of a node on a particular anim frame, adding it if it didn't exist. void SetNodeAtFrame(AnimFrame frame, int nodeId, Vector2 offset ) { Node node = FindOrCreateNodeAtFrame(frame, nodeId); if ( node == null ) return; node.m_offset = offset; }
// draws visuals for an event private void LayoutEventVisuals(AnimFrame frame, bool selected, Rect eventRect, string labelText, Rect labelRect) { // Color differently if selected var eventColor = selected ? COLOR_UNITY_BLUE : Color.grey; var eventBGColor = selected ? COLOR_EVENT_LABEL_BG_SELECTED : COLOR_EVENT_LABEL_BG; //DrawRect( new Rect(eventRect) { width = EVENT_WIDTH }, eventColor ); DrawRect(labelRect, eventBGColor); GUI.Label(new Rect(labelRect) { yMin = labelRect.yMin - 4 }, labelText, new GUIStyle(Styles.TIMELINE_EVENT_TEXT) { normal = { textColor = eventColor } }); if (selected) { GUI.color = COLOR_UNITY_BLUE; } GUI.Box(new Rect(eventRect.xMin - 2, eventRect.yMin, 6, 20), Contents.EVENT_MARKER, new GUIStyle(Styles.TIMELINE_EVENT_TICK) { normal = { textColor = eventColor } }); GUI.color = Color.white; }
private void timeFrameRateTextBox_TextChanged(object sender, EventArgs e) { if (selectedCellValue == "") { return; } int timeRate = 0; try { timeRate = timeFrameRateTextBox.Text == "" ? 1 : int.Parse(timeFrameRateTextBox.Text); } catch (FormatException) { timeRate = 0; } if (timeRate == 0) { timeFrameRateTextBox.Text = "60"; return; } AnimFrame frame = anims[selectedCellValue].frames[animCurrentFrame]; frame.timeRate = timeRate; anims[selectedCellValue].frames[animCurrentFrame] = frame; Invalidate(); timeSecsLabel.Text = string.Format("= {0:0.#####} secs", (frame.timeFrames * 1.0f / timeRate)); SetChangesMade(true); }
void LoadAnimFrameData(string animName, int frameId) { if (!anims.ContainsKey(animName)) { return; } Anim anim = anims[animName]; if (frameId >= anim.frames.Count || frameId < 0) { return; } animCurrentFrame = frameId; AnimFrame frame = anim.frames[frameId]; animFrameLabel.Text = string.Format("Frame {0}/{1}", frameId + 1, anim.frames.Count); timeSecsLabel.Text = string.Format("= {0:0.#####} secs", (frame.timeFrames * 1.0f / frame.timeRate)); centerXTextBox.Text = frame.centerX.ToString(); centerYTextBox.Text = frame.centerY.ToString(); sizeXTextBox.Text = frame.sizeX.ToString(); sizeYTextBox.Text = frame.sizeY.ToString(); timeFrameCntTextBox.Text = frame.timeFrames.ToString(); timeFrameRateTextBox.Text = frame.timeRate.ToString(); animFrameImageTextBox.Text = frame.image; // No image associated - don't continue if (frame.image == "") { if (currentImage != null) { currentImage.Dispose(); } currentImage = null; Invalidate(); return; } if (!File.Exists(frame.image)) { MessageBox.Show("The image file associated with " + "this frame cannot be found:\n\n" + frame.image, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); animFrameImageTextBox.Text = ""; } if (currentImage != null) { currentImage.Dispose(); } currentImage = Image.FromFile(frame.image); Invalidate(); }
void LayoutAnimationNodesPanel(Rect rect) { UpdateCurrentFrameNodePositions(); Event e = Event.current; AnimFrame currentFrame = GetCurrentFrame(); // // Draw Nodes - back to front (selected at front) // for (int i = 0; i < SpriteAnimNodes.NUM_NODES; ++i) { if (i != m_selectedNode) { LayoutNode(rect, i, currentFrame); } } if (m_selectedNode >= 0) { LayoutNode(rect, m_selectedNode, currentFrame); } // // Handle node events - front to back (selected last) // if (m_selectedNode >= 0) { HandleNodeEvents(rect, m_selectedNode, e); } for (int i = SpriteAnimNodes.NUM_NODES - 1; i >= 0; --i) { if (i != m_selectedNode) { HandleNodeEvents(rect, i, e); } } // // Check for double click to add node // if (m_playing == false && e.button == 0 && e.type == EventType.MouseDown && rect.Contains(e.mousePosition) && m_dragState == eDragState.None) { if (m_selectedNode >= 0) { ClearSelection(); GUI.FocusControl("none"); e.Use(); } if (e.clickCount == 2 && GetUnusedNodeId() >= 0) { // Double clicked, add new node at position, with the cached angle from the last set frame AddNode((e.mousePosition - rect.center - m_previewOffset) / m_previewScale); GUI.FocusControl("none"); e.Use(); } } }
private void OnGUI() { _animation = (Animation)EditorGUILayout.ObjectField("模型:", _animation, typeof(Animation), false); if (_animation == null) { EditorGUILayout.HelpBox("请选择带有Animation组件的prefab", MessageType.Error); return; } GUILayout.Space(5); GUILayout.Label("动画列表:"); int index = 0; foreach (AnimationState a in _animation) { EditorGUILayout.BeginHorizontal(); { bool isSelect = _selectSet.Contains(a.name); bool newState = EditorGUILayout.Toggle(isSelect); if (isSelect != newState) { if (!newState) { _selectSet.Remove(a.name); } else { _selectSet.Add(a.name); } } EditorGUILayout.ObjectField(a.clip, typeof(AnimationClip), false); } EditorGUILayout.EndHorizontal(); index++; } GUILayout.Space(5); if (index == 0) { EditorGUILayout.HelpBox("动画列表为空!", MessageType.Error); return; } GUILayout.Space(5); _animFrame = (AnimFrame)EditorGUILayout.EnumPopup("动画帧率:", _animFrame); GUILayout.Space(5); if (GUILayout.Button("导出动画数据")) { string dir = EditorUtility.SaveFolderPanel("导出动画数据", "", ""); if (!string.IsNullOrEmpty(dir)) { dir = dir.Replace("\\", "/"); if (!dir.StartsWith(Application.dataPath)) { return; } dir = dir.Replace(Application.dataPath, "Assets"); ExportAnim(dir); } } }
private void SetFrameLength(AnimFrame frame, float length) { if (Mathf.Approximately(length, frame.RealLength) == false) { frame.RealLength = MathEx.Max(GetFrameTime(), SnapTimeToFrameRate(length)); RecalcFrameTimes(); } }
public void SetFrame(AnimFrame frameID) { switch (frameID) { case AnimFrame.DUCK: frame = new Rectangle(70, 0, 35, 50); animationCount = 0; break; case AnimFrame.STAND: frame = new Rectangle(0, 0, 35, 100); animationCount = 0; break; case AnimFrame.LEFT: if (animationCount <= 0) { animationCount = 150; if (this.frameID == AnimFrame.LEFT && frame.X == 175) { frame = new Rectangle(245, 0, -70, 100); } else { frame = new Rectangle(175, 0, -70, 100); } } break; case AnimFrame.RIGHT: animationCount = 150; if (this.frameID == AnimFrame.RIGHT && frame.X == 105) { frame = new Rectangle(175, 0, 70, 100); } else { frame = new Rectangle(105, 0, 70, 100); } break; case AnimFrame.JUMP: frame = new Rectangle(35, 0, 35, 100); animationCount = 0; break; case AnimFrame.PUNCH_LEFT: frame = new Rectangle(315, 0, -70, 100); animationCount = 200; break; case AnimFrame.PUNCH_RIGHT: frame = new Rectangle(245, 0, 70, 100); animationCount = 200; break; } this.frameID = frameID; }
// Sets the y offset of a node on a particular anim frame, adding it if it didn't exist. void SetNodeYAtFrame(AnimFrame frame, int nodeId, float value) { Node node = FindOrCreateNodeAtFrame(frame, nodeId); if (node != null) { node.m_offset = new Vector2(node.m_offset.x, value); } }
void LayoutFrameListFrame(Rect rect, int index, bool isActive, bool isFocused) { if (m_frames == null || index < 0 || index >= m_frames.Count) { return; } AnimFrame frame = m_frames[index]; EditorGUI.BeginChangeCheck(); rect = new Rect(rect) { height = rect.height - 4, y = rect.y + 2 }; // frame ID float xOffset = rect.x; float width = Styles.INFOPANEL_LABEL_RIGHTALIGN.CalcSize(new GUIContent(index.ToString())).x; EditorGUI.LabelField(new Rect(rect) { x = xOffset, width = width }, index.ToString(), Styles.INFOPANEL_LABEL_RIGHTALIGN); // Frame Sprite xOffset += width + 5; width = (rect.xMax - 5 - 28) - xOffset; // Sprite thingy Rect spriteFieldRect = new Rect(rect) { x = xOffset, width = width, height = 16 }; frame.m_sprite = EditorGUI.ObjectField(spriteFieldRect, frame.m_sprite, typeof(Sprite), false) as Sprite; // Frame length (in samples) xOffset += width + 5; width = 28; GUI.SetNextControlName("FrameLen"); int frameLen = Mathf.RoundToInt(frame.m_length / GetMinFrameTime()); frameLen = EditorGUI.IntField(new Rect(rect) { x = xOffset, width = width }, frameLen); SetFrameLength(frame, frameLen * GetMinFrameTime()); if (EditorGUI.EndChangeCheck()) { // Apply events ApplyChanges(); } }
// Sets the y offset of a node on a particular anim frame, adding it if it didn't exist. void SetNodeYAtFrame(AnimFrame frame, int nodeId, float value) { Node node = FindOrCreateNodeAtFrame(frame, nodeId); // if (value == 0 && onLoad == false ) - This function is only called on load // value = 0.0001f; // Zero nodes are stripped, so when setting to zero, actually set to a real low value if (node != null) { node.m_offset = new Vector2(node.m_offset.x, value); } }
public void AddFrame(Vector3 Position, Quaternion Rotation, float Time) { var Frame = new AnimFrame(); Frame.Position = Position; Frame.Rotation = Rotation; Frame.Scale = Vector3.one; Frame.Time = Time; Pop.AllocIfNull(ref Frames); Frames.Add(Frame); }
private void starButton5_ClickButton(object sender, EventArgs e) { BrowseFile.ShowDialog(); foreach (var f in BrowseFile.FileNames) { var af = new AnimFrame(); af.RawFrame = new Bitmap(f); EditAnim.Frames.Add(af); } SyncFrames(); SyncAnimBox(); }
/// Handles selection a single frame on timeline and list, and puts playhead at start private void SelectFrame(AnimFrame selectedFrame) { var ctrlClick = Event.current.control; var shiftClick = Event.current.shift && _selectedFrames.Count == 1; // Can only shift click if 1 is selected already // Clear existing events unless ctrl is clicked, or we're select dragging if (ctrlClick == false && shiftClick == false) { _selectedFrames.Clear(); } //_selectedEvents.Clear(); // Don't add if already in selection list, and if holding ctrl remove it from the list if (_selectedFrames.Contains(selectedFrame) == false) { if (shiftClick) { // Add frames between selectd and clicked. var indexFrom = _frames.FindIndex(item => item == _selectedFrames[0]); var indexTo = _frames.FindIndex(item => item == selectedFrame); if (indexFrom > indexTo) { Utils.Swap(ref indexFrom, ref indexTo); } for (var i = indexFrom + 1; i < indexTo; ++i) { _selectedFrames.Add(_frames[i]); } } _selectedFrames.Add(selectedFrame); if (ctrlClick == false) { _framesReorderableList.index = _frames.FindIndex(item => item == selectedFrame); // Put playhead at beginning of selected frame (if not playing) if (_playing == false) { _animTime = selectedFrame.Time; } } } else if (ctrlClick) { _selectedFrames.Remove(selectedFrame); } // Sort selection _selectedFrames.Sort((a, b) => a.Time.CompareTo(b.Time)); }
// Handles gui events for an event private void LayoutEventGuiEvents(Rect rect, AnimFrame frame, bool selected, Rect eventRect, string labelText, Rect labelRect) { var eventClickRect = new Rect(eventRect) { xMin = eventRect.xMin + EVENT_CLICK_OFFSET, width = EVENT_CLICK_WIDTH }; // // Frame clicking events // //var e = Event.current; //var mouseContained = eventClickRect.Contains(e.mousePosition) || labelRect.Contains(e.mousePosition); // Can click on either label or event bar // Move cursor (when selected, it can be dragged to move it) EditorGUIUtility.AddCursorRect(eventClickRect, MouseCursor.MoveArrow); //if (_dragState == eDragState.None && mouseContained && e.button == 0) { // // // // Handle Event Selection // // // if ((selected == false || e.control) && e.type == EventType.MouseDown) { // // Started clicking unselected - start selecting // SelectEvent(frame); // GUI.FocusControl("none"); // e.Use(); // } // if (selected && e.control == false && _selectedEvents.Count > 1 && e.type == EventType.MouseUp) { // // Had multiple selected, and clicked on just one, deselect others. Done on mouse up so we can start the drag if we want // SelectEvent(frame); // GUI.FocusControl("none"); // e.Use(); // } // if (selected && e.type == EventType.MouseDown) { // GUI.FocusControl("none"); // // Clicked alredy selected item, consume event so it doesn't get deseleccted when starting a move // e.Use(); // } // // // // Handle start move frame drag // // // if (e.type == EventType.MouseDrag) { // _dragState = eDragState.MoveEvent; // } //} }
// Sets the offset of a node on a particular anim frame, adding it if it didn't exist. void SetNodeOffsetAtFrame(AnimFrame frame, int nodeId, Vector2 offset) { Node node = FindOrCreateNodeAtFrame(frame, nodeId); if (offset == Vector2.zero) { offset = new Vector2(0.0001f, 0.0001f); // Zero nodes are stripped, so when setting to zero, actually set to a real low value } if (node != null) { node.m_offset = offset; } }
void RotateNode( int id, float newAngle ) { if ( m_playing ) return; AnimFrame frame = GetCurrentFrame(); if ( frame == null ) return; SetNodeAngleAtFrame(frame, id, newAngle); m_nodeAngles[id] = Mathf.Repeat(newAngle,360); // NB: Don't wanna apply changes while dragging, just apply on lift. So no ApplyChanges() here. }
// Sets node values based on what nodes have on previous frames void InitNodeValues( Node node, AnimFrame frame ) { // Work backwards to find last node for ( int frameId = m_frames.FindIndex(item=>item == frame)-1; frameId >= 0; --frameId ) { Node prevFrameNode = null; AnimFrame prevFrame = m_frames[frameId]; if ( prevFrame.m_nodes != null ) prevFrameNode = prevFrame.m_nodes.Find(item=>item.m_nodeId == node.m_nodeId); if ( prevFrameNode != null ) { node.m_offset = prevFrameNode.m_offset; node.m_angle = prevFrameNode.m_angle; break; } } }
void SelectAnimCell(string cellName) { selectedCellValue = cellName; // Load up new anim with an empty first frame and bogus data if (!anims.ContainsKey(cellName) || anims[cellName].frames.Count == 0) { Anim newAnim = new Anim() { id = cellName, frames = new List <AnimFrame>() }; AnimFrame initFrame = new AnimFrame(); initFrame.centerX = 0; initFrame.centerY = 0; initFrame.sizeX = 0; initFrame.sizeY = 0; initFrame.timeFrames = 1; initFrame.timeRate = 60; initFrame.image = ""; newAnim.frames.Add(initFrame); anims.Add(cellName, newAnim); } Anim anim = anims[cellName]; LoadAnimFrameData(cellName, 0); animNameLabel.Text = string.Format("Name: \"{0}\"", cellName); prevAnimBtn.Enabled = false; nextAnimBtn.Enabled = anim.frames.Count > 1; addAnimFrameBtn.Enabled = true; playAnimBtn.Enabled = true; centerXTextBox.Enabled = true; centerYTextBox.Enabled = true; sizeXTextBox.Enabled = true; sizeYTextBox.Enabled = true; timeFrameCntTextBox.Enabled = true; timeFrameRateTextBox.Enabled = true; animFrameImageBtn.Enabled = true; }
void SetAnimation( string name) { if (CurrentAnimation != null && CurrentAnimation.Name == name) return; CurrentFrame = 0; switch (name) { case "WALK_LEFT": CurrentAnimation = WalkLeft; break; case "WALK_RIGHT": CurrentAnimation = WalkRight; break; case "WALK_FORWARD": CurrentAnimation = WalkForward; break; case "WALK_BACK": CurrentAnimation = WalkBack; break; case "IDLE": CurrentAnimation = Idle; break; } }
public void BuildAnimation(Texture2D texture, int numRows, int numColumns, bool loop, int[] orderOfFrames) { int row, column; AnimFrame frame; m_loop = loop; m_texture = texture; m_frames = new List<AnimFrame>(); m_totalFrames = orderOfFrames.Length; m_width = m_texture.Width / numColumns; m_height = m_texture.Height / numRows; for (int i = 0; i < m_totalFrames; i++) { frame = new AnimFrame(); row = (int)((float)orderOfFrames[i] / (float)numColumns); column = orderOfFrames[i] % numColumns; frame.m_source = new Rectangle(m_width * column, m_height * row, m_width, m_height); m_frames.Add(frame); } }