Skip to content

Commit

Permalink
Fix assets that modify other sprites. More progress towards SpriteEdi…
Browse files Browse the repository at this point in the history
…tor.
  • Loading branch information
isadorasophia committed Dec 16, 2023
1 parent 36ccc17 commit 5daffa8
Show file tree
Hide file tree
Showing 13 changed files with 231 additions and 118 deletions.
95 changes: 95 additions & 0 deletions src/Murder.Editor/Assets/SpriteEventData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
namespace Murder.Editor.Assets;

public class SpriteEventData
{
public readonly Dictionary<string, Dictionary<int, string>> Events = new();

public readonly Dictionary<string, HashSet<int>> DeletedEvents = new();

/// <summary>
/// Apply custom messages to an existing dictionary of events.
/// </summary>
public void FilterEventsForAnimation(string animation, ref Dictionary<int, string> events)
{
if (Events.TryGetValue(animation, out var customEvents))
{
foreach ((int frame, string message) in customEvents)
{
events[frame] = message;
}
}

if (DeletedEvents.TryGetValue(animation, out var deletedEvents))
{
foreach (int frame in deletedEvents)
{
events.Remove(frame);
}
}
}

public Dictionary<int, string> GetEventsForAnimation(string animation)
{
if (!Events.TryGetValue(animation, out var dictionary))
{
dictionary = new();
Events[animation] = dictionary;
}

return dictionary;
}

public void AddEvent(string animation, int frame, string message)
{
Dictionary<int, string> dict = GetEventsForAnimation(animation);
dict[frame] = message;

RemoveFromDeletedEvents(animation, frame);
}

public void RemoveEvent(string animation, int frame)
{
if (!Events.TryGetValue(animation, out var dictionary))
{
AddToDeletedEvent(animation, frame);
return;
}

bool hadValueDefined = dictionary.Remove(frame);
if (!hadValueDefined)
{
// Value was previously not tracked here. It is likely added by aseprite.
// So let's override that!
AddToDeletedEvent(animation, frame);
}
}

private void AddToDeletedEvent(string animation, int frame)
{
if (!DeletedEvents.TryGetValue(animation, out var dictionary))
{
dictionary = new();
DeletedEvents[animation] = dictionary;
}

dictionary.Add(frame);
}

private bool RemoveFromDeletedEvents(string animation, int frame)
{
if (!DeletedEvents.TryGetValue(animation, out var dictionary))
{
return false;
}

_ = dictionary.Remove(frame);
if (dictionary.Count == 0)
{
DeletedEvents.Remove(animation);
}

return true;
}

public SpriteEventData() { }
}
74 changes: 5 additions & 69 deletions src/Murder.Editor/Assets/SpriteEventDataManagerAsset.cs
Original file line number Diff line number Diff line change
@@ -1,75 +1,10 @@
using Murder.Assets;
using Murder.Diagnostics;
using Murder.Utilities.Attributes;
using Newtonsoft.Json;
using System.Collections.Immutable;

namespace Murder.Editor.Assets.Graphics;

public class SpriteEventData
{
public readonly Dictionary<string, Dictionary<int, string>> Events = new();

public readonly Dictionary<string, HashSet<int>> DeletedEvents = new();

public Dictionary<int, string> GetEventsForAnimation(string animation)
{
if (!Events.TryGetValue(animation, out var dictionary))
{
dictionary = new();
Events[animation] = dictionary;
}

return dictionary;
}

public void AddEvent(string animation, int frame, string message)
{
Dictionary<int, string> dict = GetEventsForAnimation(animation);
dict[frame] = message;

RemoveFromDeletedEvents(animation, frame);
}

public void RemoveEvent(string animation, int frame)
{
if (!Events.TryGetValue(animation, out var dictionary))
{
AddToDeletedEvent(animation, frame);
return;
}

bool hadValueDefined = dictionary.Remove(frame);
if (!hadValueDefined)
{
// Value was previously not tracked here. It is likely added by aseprite.
// So let's override that!
AddToDeletedEvent(animation, frame);
}
}

private void AddToDeletedEvent(string animation, int frame)
{
if (!DeletedEvents.TryGetValue(animation, out var dictionary))
{
dictionary = new();
DeletedEvents[animation] = dictionary;
}

dictionary.Add(frame);
}

private bool RemoveFromDeletedEvents(string animation, int frame)
{
if (!DeletedEvents.TryGetValue(animation, out var dictionary))
{
return false;
}

return dictionary.Remove(frame);
}

public SpriteEventData() { }
}
namespace Murder.Editor.Assets;

[RuntimeOnly]
internal class SpriteEventDataManagerAsset : GameAsset
Expand All @@ -79,6 +14,7 @@ internal class SpriteEventDataManagerAsset : GameAsset
/// </summary>
public override string EditorFolder => "_Hidden";

[JsonProperty]
public ImmutableDictionary<Guid, SpriteEventData> Events { get; private set; } =
ImmutableDictionary<Guid, SpriteEventData>.Empty;

Expand All @@ -95,7 +31,7 @@ public bool DeleteSprite(Guid spriteId)

return false;
}

public SpriteEventData GetOrCreate(Guid spriteId)
{
if (Events.TryGetValue(spriteId, out SpriteEventData? spriteEventData))
Expand All @@ -119,7 +55,7 @@ public SpriteEventData GetOrCreate(Guid spriteId)
}

ImmutableDictionary<Guid, GameAsset> assets = Architect.EditorData.FilterAllAssets(typeof(SpriteEventDataManagerAsset));
if (assets.Count >= 1)
if (assets.Count > 1)
{
GameLogger.Warning("How did we end up with more than one manager assets?");
}
Expand Down
8 changes: 7 additions & 1 deletion src/Murder.Editor/CustomEditors/SpriteEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using Murder.Core.Graphics;
using Murder.Core.Sounds;
using Murder.Diagnostics;
using Murder.Editor.Assets.Graphics;
using Murder.Editor.Assets;
using Murder.Editor.Attributes;
using Murder.Editor.CustomFields;
using Murder.Editor.ImGuiExtended;
Expand Down Expand Up @@ -140,6 +140,9 @@ private void AddMessage(string animation, int frame, string message)

// Also, let the sprite know that this is a thing now.
_sprite.AddMessageToAnimationFrame(animation, frame, message);
_sprite.TrackAssetOnSave(manager.Guid);

manager.FileChanged = true;
}

private void DeleteMessage(string animation, int frame)
Expand All @@ -152,6 +155,9 @@ private void DeleteMessage(string animation, int frame)
data.RemoveEvent(animation, frame);

_sprite.RemoveMessageFromAnimationFrame(animation, frame);
_sprite.TrackAssetOnSave(manager.Guid);

manager.FileChanged = true;
}

private void DrawFirstColumn(SpriteInformation info)
Expand Down
3 changes: 2 additions & 1 deletion src/Murder.Editor/CustomFields/LocalizedStringField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ public override (bool modified, object? result) ProcessInput(EditorMember member
localization.SetResource(data);
modified = true;

Architect.EditorData.SaveAsset(localization);
EditorServices.SaveAssetWhenSelectedAssetIsSaved(localization.Guid);
localization.FileChanged = true;
}

return (modified, localizedString);
Expand Down
1 change: 1 addition & 0 deletions src/Murder.Editor/Data/Dialogs/GumToMurderConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public void ReloadDialogWith(GumData.CharacterScript script, CharacterAsset asse
asset.RemoveCustomComponents(_components.Keys.Where(t => !_matchedComponents.Contains(t)));

localizationAsset.SetResourcesForDialogue(asset.Guid, _localizedStrings.ToImmutable());
Architect.EditorData.SaveAsset(localizationAsset);
}

private Dictionary<string, LocalizedString> FetchResourcesForAsset(LocalizationAsset localizationAsset, Guid characterGuid)
Expand Down
16 changes: 16 additions & 0 deletions src/Murder.Editor/Data/EditorDataManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,22 @@ public void SaveAsset<T>(T asset) where T : GameAsset
FileHelper.CreateDirectoryPathIfNotExists(binPath);
FileHelper.SaveSerialized(asset, binPath);
}

// Also save any extra assets at this point.
List<Guid>? saveAssetsOnSave = asset.AssetsToBeSaved();
if (saveAssetsOnSave is not null)
{
foreach (Guid g in saveAssetsOnSave)
{
GameAsset? a = TryGetAsset(g);
if (a is null)
{
continue;
}

SaveAsset(a);
}
}
}

private GameAsset? GetAssetByName(string name)
Expand Down
13 changes: 11 additions & 2 deletions src/Murder.Editor/Data/EditorDataManager_Sprites.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ private void FetchResourcesForImporters(bool reload, bool skipIfNoChangesFound)
return;
}

bool foundChanges = false;

DateTime lastTimeFetched = reload ? EditorSettings.LastHotReloadImport : EditorSettings.LastImported;

string rawResourcesPath = FileHelper.GetPath(EditorSettings.RawResourcesPath);
Expand Down Expand Up @@ -178,12 +180,20 @@ private void FetchResourcesForImporters(bool reload, bool skipIfNoChangesFound)
!Directory.Exists(importer.GetSourcePackedPath()) ||
!Directory.Exists(importer.GetSourceResourcesPath());

bool changed = hasInitializedAtlas || File.GetLastWriteTime(file) > lastTimeFetched;
foundChanges |= changed;

// If everything is good so far, put it on stage and check for changes
importer.StageFile(file, hasInitializedAtlas || File.GetLastWriteTime(file) > lastTimeFetched);
importer.StageFile(file, changed);
break;
}
}

if (!foundChanges)
{
return;
}

EditorSettings.LastHotReloadImport = DateTime.Now;

if (!reload)
Expand All @@ -193,6 +203,5 @@ private void FetchResourcesForImporters(bool reload, bool skipIfNoChangesFound)

SaveAsset(Architect.EditorSettings);
}

}
}
31 changes: 22 additions & 9 deletions src/Murder.Editor/Data/Graphics/AsepriteImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
using Murder.Core.Graphics;
using Murder.Data;
using Murder.Diagnostics;
using Murder.Editor.Assets;
using Murder.Serialization;
using Murder.Utilities;
using System.Collections.Immutable;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
using static Murder.Editor.Data.Graphics.Aseprite;
using static Murder.Editor.Data.Graphics.Aseprite.Layer;
using Color = Microsoft.Xna.Framework.Color;

// Gist from:
Expand Down Expand Up @@ -748,6 +747,11 @@ private SpriteAsset CreateAsset(int layer, int sliceIndex, AtlasId atlas)
slice = Slices[sliceIndex];
}

(bool baked, Guid guid) = GetGuid(layer, sliceIndex);

SpriteEventData? spriteEventData = null;
SpriteEventDataManagerAsset.TryGet()?.Events.TryGetValue(guid, out spriteEventData);

// Create an empty animation with all frames
{
int[] frames;
Expand All @@ -769,11 +773,17 @@ private SpriteAsset CreateAsset(int layer, int sliceIndex, AtlasId atlas)
}
else
{
frames = new int[] { 0 };
durations = new float[] { Frames[0].Duration };
frames = [0];
durations = [Frames[0].Duration];
}

dictBuilder[string.Empty] = new Animation(frames, durations, events, null);

// Now that we have a guid, make sure if there are any extra events we need to pull.
if (spriteEventData is not null)
{
spriteEventData.FilterEventsForAnimation(string.Empty, ref events);
}
}

for (int i = 0; i < Tags.Count; i++) // Create individual animations for tags
Expand Down Expand Up @@ -831,15 +841,20 @@ private SpriteAsset CreateAsset(int layer, int sliceIndex, AtlasId atlas)
}
break;
}

}
else
{
frames = new int[] { 0 };
durations = new float[] { Frames[0].Duration };
frames = [0];
durations = [Frames[0].Duration];
FindEventsInframe(events, 0, 0);
}

// Now that we have a guid, make sure if there are any extra events we need to pull.
if (spriteEventData is not null)
{
spriteEventData.FilterEventsForAnimation(tag.Name, ref events);
}

dictBuilder[tag.Name] = new Animation(frames, durations, events, AnimationSequence.CreateIfPossible(tag.UserData.Text));
}

Expand All @@ -853,8 +868,6 @@ private SpriteAsset CreateAsset(int layer, int sliceIndex, AtlasId atlas)
framesBuilder.Add($"{source}");
Point pivot = slice?.Pivot != null ? new Point(slice.Pivot.Value.X, slice.Pivot.Value.Y) : Point.Zero;

(bool baked, Guid guid) = GetGuid(layer, sliceIndex);

// No slice or just get the first
SpriteAsset asset = new(
guid: guid,
Expand Down
2 changes: 1 addition & 1 deletion src/Murder.Editor/EditorScene_Selector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ private void DrawAssetFolder(string folderName, Vector4 color, Type? createType,

private void DrawAssetFolder(string folderName, Vector4 color, Type? createType, IEnumerable<GameAsset> assets, int depth, string folderRootPath, bool unfoldAll)
{
if (folderName.StartsWith(GameDataManager.SKIP_CHAR))
if (folderName.StartsWith(GameDataManager.SKIP_CHAR) || folderName.StartsWith("_"))
{
// Skip folders that start with "_".
return;
Expand Down
Loading

0 comments on commit 5daffa8

Please sign in to comment.