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