A game about forced loneliness, made by TACStudios
at master 348 lines 12 kB view raw
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using UnityEditor.U2D.Layout; 5 6namespace UnityEditor.U2D.Animation 7{ 8 internal class BoneSpriteInfluenceToolController 9 { 10 SkinningEvents m_Events; 11 IBoneSpriteInfluenceToolModel m_Model; 12 13 public BoneSpriteInfluenceToolController(IBoneSpriteInfluenceToolModel model, SkinningEvents events) 14 { 15 m_Events = events; 16 m_Model = model; 17 } 18 19 public void Activate() 20 { 21 m_Events.selectedSpriteChanged.AddListener(OnSpriteSelectionChanged); 22 m_Events.boneSelectionChanged.AddListener(OnBoneSelectionChanged); 23 m_Events.boneNameChanged.AddListener(OnBoneNameChanged); 24 m_Events.skeletonTopologyChanged.AddListener(OnSkeletonTopologyChanged); 25 m_Events.meshChanged.AddListener(OnMeshChanged); 26 m_Events.skinningModeChanged.AddListener(OnSkinningModeChanged); 27 28 ShowHideView(true); 29 } 30 31 public void Deactivate() 32 { 33 m_Events.selectedSpriteChanged.RemoveListener(OnSpriteSelectionChanged); 34 m_Events.boneSelectionChanged.RemoveListener(OnBoneSelectionChanged); 35 m_Events.boneNameChanged.RemoveListener(OnBoneNameChanged); 36 m_Events.skeletonTopologyChanged.RemoveListener(OnSkeletonTopologyChanged); 37 m_Events.meshChanged.RemoveListener(OnMeshChanged); 38 m_Events.skinningModeChanged.RemoveListener(OnSkinningModeChanged); 39 40 ShowHideView(false); 41 } 42 43 void OnSpriteSelectionChanged(SpriteCache sprite) 44 { 45 if (m_Model.view.visible) 46 { 47 m_Model.view.UpdateSelection(new TransformCache[] { m_Model.selectedSprite }); 48 UpdateAddRemoveButtons(); 49 } 50 } 51 52 void OnBoneSelectionChanged() 53 { 54 if (m_Model.view.visible) 55 { 56 UpdateSelectedBonesInfluencedSprites(); 57 m_Model.view.UpdateList(m_Model.influencedSprites); 58 m_Model.view.UpdateSelection(new TransformCache[] { m_Model.selectedSprite }); 59 UpdateAddRemoveButtons(); 60 SetViewHeaderText(); 61 } 62 } 63 64 void OnBoneNameChanged(BoneCache bone) 65 { 66 if (m_Model.view.visible) 67 { 68 SetViewHeaderText(); 69 } 70 } 71 72 void OnSkeletonTopologyChanged(SkeletonCache skeleton) 73 { 74 if (m_Model.view.visible) 75 { 76 m_Model.view.UpdateList(m_Model.influencedSprites); 77 m_Model.view.UpdateSelection(new TransformCache[] { m_Model.selectedSprite }); 78 } 79 } 80 81 void OnMeshChanged(MeshCache mesh) 82 { 83 if (m_Model.view.visible) 84 { 85 m_Model.view.UpdateList(m_Model.influencedSprites); 86 m_Model.view.UpdateSelection(new TransformCache[] { m_Model.selectedSprite }); 87 UpdateAddRemoveButtons(); 88 } 89 } 90 91 void OnSkinningModeChanged(SkinningMode skinningMode) 92 { 93 UpdateAddRemoveButtons(); 94 } 95 96 void ShowHideView(bool show) 97 { 98 m_Model.view.SetHiddenFromLayout(!show); 99 if (show) 100 { 101 UpdateSelectedBonesInfluencedSprites(); 102 m_Model.view.UpdateList(m_Model.influencedSprites); 103 m_Model.view.UpdateSelection(new TransformCache[] { m_Model.selectedSprite }); 104 m_Model.view.listLabelText = TextContent.influencedSprites; 105 m_Model.view.SetTooltips(TextContent.addSpriteInfluenceTooltip, TextContent.removeSpriteInfluenceTooltip); 106 UpdateAddRemoveButtons(); 107 SetViewHeaderText(); 108 } 109 } 110 111 void SetViewHeaderText() 112 { 113 var headerText = m_Model.selectedBone != null ? m_Model.selectedBone.name : TextContent.noBoneSelected; 114 m_Model.view.headerText = headerText; 115 } 116 117 public void OnViewCreated() 118 { 119 m_Model.view.onAddElement += AddSelectedSpriteInfluenceToBone; 120 m_Model.view.onRemoveElement += RemoveSelectedSpriteInfluenceFromBone; 121 m_Model.view.onSelectionChanged += SelectSprite; 122 123 ShowHideView(false); 124 } 125 126 void AddSelectedSpriteInfluenceToBone() 127 { 128 if (m_Model.selectedSprite == null) 129 return; 130 131 var character = m_Model.characterSkeleton; 132 133 if (character == null) 134 return; 135 136 if (m_Model.influencedSprites.Contains(m_Model.selectedSprite)) 137 return; 138 139 var characterPart = m_Model.GetSpriteCharacterPart(m_Model.selectedSprite); 140 var characterBones = characterPart.bones.ToList(); 141 var selectedBone = m_Model.selectedBone; 142 characterBones.Add(selectedBone); 143 144 using (m_Model.UndoScope(TextContent.addSpriteInfluence)) 145 { 146 characterPart.bones = characterBones.ToArray(); 147 m_Events.characterPartChanged.Invoke(characterPart); 148 149 UpdateSelectedBonesInfluencedSprites(); 150 m_Model.view.UpdateList(m_Model.influencedSprites); 151 m_Model.view.UpdateSelection(new TransformCache[] { m_Model.selectedSprite }); 152 UpdateAddRemoveButtons(); 153 } 154 } 155 156 void RemoveSelectedSpriteInfluenceFromBone() 157 { 158 var character = m_Model.characterSkeleton; 159 160 if (character == null) 161 return; 162 163 var selectedBone = m_Model.selectedBone; 164 var selectedSprite = m_Model.selectedSprite; 165 166 using (m_Model.UndoScope(TextContent.removeSpriteInfluence)) 167 { 168 var characterPart = m_Model.GetSpriteCharacterPart(selectedSprite); 169 var characterBones = characterPart.bones.ToList(); 170 characterBones.Remove(selectedBone); 171 172 characterPart.bones = characterBones.ToArray(); 173 m_Events.characterPartChanged.Invoke(characterPart); 174 175 selectedSprite.SmoothFill(); 176 177 UpdateSelectedBonesInfluencedSprites(); 178 m_Model.view.UpdateList(m_Model.influencedSprites); 179 m_Model.view.UpdateSelection(new TransformCache[] { m_Model.selectedSprite }); 180 UpdateAddRemoveButtons(); 181 } 182 } 183 184 void SelectSprite(IEnumerable<object> selectedSprite) 185 { 186 using (m_Model.UndoScope(TextContent.spriteSelection)) 187 { 188 var firstSelected = selectedSprite.FirstOrDefault(); 189 m_Model.selectedSprite = (SpriteCache)firstSelected; 190 m_Events.selectedSpriteChanged.Invoke(m_Model.selectedSprite); 191 } 192 } 193 194 void UpdateSelectedBonesInfluencedSprites() 195 { 196 var selectedBone = m_Model.selectedBone; 197 198 if (selectedBone != null) 199 { 200 if (m_Model.hasCharacter) 201 { 202 var spriteList = new List<TransformCache>(); 203 204 foreach (var characterPartCache in selectedBone.skinningCache.character.parts) 205 { 206 if (characterPartCache.bones.Contains(selectedBone)) 207 spriteList.Add(characterPartCache.sprite); 208 } 209 210 m_Model.influencedSprites = spriteList; 211 } 212 else 213 { 214 var spriteList = new List<TransformCache>(); 215 var sprites = selectedBone.skinningCache.GetSprites(); 216 foreach (var sprite in sprites) 217 { 218 if (sprite.GetSkeleton().bones.Contains(selectedBone)) 219 spriteList.Add(sprite); 220 } 221 222 m_Model.influencedSprites = spriteList; 223 } 224 } 225 else 226 { 227 m_Model.influencedSprites = new List<TransformCache>(); 228 } 229 } 230 231 public bool ShouldEnableAddButton() 232 { 233 if (IsCharacterMode()) 234 { 235 var hasSelectedBone = m_Model.selectedBone != null; 236 var selectedSprite = m_Model.selectedSprite; 237 var hasSelectedSprite = selectedSprite != null; 238 return hasSelectedBone && hasSelectedSprite && !m_Model.influencedSprites.Contains(selectedSprite); 239 } 240 241 return false; 242 } 243 244 void UpdateAddRemoveButtons() 245 { 246 m_Model.view.ToggleAddButton(ShouldEnableAddButton()); 247 m_Model.view.ToggleRemoveButton(IsCharacterMode()); 248 } 249 250 public bool IsCharacterMode() 251 { 252 return m_Model.hasCharacter && m_Model.skinningMode == SkinningMode.Character; 253 } 254 } 255 256 interface IBoneSpriteInfluenceToolModel 257 { 258 IInfluenceWindow view { get; } 259 BoneCache selectedBone { get; } 260 SpriteCache selectedSprite { get; set; } 261 List<TransformCache> influencedSprites { get; set; } 262 bool hasCharacter { get; } 263 SkinningMode skinningMode { get; } 264 SkeletonCache characterSkeleton { get; } 265 UndoScope UndoScope(string description); 266 CharacterPartCache GetSpriteCharacterPart(SpriteCache sprite); 267 } 268 269 class BoneSpriteInfluenceTool : BaseTool, IBoneSpriteInfluenceToolModel 270 { 271 BoneSpriteInfluenceToolController m_Controller; 272 MeshPreviewBehaviour m_MeshPreviewBehaviour = new MeshPreviewBehaviour(); 273 InfluenceWindow m_View; 274 275 public SkeletonTool skeletonTool { get; set; } 276 277 public override IMeshPreviewBehaviour previewBehaviour => m_MeshPreviewBehaviour; 278 279 internal override void OnCreate() 280 { 281 m_Controller = new BoneSpriteInfluenceToolController(this, skinningCache.events); 282 } 283 284 IInfluenceWindow IBoneSpriteInfluenceToolModel.view => m_View; 285 286 BoneCache IBoneSpriteInfluenceToolModel.selectedBone => skinningCache.skeletonSelection.elements.FirstOrDefault(); 287 288 SpriteCache IBoneSpriteInfluenceToolModel.selectedSprite 289 { 290 get => skinningCache.selectedSprite; 291 set => skinningCache.selectedSprite = value; 292 } 293 294 List<TransformCache> IBoneSpriteInfluenceToolModel.influencedSprites { get; set; } 295 bool IBoneSpriteInfluenceToolModel.hasCharacter => skinningCache.hasCharacter; 296 SkinningMode IBoneSpriteInfluenceToolModel.skinningMode => skinningCache.mode; 297 SkeletonCache IBoneSpriteInfluenceToolModel.characterSkeleton => skinningCache.character != null ? skinningCache.character.skeleton : null; 298 299 UndoScope IBoneSpriteInfluenceToolModel.UndoScope(string description) 300 { 301 return skinningCache.UndoScope(description); 302 } 303 304 public CharacterPartCache GetSpriteCharacterPart(SpriteCache sprite) 305 { 306 return sprite.GetCharacterPart(); 307 } 308 309 protected override void OnActivate() 310 { 311 m_Controller.Activate(); 312 if (skeletonTool != null) 313 skeletonTool.Activate(); 314 } 315 316 protected override void OnDeactivate() 317 { 318 m_Controller.Deactivate(); 319 if (skeletonTool != null) 320 skeletonTool.Deactivate(); 321 } 322 323 public override void Initialize(LayoutOverlay layout) 324 { 325 if (m_View == null) 326 { 327 m_View = InfluenceWindow.CreateFromUxml(); 328 m_View.SetListReorderable(false); 329 m_View.SetAllowMultiselect(false); 330 m_Controller.OnViewCreated(); 331 } 332 333 layout.rightOverlay.Add(m_View); 334 } 335 336 protected override void OnGUI() 337 { 338 m_MeshPreviewBehaviour.showWeightMap = true; 339 m_MeshPreviewBehaviour.overlaySelected = true; 340 m_MeshPreviewBehaviour.drawWireframe = true; 341 342 skeletonTool.skeletonStyle = SkeletonStyles.WeightMap; 343 skeletonTool.mode = SkeletonMode.EditPose; 344 skeletonTool.editBindPose = false; 345 skeletonTool.DoGUI(); 346 } 347 } 348}