namespace Editor; // The component list will be rebuilt on hotload, so we can safely skip [SkipHotload] public class ComponentSheetHeader : InspectorHeader { SerializedObject TargetObject { get; init; } TypeDescription TargetType { get; init; } ComponentSheet Sheet { get; set; } ControlWidget EnabledWidget { get; set; } public ComponentSheetHeader( SerializedObject target, ComponentSheet parent ) : base() { TargetObject = target; Sheet = parent; var t = target.Targets.FirstOrDefault(); TargetType = TypeLibrary.GetType( t.GetType() ); Title = TargetObject.TypeTitle; Icon = TargetObject.TypeIcon; Color = Theme.Blue; IsExpanded = Sheet.Expanded; ToolTip = GetTooltip(); IsDraggable = !target.IsMultipleTargets; TargetObject.OnPropertyFinishEdit += TargetObject_PropertyChanged; ContextMenu += FillContextMenu; var tint = TypeLibrary.GetAttribute( t.GetType() ); if ( tint is not null ) Color = Theme.GetTint( tint.Tint ); UpdateOverrideState(); var helpUrl = TypeLibrary.GetAttribute( t.GetType() ); if ( helpUrl is not null ) HelpUrl = helpUrl.Url; } protected override Widget BuildIcons() { if ( TargetObject is null ) return default; var propEnabled = TargetObject.GetProperty( "Enabled" ); if ( propEnabled is not null ) { EnabledWidget = new ComponentEnabledWidget( propEnabled ) { Tint = Color }; return EnabledWidget; } return default; } protected override bool IsTargetDisabled() { var propEnabled = TargetObject.GetProperty( "Enabled" ); if ( propEnabled is null ) return false; return !propEnabled.As.Bool; } private void TargetObject_PropertyChanged( SerializedProperty property ) { Update(); UpdateOverrideState(); } private void UpdateOverrideState() { var component = TargetObject.Targets.FirstOrDefault() as Component; if ( !component.IsValid() ) return; if ( EditorUtility.Prefabs.IsComponentAddedToInstance( component ) ) { IconOverlay = "add_circle"; } else { IconOverlay = string.Empty; } } public override void OnDestroyed() { TargetObject.OnPropertyFinishEdit -= TargetObject_PropertyChanged; base.OnDestroyed(); } public Component GetComponent() { return TargetObject?.Targets?.FirstOrDefault() as Component; } protected override void OnDragStart() { if ( Children.Any( x => x.IsPressed ) ) return; base.OnDragStart(); dragData = new ComponentHeaderDrag( this ); dragData.Data.Object = TargetObject; dragData.Execute(); } protected override void OnExpandChanged() { base.OnExpandChanged(); Sheet.SetExpanded( IsExpanded ); } void FillContextMenu( Menu menu ) { var o = menu.AddOption( "View Legacy Actions", "sentiment_very_dissatisfied" ); o.Checkable = true; o.Checked = Sheet.ViewMode == ComponentViewMode.Events; o.Toggled = b => Sheet.ViewMode = b ? ComponentViewMode.Events : ComponentViewMode.Default; menu.AddSeparator(); } string GetTooltip() { var str = ""; str += $"{TargetObject.TypeTitle}"; if ( TargetType?.BaseType is TypeDescription baseType && baseType.TargetType.IsSubclassOf( typeof( Component ) ) ) { str += $" - "; str += $"{baseType.TargetType.ToRichText()}"; } str += ""; var description = TargetType?.Description; if ( string.IsNullOrWhiteSpace( description ) ) { description = TargetObject.ParentProperty?.Description; } if ( !string.IsNullOrWhiteSpace( description ) ) { str += $"

{description}"; } return str; } } file sealed class ComponentHeaderDrag : Drag { ComponentSheetHeader Header; public ComponentHeaderDrag( ComponentSheetHeader header ) : base( header ) { Header = header; } public override void OnDestroyed() { if ( Header.IsValid() ) { Header.Update(); } base.OnDestroyed(); } } file sealed class ComponentEnabledWidget : BoolControlWidget { public ComponentEnabledWidget( SerializedProperty property ) : base( property ) { ToolTip = "Enabled"; FixedWidth = 18; FixedHeight = 18; IsDraggable = !property.Parent.IsMultipleTargets; } protected override void OnDragStart() { base.OnDragStart(); var drag = new Drag( this ) { Data = { Object = SerializedProperty, Text = SerializedProperty.As.String } }; drag.Execute(); } }