using Godot; using Rokojori; using System.Collections.Generic; using System.Linq; namespace Rokojori { [Tool] [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIImage.svg")] public partial class UIImage:TextureRect, UIStylePropertyContainerNode, UIHolderControl, IAssemblyReload { UIImageType _imageType; [Export] public UIImageType imageType { get => _imageType; set { if ( _imageType != value ) { if ( _imageType != null ) { _imageType.Clear( this ); } } _imageType = value; UpdateImageType(); } } UI ui; public void SetUI( UI ui, bool computeDepth = true ) { this.ui = ui; if ( computeDepth ) { ComputeUIAncestorDepth(); } } public UI GetUI( bool computeDepth = true ) { if ( this.ui != null ) { return this.ui; } var ui = this.FindParentThatIs(); if ( ui == null ) { this._uiAncestorDepth = -1; this.LogInfo( "No UI in parents >", ui ); return null; } if ( computeDepth ) { ComputeUIAncestorDepth(); } return ui; } void UpdateImageType() { ResetImageType(); if ( _imageType != null ) { // this.LogInfo( "Assigning Image Type:", _imageType ); _imageType.Assign( this ); } } string hoverID = IDGenerator.GenerateID(); public override void _Ready() { MouseEntered += ()=> { AddUISelectorFlag( UISelectorFlag.Hover, hoverID ); this.SetDirty(); }; MouseExited += ()=> { RemoveUISelectorFlag( UISelectorFlag.Hover, hoverID ); this.SetDirty(); }; UpdateImageType(); ComputeUIAncestorDepth(); } public override void _EnterTree() { UpdateImageType(); ComputeUIAncestorDepth(); } public override void _ExitTree() { _uiAncestorDepth = -1; } public void OnAssemblyReloaded() { UpdateImageType(); } int _uiAncestorDepth; public void ComputeUIAncestorDepth() { SetUIAncestorDepth( NodesWalker.Get().GetAncestorDistance( this, GetUI( false ) ) ); } public void SetUIAncestorDepth( int depth ) { _uiAncestorDepth = depth; } public int GetUIAncestorDepth() { return _uiAncestorDepth; } void ResetImageType() { ExpandMode = TextureRect.ExpandModeEnum.IgnoreSize; StretchMode = TextureRect.StretchModeEnum.Scale; Material = null; } protected override void Dispose( bool disposing) { _selectorFlagReferenceCounter.Clear(); } MapList _selectorFlagReferenceCounter = new MapList(); public void AddUISelectorFlag( UISelectorFlag flag, string reference = "" ) { SetSelectorFlagReference( flag, reference, true ); } public void RemoveUISelectorFlag( UISelectorFlag flag, string reference = "" ) { SetSelectorFlagReference( flag, reference, false ); } void SetSelectorFlagReference( UISelectorFlag flag, string reference, bool enable ) { if ( enable ) { _selectorFlagReferenceCounter.AddIfNotPresent( flag, reference ); } else { _selectorFlagReferenceCounter.Remove( flag, reference ); } var numFlagsBefore = _selectorFlags.Count; _selectorFlags = _selectorFlagReferenceCounter.Keys.ToList(); var changed = numFlagsBefore != _selectorFlags.Count; UISelector.UpdateParentUISelectorFlags( this ); if ( changed ) { // this.LogInfo( "Changed flag:", flag, reference ); this.SetDirty(); } } List _selectorFlags = []; List _parentSelectorFlags = []; public List GetUISelectorFlags() { return _selectorFlags; } public List GetParentUISelectorFlags() { return _parentSelectorFlags; } public void CopyNumberShaderPropertyFrom( CustomMaterialProperty name, UINumber number, TransitionSettings transition ) { SetNumberShaderProperty( name.GetPropertyName(), number, transition ); } public void SetNumberShaderProperty( FloatPropertyName name, UINumber number, TransitionSettings transition ) { if ( name == null || name.propertyName == null ) { this.LogInfo( "Name is null" ); return; } for ( int i = 0; i < numberProperties.Length; i++ ) { if ( numberProperties[ i ] == null || numberProperties[ i ].floatPropertyName == null ) { return; } } if ( number == null ) { var index = Arrays.FindIndex( numberProperties, p => p.floatPropertyName.propertyName == name.propertyName ); numberProperties = Arrays.RemoveIndex( numberProperties, index ); return; } var shaderUINumber = Arrays.Find( numberProperties, p => p.floatPropertyName.propertyName == name.propertyName ); if ( shaderUINumber == null ) { shaderUINumber = new ShaderUINumber(); shaderUINumber.floatPropertyName = name; numberProperties = Arrays.AddEntry( numberProperties, shaderUINumber ); } shaderUINumber.number = number; } public void CopyColorShaderPropertyFrom( CustomMaterialProperty name, UIColor color ) { SetColorShaderProperty( name.GetPropertyName(), color ); } public void SetColorShaderProperty( ColorPropertyName name, UIColor color ) { if ( name == null || name.propertyName == null ) { this.LogInfo( "Name is null" ); return; } for ( int i = 0; i < colorProperties.Length; i++ ) { if ( colorProperties[ i ] == null || colorProperties[ i ].colorPropertyName == null ) { return; } } if ( color == null ) { var index = Arrays.FindIndex( colorProperties, p => p != null && p.colorPropertyName.propertyName == name.propertyName ); colorProperties = Arrays.RemoveIndex( colorProperties, index ); return; } var shaderUIColor = Arrays.Find( colorProperties, p => p != null && p.colorPropertyName.propertyName == name.propertyName ); if ( shaderUIColor == null ) { shaderUIColor = new ShaderUIColor(); shaderUIColor.colorPropertyName = name; colorProperties = Arrays.AddEntry( colorProperties, shaderUIColor ); } shaderUIColor.color = color; } [Export] public UIStyle parentStyle; [ExportGroup("Size & Margins")] [Export] public UINumber width; [Export] public UINumber height; [Export] public UINumber margin; [Export] public UINumber marginLeft; [Export] public UINumber marginTop; [Export] public UINumber marginRight; [Export] public UINumber marginBottom; [ExportGroup( "Position" )] [Export] public UIPosition position; [Export] public UILineWrap lineWrap; [Export] public UINumber left; [Export] public UINumber top; [Export] public UINumber right; [Export] public UINumber bottom; [ExportGroup( "Rotation & Scale" )] [Export] public UINumber pivotX; [Export] public UINumber pivotY; [Export] public UINumber rotation; [Export] public UINumber scale; [Export] public UINumber scaleX; [Export] public UINumber scaleY; [ExportGroup( "Shader Properties" )] [Export] public ShaderUIColor[] colorProperties = new ShaderUIColor[ 0 ]; // public List> activeShaderColorTransitions = new List>(); // public List> GetActiveShaderUIColorTransitions() // { // return activeShaderColorTransitions; // } [Export] public ShaderUINumber[] numberProperties = new ShaderUINumber[ 0 ]; // public List> activeShaderNumberTransitions = new List>(); // public List> GetActiveShaderUINumberTransitions() // { // return activeShaderNumberTransitions; // } [ExportGroup("Transitions")] [Export] public TransitionSettingsAll transitionSettings; public TransitionSettingsAll GetTransitionSettingsAll() { return transitionSettings; } [Export] public UINumberTransition[] numberTransitions = new UINumberTransition[0]; public UINumberTransition[] GetNumberTransitions() { return numberTransitions; } public List> activeNumberTransitions = new List>(); public List> GetActiveUINumberTransitions() { return activeNumberTransitions; } [Export] public UIColorTransition[] colorTransitions = new UIColorTransition[ 0 ]; public UIColorTransition[] GetColorTransitions() { return colorTransitions; } public List> activeColorTransitions = new List>(); public List> GetActiveUIColorTransitions() { return activeColorTransitions; } public UIStyle GetUIStyleParent() { return parentStyle; } public UIPosition GetUIPosition() { return position; } public UILineWrap GetUILineWrap() { return lineWrap; } public UILayout GetUILayout() { return UILayout.___; } public ShaderUIColor[] GetShaderUIColors() { return colorProperties; } public ShaderUINumber[] GetShaderUINumbers() { return numberProperties; } public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property, string shaderPropertyName, UIStylePropertyContainer source ) { switch ( property ) { case UIStyleNumberProperty.Width: return width; case UIStyleNumberProperty.Height: return height; case UIStyleNumberProperty.Margin: return margin; case UIStyleNumberProperty.MarginLeft: return marginLeft; case UIStyleNumberProperty.MarginRight: return marginRight; case UIStyleNumberProperty.MarginTop: return marginTop; case UIStyleNumberProperty.MarginBottom: return marginBottom; case UIStyleNumberProperty.Left: return left; case UIStyleNumberProperty.Right: return right; case UIStyleNumberProperty.Top: return top; case UIStyleNumberProperty.Bottom: return bottom; case UIStyleNumberProperty.PivotX: return pivotX; case UIStyleNumberProperty.PivotY: return pivotY; case UIStyleNumberProperty.Rotation: return rotation; case UIStyleNumberProperty.Scale: return scale; case UIStyleNumberProperty.ScaleX: return scaleX; case UIStyleNumberProperty.ScaleY: return scaleY; } if ( UIStyleNumberProperty.FloatShaderProperty == property ) { var numberProperty = numberProperties.Find( n => n.floatPropertyName.propertyName == shaderPropertyName ); if ( numberProperty != null ) { return numberProperty.number; } } return null; } public void SetUIStyleNumberProperty( UIStyleNumberProperty property, UINumber number ) { switch ( property ) { case UIStyleNumberProperty.Left: { left = number; } break; case UIStyleNumberProperty.Right: { right = number; } break; case UIStyleNumberProperty.Top: { top = number; } break; case UIStyleNumberProperty.Bottom: { bottom = number; } break; case UIStyleNumberProperty.Width: { width = number; } break; case UIStyleNumberProperty.Height: { height = number; } break; case UIStyleNumberProperty.Margin: { margin = number; } break; case UIStyleNumberProperty.MarginLeft: { marginLeft = number; } break; case UIStyleNumberProperty.MarginRight: { marginRight = number; } break; case UIStyleNumberProperty.MarginTop: { marginTop = number; } break; case UIStyleNumberProperty.MarginBottom: { marginBottom = number; } break; case UIStyleNumberProperty.PivotX: { pivotX = number; } break; case UIStyleNumberProperty.PivotY: { pivotY = number; } break; case UIStyleNumberProperty.Rotation: { rotation = number; } break; case UIStyleNumberProperty.Scale: { scale = number; } break; case UIStyleNumberProperty.ScaleX: { scaleX = number; } break; case UIStyleNumberProperty.ScaleY: { scaleY = number; } break; } this.SetLayoutDirtyFlag(); } bool _isAnimated = false; int _isLayoutDirty = 3; public void ResetDirtyFlags() { _isAnimated = false; _isLayoutDirty = Mathf.Max( 0, _isLayoutDirty - 1 ); } public void SetAnimatedFlag() { _isAnimated = true; this.SetDirty(); } public void SetLayoutDirtyFlag() { _isLayoutDirty = 3; this.SetDirty(); } public bool IsDirty() { return _isAnimated || _isLayoutDirty != 0 || this.HasActiveTransitions(); } public void Update() { if ( Texture == null ) { Size = new Vector2( 0, 0 ); return; } var tw = Texture.GetWidth(); var th = Texture.GetHeight(); var w = UINumber.Compute( this, UIStyleNumberProperty.Width, tw, tw / 100f ); var h = UINumber.Compute( this, UIStyleNumberProperty.Height, th, th / 100f ); Size = new Vector2( w, h ); if ( Material == null ) { return; } var ui = GetUI(); if ( ui == null || ui.settings == null || ui.settings.sizePropertyName == null ) { return; } ui.settings.sizePropertyName.Set( Material, Size ); var colorProperties = imageType != null ? imageType.GetColorShaderProperties() : []; var colorPropertyName = new ColorPropertyName(); foreach ( var c in colorProperties ) { var color = UIColor.Compute( this, UIStyleColorProperty.ColorShaderProperty, c, Colors.White ); colorPropertyName.propertyName = c; colorPropertyName.Set( Material, color ); } var numberProperties = imageType != null ? imageType.GetNumberShaderProperties() : []; var numberPropertyName = new FloatPropertyName(); foreach ( var n in numberProperties ) { var value = UINumber.Compute( this, UIStyleNumberProperty.FloatShaderProperty, n ); numberPropertyName.propertyName = n; numberPropertyName.Set( Material, value ); } } public UIColor GetUIStyleColorProperty( UIStyleColorProperty property, string shaderPropertyName, UIStylePropertyContainer source ) { if ( property != UIStyleColorProperty.ColorShaderProperty ) { return null; } if ( imageType != null ) { var uiColor = imageType.GetUIStyleColorProperty( property, shaderPropertyName ); if ( uiColor != null ) { return uiColor; } } var shaderUIColor = colorProperties.Find( c => c.colorPropertyName.propertyName == shaderPropertyName ); return shaderUIColor != null ? shaderUIColor.color : null; } public Font GetFont() { return null; } public Vector2 GetUISize() { return GetSize(); } } }