using UnityEditor; using UnityEngine; using System.Collections.Generic; using UnityEngine.UIElements; using UnityEditor.UIElements; namespace Unity.Cinemachine.Editor { [CustomEditor(typeof(CinemachineMixingCamera))] class CinemachineMixingCameraEditor : UnityEditor.Editor { CinemachineMixingCamera Target => target as CinemachineMixingCamera; static string WeightPropertyName(int i) => "Weight" + i; public override VisualElement CreateInspectorGUI() { var ux = new VisualElement(); this.AddCameraStatus(ux); this.AddTransitionsSection(ux); ux.AddHeader("Global Settings"); this.AddGlobalControls(ux); ux.AddSpace(); ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.DefaultTarget))); ux.AddHeader("Child Camera Weights"); List weights = new (); for (int i = 0; i < CinemachineMixingCamera.MaxCameras; ++i) weights.Add(ux.AddChild(new PropertyField(serializedObject.FindProperty(WeightPropertyName(i))))); var noChildrenHelp = ux.AddChild(new HelpBox("There are no CinemachineCamera children", HelpBoxMessageType.Warning)); var noWeightHelp = ux.AddChild(new HelpBox("No input channels are active", HelpBoxMessageType.Warning)); var container = ux.AddChild(new VisualElement()); container.AddHeader("Mix Result"); container.Add(new IMGUIContainer(() => { float totalWeight = 0; var children = Target.ChildCameras; int numCameras = Mathf.Min(CinemachineMixingCamera.MaxCameras, children.Count); for (int i = 0; i < numCameras; ++i) if (children[i].isActiveAndEnabled) totalWeight += Target.GetWeight(i); DrawProportionIndicator(children, numCameras, totalWeight); })); ux.AddSpace(); this.AddExtensionsDropdown(ux); ux.TrackAnyUserActivity(() => { if (Target == null) return; // object deleted var children = Target.ChildCameras; int numCameras = Mathf.Min(CinemachineMixingCamera.MaxCameras, children.Count); noChildrenHelp.SetVisible(numCameras == 0); float totalWeight = 0; for (int i = 0; totalWeight == 0 && i < numCameras; ++i) if (children[i].isActiveAndEnabled) totalWeight += Target.GetWeight(i); noWeightHelp.SetVisible(numCameras > 0 && totalWeight == 0); container.SetVisible(totalWeight > 0); for (int i = 0; i < weights.Count; ++i) weights[i].SetVisible(i < numCameras); }); return ux; } void DrawProportionIndicator( List children, int numCameras, float totalWeight) { GUIStyle style = EditorStyles.centeredGreyMiniLabel; Color bkg = new Color(0.27f, 0.27f, 0.27f); // ack! no better way than this? Color fg = Color.Lerp(CinemachineCore.SoloGUIColor(), bkg, 0.8f); float totalHeight = (style.lineHeight + style.margin.vertical) * numCameras; Rect r = EditorGUILayout.GetControlRect(true, totalHeight); r.height /= numCameras; r.height -= 1; float fullWidth = r.width; for (int i = 0; i < numCameras; ++i) { float p = 0; string label = children[i].Name; if (totalWeight > UnityVectorExtensions.Epsilon) { if (children[i].isActiveAndEnabled) p = Target.GetWeight(i) / totalWeight; else label += " (disabled)"; } r.width = fullWidth * p; EditorGUI.DrawRect(r, fg); Rect r2 = r; r2.x += r.width; r2.width = fullWidth - r.width; EditorGUI.DrawRect(r2, bkg); r.width = fullWidth; EditorGUI.LabelField(r, label, style); r.y += r.height + 1; } } } }