//********************************** Banshee Engine (www.banshee3d.com) **************************************************// //**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************// using System.Collections.Generic; using BansheeEngine; namespace BansheeEditor { /** @addtogroup Inspectors * @{ */ /// /// Renders an inspector for the component. /// [CustomInspector(typeof(Animation))] internal class AnimationInspector : Inspector { private GUIResourceField animationClipField = new GUIResourceField(typeof(AnimationClip), new LocEdString("Clip")); private GUIEnumField wrapModeField = new GUIEnumField(typeof(AnimWrapMode), new LocEdString("Wrap mode")); private GUIFloatField speedField = new GUIFloatField(new LocEdString("Speed")); private GUIToggleField cullingField = new GUIToggleField(new LocEdString("Culling")); private GUIToggleField overrideBoundsField = new GUIToggleField(new LocEdString("Override bounds")); private GUIVector3Field centerField = new GUIVector3Field(new LocEdString("Center")); private GUIVector3Field sizeField = new GUIVector3Field(new LocEdString("Size")); private InspectableState modifyState; /// protected internal override void Initialize() { BuildGUI(); } /// protected internal override InspectableState Refresh() { Animation animation = InspectedObject as Animation; if (animation == null) return InspectableState.NotModified; animationClipField.Value = animation.DefaultClip; wrapModeField.Value = (ulong)animation.WrapMode; speedField.Value = animation.Speed; cullingField.Value = animation.Cull; overrideBoundsField.Value = animation.UseBounds; centerField.Value = animation.Bounds.Center; sizeField.Value = animation.Bounds.Size; InspectableState oldState = modifyState; if (modifyState.HasFlag(InspectableState.Modified)) modifyState = InspectableState.NotModified; return oldState; } /// /// Recreates all the GUI elements used by this inspector. /// private void BuildGUI() { Layout.Clear(); Animation animation = InspectedObject as Animation; if (animation == null) return; animationClipField.OnChanged += x => { AnimationClip clip = Resources.Load(x); animation.DefaultClip = clip; MarkAsModified(); ConfirmModify(); }; wrapModeField.OnSelectionChanged += x => { animation.WrapMode = (AnimWrapMode)x; MarkAsModified(); ConfirmModify(); }; speedField.OnChanged += x => { animation.Speed = x; MarkAsModified(); }; speedField.OnConfirmed += ConfirmModify; speedField.OnFocusLost += ConfirmModify; cullingField.OnChanged += x => { animation.Cull = x; MarkAsModified(); ConfirmModify(); }; overrideBoundsField.OnChanged += x => { animation.UseBounds = x; MarkAsModified(); ConfirmModify(); }; centerField.OnChanged += x => { AABox bounds = animation.Bounds; Vector3 min = x - bounds.Size*0.5f; Vector3 max = x + bounds.Size*0.5f; animation.Bounds = new AABox(min, max); MarkAsModified(); }; centerField.OnConfirmed += ConfirmModify; centerField.OnFocusLost += ConfirmModify; sizeField.OnChanged += x => { AABox bounds = animation.Bounds; Vector3 min = bounds.Center - x * 0.5f; Vector3 max = bounds.Center + x * 0.5f; animation.Bounds = new AABox(min, max); MarkAsModified(); }; sizeField.OnConfirmed += ConfirmModify; sizeField.OnFocusLost += ConfirmModify; Layout.AddElement(animationClipField); Layout.AddElement(wrapModeField); Layout.AddElement(speedField); Layout.AddElement(cullingField); Layout.AddElement(overrideBoundsField); GUILayoutX boundsLayout = Layout.AddLayoutX(); boundsLayout.AddElement(new GUILabel(new LocEdString("Bounds"), GUIOption.FixedWidth(100))); GUILayoutY boundsContent = boundsLayout.AddLayoutY(); boundsContent.AddElement(centerField); boundsContent.AddElement(sizeField); // Morph shapes Renderable renderable = animation.SceneObject.GetComponent(); MorphShapes morphShapes = renderable?.Mesh?.MorphShapes; if (morphShapes != null) { GUIToggle morphShapesToggle = new GUIToggle(new LocEdString("Morph shapes"), EditorStyles.Foldout); Layout.AddElement(morphShapesToggle); GUILayoutY channelsLayout = Layout.AddLayoutY(); morphShapesToggle.OnToggled += x => { channelsLayout.Active = x; Persistent.SetBool("Channels_Expanded", x); }; channelsLayout.Active = Persistent.GetBool("Channels_Expanded"); MorphChannel[] channels = morphShapes.Channels; for (int i = 0; i < channels.Length; i++) { GUILayoutY channelLayout = channelsLayout.AddLayoutY(); GUILayoutX channelTitleLayout = channelLayout.AddLayoutX(); channelLayout.AddSpace(5); GUILayoutY channelContentLayout = channelLayout.AddLayoutY(); string channelName = channels[i].Name; GUIToggle channelNameField = new GUIToggle(channelName, EditorStyles.Expand, GUIOption.FlexibleWidth()); channelTitleLayout.AddSpace(15); // Indent channelTitleLayout.AddElement(channelNameField); channelTitleLayout.AddFlexibleSpace(); channelNameField.OnToggled += x => { channelContentLayout.Active = x; Persistent.SetBool(channelName + "_Expanded", x); }; channelContentLayout.Active = Persistent.GetBool(channelName + "_Expanded"); MorphShape[] shapes = channels[i].Shapes; for (int j = 0; j < shapes.Length; j++) { GUILayoutX shapeLayout = channelContentLayout.AddLayoutX(); channelContentLayout.AddSpace(5); LocString nameString = new LocString("[{0}]. {1}"); nameString.SetParameter(0, j.ToString()); nameString.SetParameter(1, shapes[j].Name); GUILabel shapeNameField = new GUILabel(shapes[j].Name); LocString weightString = new LocEdString("Weight: {0}"); weightString.SetParameter(0, shapes[j].Weight.ToString()); GUILabel weightField = new GUILabel(weightString); shapeLayout.AddSpace(30); // Indent shapeLayout.AddElement(shapeNameField); shapeLayout.AddFlexibleSpace(); shapeLayout.AddElement(weightField); } } } } /// /// Marks the contents of the inspector as modified. /// protected void MarkAsModified() { modifyState |= InspectableState.ModifyInProgress; } /// /// Confirms any queued modifications. /// protected void ConfirmModify() { if (modifyState.HasFlag(InspectableState.ModifyInProgress)) modifyState |= InspectableState.Modified; } } /** @} */ }