OldBlueWater/BlueWater/Assets/Doozy/Editor/Reactor/Components/Texture2DAnimationInfo.cs
2023-08-02 15:08:03 +09:00

326 lines
12 KiB
C#

// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using System;
using System.Collections.Generic;
using Doozy.Editor.Common.Extensions;
using Doozy.Editor.EditorUI;
using Doozy.Editor.EditorUI.Components;
using Doozy.Editor.EditorUI.Utils;
using Doozy.Editor.Reactor.Internal;
using Doozy.Runtime.Colors;
using Doozy.Runtime.Common.Extensions;
using Doozy.Runtime.Reactor.Extensions;
using Doozy.Runtime.Reactor.Reactions;
using Doozy.Runtime.UIElements.Extensions;
using UnityEditor;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UIElements;
using EditorStyles = Doozy.Editor.EditorUI.EditorStyles;
using Object = UnityEngine.Object;
// ReSharper disable MemberCanBePrivate.Global
namespace Doozy.Editor.Reactor.Components
{
/// <summary> Texture2D Animation Info VisualElement </summary>
public class Texture2DAnimationInfo : VisualElement, IDisposable
{
public TemplateContainer templateContainer { get; }
public VisualElement layoutContainer { get; }
public VisualElement content { get; }
public Image previewImageContainer { get; }
public Image previewImage { get; }
public VisualElement detailsContainer { get; }
public Label animationName { get; }
public Label numberOfFrames { get; }
public Label textureSize { get; }
public VisualElement playerContainer { get; }
public Label pathLabel { get; }
public Texture2DReaction reaction { get; private set; }
public FluidButton playForwardButton { get; private set; }
public FluidButton playReversedButton { get; private set; }
public FluidButton setTextureButton { get; private set; }
public Slider playerSlider { get; private set; }
public SerializedProperty arrayProperty { get; }
public Texture2D spriteSheet
{
get;
set;
}
public int frameCount => arrayProperty?.arraySize ?? 0;
public Texture2D firstTexture
{
get
{
if (frameCount <= 0)
return null;
Object objectReferenceValue = arrayProperty.GetArrayElementAtIndex(0).objectReferenceValue;
return (Texture2D)objectReferenceValue;
}
}
private const float PLAYER_SPACING = DesignUtils.k_Spacing * 0.5f;
public UnityAction<Texture2D> textureSetter { get; set; }
public void Dispose()
{
reaction?.Recycle();
playForwardButton?.Recycle();
playReversedButton?.Recycle();
setTextureButton?.Recycle();
}
public Texture2DAnimationInfo(SerializedProperty arrayProperty, Texture2D spriteSheet)
{
this.arrayProperty = arrayProperty;
this.spriteSheet = spriteSheet;
Add(templateContainer = EditorLayouts.Reactor.AnimationInfo.CloneTree());
templateContainer
.AddStyle(EditorStyles.Reactor.AnimationInfo);
layoutContainer = templateContainer.Q<VisualElement>(nameof(layoutContainer));
content = layoutContainer.Q<VisualElement>(nameof(content));
previewImageContainer = content.Q<Image>(nameof(previewImageContainer));
previewImage = previewImageContainer.Q<Image>(nameof(previewImage));
detailsContainer = content.Q<VisualElement>(nameof(detailsContainer));
animationName = detailsContainer.Q<Label>(nameof(animationName));
numberOfFrames = detailsContainer.Q<Label>(nameof(numberOfFrames));
textureSize = detailsContainer.Q<Label>(nameof(textureSize));
playerContainer = detailsContainer.Q<VisualElement>(nameof(playerContainer));
pathLabel = layoutContainer.Q<Label>(nameof(pathLabel));
layoutContainer
.SetStyleBackgroundColor(EditorColors.Default.FieldBackground)
.SetStyleBorderColor(EditorColors.Default.Selection);
previewImageContainer
.SetStyleBackgroundImage(EditorTextures.EditorUI.Placeholders.TransparencyGrid)
.SetStyleBackgroundImageTintColor(Color.gray.WithAlpha(0.5f));
numberOfFrames
.SetStyleColor(EditorColors.Default.TextDescription)
.SetStyleUnityFont(EditorFonts.Inter.Light);
textureSize
.SetStyleColor(EditorColors.Default.TextDescription)
.SetStyleUnityFont(EditorFonts.Inter.Light);
pathLabel
.SetStyleColor(EditorColors.Default.TextDescription)
.SetStyleUnityFont(EditorFonts.Inter.Regular);
previewImageContainer.RegisterCallback<MouseEnterEvent>(evt =>
{
if (reaction == null) return;
if (reaction.isActive) return;
reaction.Play();
});
previewImageContainer.RegisterCallback<MouseUpEvent>(evt =>
{
if (reaction == null) return;
const int leftMouseButton = 0;
const int rightMouseButton = 1;
switch (evt.button)
{
case leftMouseButton:
reaction.Play(); //play forward
break;
case rightMouseButton:
reaction.Play(true); //play in reverse
break;
}
});
VisualElement controlsLine =
new VisualElement()
.SetStyleFlexDirection(FlexDirection.Row)
.SetStylePadding(PLAYER_SPACING);
playerContainer
.AddChild(controlsLine);
playerSlider =
new Slider(0f, 1f)
.SetStyleFlexGrow(1)
.SetStyleMargins(PLAYER_SPACING)
.SetStylePadding(0);
playerSlider.RegisterValueChangedCallback(evt =>
{
if (reaction == null) return;
if (reaction.isActive) return;
reaction?.SetFrameAtProgress(Mathf.Clamp01(evt.newValue));
UpdateFramesLabel();
});
playerSlider.RegisterCallback<MouseDownEvent>(evt =>
{
if (reaction == null) return;
if (!reaction.isActive) return;
reaction?.Stop();
});
Update();
playForwardButton =
FluidButton.Get()
.SetIcon(EditorSpriteSheets.EditorUI.Icons.PlayForward)
.SetAccentColor(EditorSelectableColors.EditorUI.LightGreen)
.SetTooltip("Play Forward")
.SetElementSize(ElementSize.Small)
.SetButtonStyle(ButtonStyle.Clear)
.SetOnClick(() => reaction?.Play()); //play forward
playReversedButton =
FluidButton.Get()
.SetIcon(EditorSpriteSheets.EditorUI.Icons.PlayReverse)
.SetAccentColor(EditorSelectableColors.EditorUI.LightGreen)
.SetTooltip("Play Reversed")
.SetElementSize(ElementSize.Small)
.SetButtonStyle(ButtonStyle.Clear)
.SetOnClick(() => reaction?.Play(true)); //play in reverse
setTextureButton =
FluidButton.Get()
.SetIcon(EditorSpriteSheets.EditorUI.Icons.Texture)
.SetAccentColor(EditorSelectableColors.EditorUI.LightGreen)
.SetTooltip("Set Texture")
.SetLabelText("Set Texture")
.SetElementSize(ElementSize.Small)
.SetButtonStyle(ButtonStyle.Contained)
.SetStyleMarginLeft(PLAYER_SPACING)
.SetOnClick(() =>
{
if (reaction == null) return;
if (reaction.current == null) return;
if (textureSetter == null) return;
textureSetter.Invoke(AssetDatabase.LoadAssetAtPath<Texture2D>(AssetDatabase.GetAssetPath(reaction.current)));
}); //set texture2D
controlsLine
.AddChild(playForwardButton)
.AddChild(playerSlider.SetStyleMarginLeft(PLAYER_SPACING))
.AddChild(playReversedButton)
.AddChild(setTextureButton);
}
public void Update()
{
var textures = new List<Texture2D>();
if (spriteSheet != null) textures = spriteSheet.GetTextures();
Texture2D texture = spriteSheet != null ? textures[0] : firstTexture;
int numberOfFramesCount = frameCount;
bool hasReference = texture != null;
DisplayStyle displayStyle = hasReference ? DisplayStyle.Flex : DisplayStyle.None;
previewImage.SetStyleBackgroundImage(texture);
animationName?.SetStyleDisplay(displayStyle);
playForwardButton?.SetStyleDisplay(displayStyle);
playReversedButton?.SetStyleDisplay(displayStyle);
pathLabel.SetStyleDisplay(displayStyle);
numberOfFrames.SetStyleDisplay(displayStyle);
textureSize.SetStyleDisplay(displayStyle);
if (!hasReference)
return;
numberOfFrames.SetText($"{numberOfFramesCount} Frames");
textureSize.SetText($"W: {texture.width}px\nH: {texture.height}px");
string assetPath = AssetDatabase.GetAssetPath(texture);
if (spriteSheet == null)
{
string[] splitPath = assetPath.Split('/');
assetPath = string.Empty;
for (int i = 0; i < splitPath.Length - 1; i++)
{
bool lastItem = i == splitPath.Length - 2;
assetPath += $"{splitPath[i]}/";
}
assetPath = assetPath.RemoveLastCharacter();
animationName.SetText($"{splitPath[splitPath.Length - 2]}");
}
else
{
animationName.SetText($"{spriteSheet.name}");
}
pathLabel.SetText($"{assetPath}");
if (spriteSheet == null)
{
textures.Clear();
for (int i = 0; i < arrayProperty.arraySize; i++)
{
Object objectReferenceValue = arrayProperty.GetArrayElementAtIndex(i).objectReferenceValue;
if (objectReferenceValue == null) continue;
textures.Add((Texture2D)objectReferenceValue);
}
}
reaction?.Recycle();
reaction = GetAnimation(previewImage, textures);
reaction.OnPlayCallback += () =>
{
UpdateSliderValue();
UpdateFramesLabel();
};
reaction.OnStopCallback += () =>
{
UpdateSliderValue();
UpdateFramesLabel();
};
reaction.OnUpdateCallback += () =>
{
UpdateFramesLabel();
if (!reaction.isActive)
return;
UpdateSliderValue();
};
}
public Texture2DAnimationInfo HideSetTextureButton(bool hide)
{
setTextureButton?.SetStyleDisplay(hide ? DisplayStyle.None : DisplayStyle.Flex);
return this;
}
private void UpdateFramesLabel()
{
numberOfFrames.text =
reaction == null
? "-/- Frames"
: $"{reaction.currentFrame + 1}/{reaction.numberOfFrames} Frames";
}
private void UpdateSliderValue()
{
playerSlider.value = reaction.progress;
playerSlider.MarkDirtyRepaint();
}
private static Texture2DReaction GetAnimation(VisualElement previewImage, IEnumerable<Texture2D> textures) =>
previewImage.GetTexture2DReaction(textures).SetEditorHeartbeat();
}
}