Singularity/Library/PackageCache/com.unity.2d.animation@7.0.10/Editor/SkinningModule/SpriteBoneInfluence/BoneSpriteInfluenceTool.cs
2024-05-06 11:45:45 -07:00

347 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.U2D.Layout;
namespace UnityEditor.U2D.Animation
{
internal class BoneSpriteInfluenceToolController
{
SkinningEvents m_Events;
IBoneSpriteInfluenceToolModel m_Model;
public BoneSpriteInfluenceToolController(IBoneSpriteInfluenceToolModel model, SkinningEvents events)
{
m_Events = events;
m_Model = model;
}
public void Activate()
{
m_Events.selectedSpriteChanged.AddListener(OnSpriteSelectionChanged);
m_Events.boneSelectionChanged.AddListener(OnBoneSelectionChanged);
m_Events.boneNameChanged.AddListener(OnBoneNameChanged);
m_Events.skeletonTopologyChanged.AddListener(OnSkeletonTopologyChanged);
m_Events.meshChanged.AddListener(OnMeshChanged);
m_Events.skinningModeChanged.AddListener(OnSkinningModeChanged);
ShowHideView(true);
}
public void Deactivate()
{
m_Events.selectedSpriteChanged.RemoveListener(OnSpriteSelectionChanged);
m_Events.boneSelectionChanged.RemoveListener(OnBoneSelectionChanged);
m_Events.boneNameChanged.RemoveListener(OnBoneNameChanged);
m_Events.skeletonTopologyChanged.RemoveListener(OnSkeletonTopologyChanged);
m_Events.meshChanged.RemoveListener(OnMeshChanged);
m_Events.skinningModeChanged.RemoveListener(OnSkinningModeChanged);
ShowHideView(false);
}
void OnSpriteSelectionChanged(SpriteCache sprite)
{
if (m_Model.view.visible)
{
m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
UpdateAddRemoveButtons();
}
}
void OnBoneSelectionChanged()
{
if (m_Model.view.visible)
{
UpdateSelectedBonesInfluencedSprites();
m_Model.view.UpdateList(m_Model.influencedSprites);
m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
UpdateAddRemoveButtons();
SetViewHeaderText();
}
}
void OnBoneNameChanged(BoneCache bone)
{
if (m_Model.view.visible)
{
SetViewHeaderText();
}
}
void OnSkeletonTopologyChanged(SkeletonCache skeleton)
{
if (m_Model.view.visible)
{
m_Model.view.UpdateList(m_Model.influencedSprites);
m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
}
}
void OnMeshChanged(MeshCache mesh)
{
if (m_Model.view.visible)
{
m_Model.view.UpdateList(m_Model.influencedSprites);
m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
UpdateAddRemoveButtons();
}
}
void OnSkinningModeChanged(SkinningMode skinningMode)
{
UpdateAddRemoveButtons();
}
void ShowHideView(bool show)
{
m_Model.view.SetHiddenFromLayout(!show);
if (show)
{
UpdateSelectedBonesInfluencedSprites();
m_Model.view.UpdateList(m_Model.influencedSprites);
m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
m_Model.view.listLabelText = TextContent.influencedSprites;
m_Model.view.SetTooltips(TextContent.addSpriteInfluenceTooltip, TextContent.removeSpriteInfluenceTooltip);
UpdateAddRemoveButtons();
SetViewHeaderText();
}
}
void SetViewHeaderText()
{
var headerText = m_Model.selectedBone != null ? m_Model.selectedBone.name : TextContent.noBoneSelected;
m_Model.view.headerText = headerText;
}
public void OnViewCreated()
{
m_Model.view.onAddElement += AddSelectedSpriteInfluenceToBone;
m_Model.view.onRemoveElement += RemoveSelectedSpriteInfluenceFromBone;
m_Model.view.onSelectionChanged += SelectSprite;
ShowHideView(false);
}
void AddSelectedSpriteInfluenceToBone()
{
if(m_Model.selectedSprite == null)
return;
var character = m_Model.characterSkeleton;
if (character == null)
return;
if(m_Model.influencedSprites.Contains(m_Model.selectedSprite))
return;
var characterPart = m_Model.GetSpriteCharacterPart(m_Model.selectedSprite);
var characterBones = characterPart.bones.ToList();
var selectedBone = m_Model.selectedBone;
characterBones.Add(selectedBone);
using (m_Model.UndoScope(TextContent.addSpriteInfluence))
{
characterPart.bones = characterBones.ToArray();
m_Events.characterPartChanged.Invoke(characterPart);
UpdateSelectedBonesInfluencedSprites();
m_Model.view.UpdateList(m_Model.influencedSprites);
m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
UpdateAddRemoveButtons();
}
}
void RemoveSelectedSpriteInfluenceFromBone()
{
var character = m_Model.characterSkeleton;
if (character == null)
return;
var selectedBone = m_Model.selectedBone;
var selectedSprite = m_Model.selectedSprite;
using (m_Model.UndoScope(TextContent.removeSpriteInfluence))
{
var characterPart = m_Model.GetSpriteCharacterPart(selectedSprite);
var characterBones = characterPart.bones.ToList();
characterBones.Remove(selectedBone);
characterPart.bones = characterBones.ToArray();
m_Events.characterPartChanged.Invoke(characterPart);
selectedSprite.SmoothFill();
UpdateSelectedBonesInfluencedSprites();
m_Model.view.UpdateList(m_Model.influencedSprites);
m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
UpdateAddRemoveButtons();
}
}
void SelectSprite(IEnumerable<object> selectedSprite)
{
using (m_Model.UndoScope(TextContent.spriteSelection))
{
var firstSelected = selectedSprite.FirstOrDefault();
m_Model.selectedSprite = (SpriteCache)firstSelected;
m_Events.selectedSpriteChanged.Invoke(m_Model.selectedSprite);
}
}
void UpdateSelectedBonesInfluencedSprites()
{
var selectedBone = m_Model.selectedBone;
if (selectedBone != null)
{
if (m_Model.hasCharacter)
{
var spriteList = new List<TransformCache>();
foreach (var characterPartCache in selectedBone.skinningCache.character.parts)
{
if(characterPartCache.bones.Contains(selectedBone))
spriteList.Add(characterPartCache.sprite);
}
m_Model.influencedSprites = spriteList;
}
else
{
var spriteList = new List<TransformCache>();
var sprites = selectedBone.skinningCache.GetSprites();
foreach (var sprite in sprites)
{
if(sprite.GetSkeleton().bones.Contains(selectedBone))
spriteList.Add(sprite);
}
m_Model.influencedSprites = spriteList;
}
}
else
{
m_Model.influencedSprites = new List<TransformCache>();
}
}
public bool ShouldEnableAddButton()
{
if (IsCharacterMode())
{
var hasSelectedBone = m_Model.selectedBone != null;
var selectedSprite = m_Model.selectedSprite;
var hasSelectedSprite = selectedSprite != null;
return hasSelectedBone && hasSelectedSprite && !m_Model.influencedSprites.Contains(selectedSprite);
}
return false;
}
void UpdateAddRemoveButtons()
{
m_Model.view.ToggleAddButton(ShouldEnableAddButton());
m_Model.view.ToggleRemoveButton(IsCharacterMode());
}
public bool IsCharacterMode()
{
return m_Model.hasCharacter && m_Model.skinningMode == SkinningMode.Character;
}
}
interface IBoneSpriteInfluenceToolModel
{
IInfluenceWindow view { get; }
BoneCache selectedBone { get; }
SpriteCache selectedSprite { get; set; }
List<TransformCache> influencedSprites { get; set; }
bool hasCharacter { get; }
SkinningMode skinningMode { get; }
SkeletonCache characterSkeleton { get; }
UndoScope UndoScope(string description);
CharacterPartCache GetSpriteCharacterPart(SpriteCache sprite);
}
class BoneSpriteInfluenceTool : BaseTool, IBoneSpriteInfluenceToolModel
{
BoneSpriteInfluenceToolController m_Controller;
MeshPreviewBehaviour m_MeshPreviewBehaviour = new MeshPreviewBehaviour();
InfluenceWindow m_View;
public SkeletonTool skeletonTool { get; set; }
public override IMeshPreviewBehaviour previewBehaviour => m_MeshPreviewBehaviour;
internal override void OnCreate()
{
m_Controller = new BoneSpriteInfluenceToolController(this, skinningCache.events);
}
IInfluenceWindow IBoneSpriteInfluenceToolModel.view => m_View;
BoneCache IBoneSpriteInfluenceToolModel.selectedBone => skinningCache.skeletonSelection.elements.FirstOrDefault();
SpriteCache IBoneSpriteInfluenceToolModel.selectedSprite
{
get => skinningCache.selectedSprite;
set => skinningCache.selectedSprite = value;
}
List<TransformCache> IBoneSpriteInfluenceToolModel.influencedSprites { get; set; }
bool IBoneSpriteInfluenceToolModel.hasCharacter => skinningCache.hasCharacter;
SkinningMode IBoneSpriteInfluenceToolModel.skinningMode => skinningCache.mode;
SkeletonCache IBoneSpriteInfluenceToolModel.characterSkeleton => skinningCache.character != null ? skinningCache.character.skeleton : null;
UndoScope IBoneSpriteInfluenceToolModel.UndoScope(string description)
{
return skinningCache.UndoScope(description);
}
public CharacterPartCache GetSpriteCharacterPart(SpriteCache sprite)
{
return sprite.GetCharacterPart();
}
protected override void OnActivate()
{
m_Controller.Activate();
if(skeletonTool != null)
skeletonTool.Activate();
}
protected override void OnDeactivate()
{
m_Controller.Deactivate();
if(skeletonTool != null)
skeletonTool.Deactivate();
}
public override void Initialize(LayoutOverlay layout)
{
if (m_View == null)
{
m_View = InfluenceWindow.CreateFromUxml();
m_View.SetListReorderable(false);
m_View.SetAllowMultiselect(false);
m_Controller.OnViewCreated();
}
layout.rightOverlay.Add(m_View);
}
protected override void OnGUI()
{
m_MeshPreviewBehaviour.showWeightMap = true;
m_MeshPreviewBehaviour.overlaySelected = true;
m_MeshPreviewBehaviour.drawWireframe = true;
skeletonTool.skeletonStyle = SkeletonStyles.WeightMap;
skeletonTool.mode = SkeletonMode.EditPose;
skeletonTool.editBindPose = false;
skeletonTool.DoGUI();
}
}
}