Skip to content

Commit

Permalink
Add chibi items (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonko0493 authored Feb 2, 2023
1 parent 42203c0 commit 47be581
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 6 deletions.
38 changes: 34 additions & 4 deletions src/SerialLoops.Lib/Items/ChibiItem.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,42 @@
using System;
using HaruhiChokuretsuLib.Archive;
using HaruhiChokuretsuLib.Archive.Data;
using HaruhiChokuretsuLib.Archive.Graphics;
using SkiaSharp;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SerialLoops.Lib.Items
{
internal class ChibiItem
public class ChibiItem : Item
{
public Chibi Chibi { get; set; }
public List<(string Name, ChibiEntry Chibi)> ChibiEntries { get; set; } = new();
public List<IEnumerable<(SKBitmap Frame, int Timing)>> ChibiAnimations { get; set; } = new();

public ChibiItem(Chibi chibi, Project project) : base($"CHIBI{chibi.ChibiEntries[0].Animation}", ItemType.Chibi)
{
Chibi = chibi;
string firstAnimationName = project.Grp.Files.First(f => f.Index == Chibi.ChibiEntries[0].Animation).Name;
Name = $"CHIBI_{firstAnimationName[0..firstAnimationName.IndexOf('_')]}";
ChibiEntries.AddRange(Chibi.ChibiEntries.Where(c => c.Animation > 0)
.Select(c => (project.Grp.Files.First(f => f.Index == c.Animation).Name[0..^3], c)));
ChibiAnimations.AddRange(ChibiEntries.Select(c => GetChibiAnimation(c.Name, project.Grp)));
}

private IEnumerable<(SKBitmap Frame, int Timing)> GetChibiAnimation(string entryName, ArchiveFile<GraphicsFile> grp)
{
ChibiEntry entry = ChibiEntries.First(c => c.Name == entryName).Chibi;
GraphicsFile animation = grp.Files.First(f => f.Index == entry.Animation);

IEnumerable<SKBitmap> frames = animation.GetAnimationFrames(grp.Files.First(f => f.Index == entry.Texture)).Select(f => f.GetImage());
IEnumerable<int> timings = animation.AnimationEntries.Select(a => (int)((FrameAnimationEntry)a).Time);

return frames.Zip(timings);
}

public override void Refresh(Project project)
{
GetChibiAnimation(Name, project.Grp);
}
}
}
2 changes: 1 addition & 1 deletion src/SerialLoops.Lib/Items/ItemDescription.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
public class ItemDescription
{

public string Name { get; private set; }
public string Name { get; protected set; }
public ItemType Type { get; private set; }

public ItemDescription(string name, ItemType type)
Expand Down
2 changes: 2 additions & 0 deletions src/SerialLoops.Lib/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ public void LoadArchives(ILogger log)
Items.Add(new BackgroundItem(name, i, entry, Evt, Grp));
}
}
Items.AddRange(Dat.Files.First(d => d.Name == "CHIBIS").CastTo<ChibiFile>()
.Chibis.Select(c => new ChibiItem(c, this)));
Items.AddRange(Evt.Files
.Where(e => !new string[] { "CHESSS", "EVTTBLS", "TOPICS", "SCENARIOS", "TUTORIALS", "VOICEMAPS" }.Contains(e.Name))
.Select(e => new ScriptItem(e)));
Expand Down
2 changes: 2 additions & 0 deletions src/SerialLoops/Controls/EditorTabsPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ internal static DocumentPage CreateTab(ItemDescription item, Project project, IL
{
case ItemDescription.ItemType.Background:
return new BackgroundEditor((BackgroundItem)project.Items.First(i => i.Name == item.Name), log);
case ItemDescription.ItemType.Chibi:
return new ChibiEditor((ChibiItem)project.Items.First(i => i.Name == item.Name), log);
case ItemDescription.ItemType.Map:
return new MapEditor((MapItem)project.Items.First(i => i.Name == item.Name), log);
case ItemDescription.ItemType.Puzzle:
Expand Down
83 changes: 83 additions & 0 deletions src/SerialLoops/Editors/ChibiEditor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using Eto.Forms;
using HaruhiChokuretsuLib.Util;
using SerialLoops.Lib.Items;
using SerialLoops.Utility;
using System;
using System.Linq;

namespace SerialLoops.Editors
{
public class ChibiEditor : Editor
{
private ChibiItem _chibi;
private DropDown _chibiSelection;
private AnimatedImage _animatedImage;
private StackLayout _framesStack;

public ChibiEditor(ChibiItem chibi, ILogger log) : base(chibi, log)
{
}

public override Panel GetEditorPanel()
{
_chibi = (ChibiItem)Description;

_chibiSelection = new();
_chibiSelection.Items.AddRange(_chibi.ChibiEntries.Select(c => new ListItem() { Text = c.Name, Key = c.Name }));
_chibiSelection.SelectedIndex = 0;
_chibiSelection.SelectedKeyChanged += ChibiSelection_SelectedKeyChanged;

_animatedImage = new(_chibi.ChibiAnimations[0]);
_animatedImage.Play();

_framesStack = new() { Orientation = Orientation.Vertical, Spacing = 10 };
UpdateFramesStack();

return new StackLayout
{
Orientation = Orientation.Vertical,
Items =
{
_chibiSelection,
new StackLayout
{
Orientation = Orientation.Horizontal,
Spacing = 20,
Items =
{
new GroupBox
{
Text = "Animation",
Content = _animatedImage,
},
new GroupBox
{
Text = "Frames",
Content = _framesStack,
}
}
}
}
};
}

private void UpdateFramesStack()
{
_framesStack.Items.Clear();
foreach (SKGuiImage image in _animatedImage.FramesWithTimings.Select(f => f.Frame))
{
_framesStack.Items.Add(image);
}
}

private void ChibiSelection_SelectedKeyChanged(object sender, EventArgs e)
{
DropDown chibiDropDown = (DropDown)sender;
AnimatedImage newImage = new(_chibi.ChibiAnimations[chibiDropDown.SelectedIndex]);
_animatedImage.CurrentFrame = 0;
_animatedImage.FramesWithTimings = newImage.FramesWithTimings;
_animatedImage.UpdateImage();
UpdateFramesStack();
}
}
}
53 changes: 53 additions & 0 deletions src/SerialLoops/Utility/AnimatedImage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using Eto.Forms;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SerialLoops.Utility
{
public class AnimatedImage : Panel
{
public List<(SKGuiImage Frame, int Timing)> FramesWithTimings { get; set; }
public int CurrentFrame { get; set; }
public UITimer FrameTimer { get; set; }

public AnimatedImage(IEnumerable<(SKBitmap Frame, int Timing)> framesWithTimings)
{
FramesWithTimings = framesWithTimings.Select(f => (new SKGuiImage(f.Frame), f.Timing)).ToList();
InitializeComponent();
}

private void InitializeComponent()
{
CurrentFrame = 0;
Padding = 0;
UpdateImage();
}

public void UpdateImage()
{
Content = FramesWithTimings[CurrentFrame].Frame;
}

public void Play()
{
FrameTimer = new();
FrameTimer.Elapsed += FrameTimer_Elapsed;
FrameTimer.Interval = FramesWithTimings[CurrentFrame].Timing / 60.0;
FrameTimer.Start();
}

private void FrameTimer_Elapsed(object sender, EventArgs e)
{
FrameTimer.Stop();
CurrentFrame++;
if (CurrentFrame >= FramesWithTimings.Count)
{
CurrentFrame = 0;
}
UpdateImage();
Play();
}
}
}
2 changes: 1 addition & 1 deletion src/SerialLoops/Utility/SKGuiImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace SerialLoops.Utility
{
public class SKGuiImage : Bitmap
{
public SKBitmap skBitmap { get; set; }
public SKBitmap SkBitmap { get; set; }

public SKGuiImage(SKBitmap skBitmap) : base(skBitmap.Encode(SKEncodedImageFormat.Png, 1).AsStream())
{
Expand Down

0 comments on commit 47be581

Please sign in to comment.