diff --git a/Models/CelModel.cs b/Models/CelModel.cs index 9e7bbf4..b9ef193 100644 --- a/Models/CelModel.cs +++ b/Models/CelModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text.Json.Serialization; using System.Text.RegularExpressions; using fxl.codes.kisekae.Services; using Microsoft.Extensions.Logging; @@ -58,13 +59,10 @@ namespace fxl.codes.kisekae.Models public bool[] Sets { get; } = new bool[10]; public string Comment { get; init; } public Coordinate[] InitialPositions { get; } = new Coordinate[10]; - public string DefaultImage => ImageByPalette.ContainsKey(PaletteId) ? ImageByPalette[PaletteId] : null; + [JsonIgnore] public string DefaultImage => ImageByPalette.ContainsKey(PaletteId) ? ImageByPalette[PaletteId] : null; public Coordinate Offset { get; set; } - - public Coordinate PositionForSet(int set) - { - var current = InitialPositions[set]; - return current == null ? new Coordinate(0, 0) : new Coordinate(current.X + Offset.X, current.Y + Offset.Y); - } + [JsonIgnore] public int Height { get; internal set; } + [JsonIgnore] public int Width { get; internal set; } + [JsonIgnore] public int ZIndex { get; internal set; } } } \ No newline at end of file diff --git a/Models/PlaysetModel.cs b/Models/PlaysetModel.cs index 585846f..7dd7e9c 100644 --- a/Models/PlaysetModel.cs +++ b/Models/PlaysetModel.cs @@ -1,17 +1,17 @@ using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; using SixLabors.ImageSharp; namespace fxl.codes.kisekae.Models { public class PlaysetModel { - public int[] CurrentPalettes = new int[10]; public string Name { get; set; } public int Height { get; set; } public int Width { get; set; } - public Color BorderColor { get; set; } = Color.Black; - - public List Palettes { get; } = new(); + [JsonIgnore] public Color BorderColor { get; set; } = Color.Black; + [JsonIgnore] public List Palettes { get; } = new(); public List Cels { get; } = new(); public bool[] EnabledSets @@ -19,10 +19,8 @@ namespace fxl.codes.kisekae.Models get { var enabled = new bool[10]; - foreach (var cel in Cels) - for (var index = 0; index < cel.Sets.Length; index++) - if (cel.Sets[index]) - enabled[index] = true; + + for (var index = 0; index < enabled.Length; index++) enabled[index] = Cels.Any(x => x.Sets[index]); return enabled; } diff --git a/Scripts/function.ts b/Scripts/function.ts index 877920f..b8f5e8a 100644 --- a/Scripts/function.ts +++ b/Scripts/function.ts @@ -1,43 +1,24 @@ -import {ICel, IPlayset} from "./pto" -import Builder from "./utility"; +import {Playset} from "./pto" -export function draw(playset: IPlayset, canvas: HTMLCanvasElement, set: number): void { - let context = canvas.getContext("2d") - context.clearRect(0, 0, canvas.width, canvas.height) +const cssClass = "active-set" - playset.cels.forEach(cel => { - drawToCanvas2dContext(cel, context, set) - }) -} - -export function drawToCanvas2dContext(cel: ICel, context: CanvasRenderingContext2D, set: number): void { - if (!cel.sets[set]) return - - let image = new Image() - image.onload = () => { - context.drawImage(image, cel.initialPositions[set].x + cel.offset.x, cel.initialPositions[set].y + cel.offset.y) - } - - image.src = `data:image/gif;base64,${cel.defaultImage}` -} - -export function setPlayArea(header: HTMLElement, container: HTMLElement, playset: IPlayset, set: number): void { - const cssClass = "active-set" +export function setPlayArea(header: HTMLElement, container: HTMLElement, playset: Playset, set: number): void { header.querySelectorAll("button").forEach(button => { button.classList.remove(cssClass) }) header.querySelector(`button[data-set="${set}"]`).classList.add(cssClass) + let elements = container.querySelectorAll(".cel-image") - let canvases = container.getElementsByTagName("canvas") - if (canvases.length) { - draw(playset, canvases[0], set) - return - } - - let canvas = new Builder("canvas") - .addAttributes({"height": playset.height, "width": playset.width}) - .build() - container.appendChild(canvas) - draw(playset, canvases[0], set) + playset.cels.forEach((cel, index) => { + let element = elements[index] as HTMLDivElement + element.style.visibility = "hidden" + + if (cel.sets[set]) { + let position = cel.currentPositions[set] + element.style.visibility = "visible" + element.style.left = `${position.x}px` + element.style.top = `${position.y}px` + } + }) } \ No newline at end of file diff --git a/Scripts/main.ts b/Scripts/main.ts index 3e744f0..828819f 100644 --- a/Scripts/main.ts +++ b/Scripts/main.ts @@ -2,7 +2,7 @@ import {MDCLinearProgress} from "@material/linear-progress" import {MDCRipple} from "@material/ripple" import {MDCTopAppBar} from "@material/top-app-bar" import {setPlayArea} from "./function" -import {IPlayset} from "./pto" +import {Playset} from "./pto" import Builder from "./utility" declare global { @@ -28,7 +28,7 @@ export default class Main { this.init() } - public load(containerId: string, headerId: string, playset: IPlayset, set: number = 0): void { + public load(containerId: string, headerId: string, playset: Playset, set: number = 0): void { let container = document.getElementById(containerId) let header = document.getElementById(headerId) let menu = header.querySelector("ul") @@ -36,7 +36,7 @@ export default class Main { let reset = header.querySelector(`button[data-rel="reset"]`) reset.addEventListener("click", () => { // TODO reset positions - setPlayArea(header, container, playset, 0) + setPlayArea(header, container, playset, set) }) playset.enabledSets.forEach((enabled, index) => { @@ -57,6 +57,10 @@ export default class Main { menu.appendChild(button) } }) + + playset.cels.forEach(cel => { + cel.currentPositions = [...cel.initialPositions] + }) setPlayArea(header, container, playset, set) } diff --git a/Scripts/pto.ts b/Scripts/pto.ts index a0e9f67..fa41f17 100644 --- a/Scripts/pto.ts +++ b/Scripts/pto.ts @@ -1,20 +1,27 @@ -export interface IPlayset { +export class Playset { name: string height: number width: number - cels: ICel[] + cels: Cel[] enabledSets: boolean[] } -export interface ICel { +export class Cel { defaultImage: string initialPositions: Coordinate[] offset: Coordinate sets: boolean[] + + currentPositions: Coordinate[] } export class Coordinate { x: number y: number + + constructor(x: number = 0, y: number = 0) { + this.x = x + this.y = y + } } diff --git a/Services/ConfigurationReaderService.cs b/Services/ConfigurationReaderService.cs index 6690628..42553d3 100644 --- a/Services/ConfigurationReaderService.cs +++ b/Services/ConfigurationReaderService.cs @@ -4,15 +4,14 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; using fxl.codes.kisekae.Models; -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; namespace fxl.codes.kisekae.Services { public class ConfigurationReaderService { - private readonly ILogger _logger; private readonly FileParserService _fileParser; + private readonly ILogger _logger; public ConfigurationReaderService(ILogger logger, FileParserService fileParser) { @@ -20,20 +19,12 @@ namespace fxl.codes.kisekae.Services _fileParser = fileParser; } - public PlaysetModel ReadCnf(IFormFile file) - { - _logger.LogTrace($"Reading filename {file.FileName}"); - var set = ParseStream(file.OpenReadStream()); - set.Name = file.FileName; - return set; - } - public PlaysetModel ParseStream(Stream fileStream, string directory = null) { var model = new PlaysetModel(); var initialPositions = new StringBuilder(); var borderColorIndex = 0; - + using var reader = new StreamReader(fileStream); while (!reader.EndOfStream) { @@ -65,22 +56,21 @@ namespace fxl.codes.kisekae.Services break; } } - + SetInitialPositions(model, initialPositions.ToString()); if (string.IsNullOrEmpty(directory)) return model; - - foreach (var palette in model.Palettes) - { - _fileParser.ParsePalette(directory, palette); - } + foreach (var palette in model.Palettes) _fileParser.ParsePalette(directory, palette); + + var celIndex = 0; foreach (var cel in model.Cels.Where(x => !string.IsNullOrEmpty(x.FileName))) { _fileParser.ParseCel(directory, cel, model.Palettes); + cel.ZIndex = (model.Cels.Count - celIndex) * 10; + celIndex++; } - + if (model.Palettes.Any() && model.Palettes[0].Colors.Any()) model.BorderColor = model.Palettes[0].Colors[borderColorIndex]; - model.Cels.Reverse(); return model; } @@ -91,17 +81,13 @@ namespace fxl.codes.kisekae.Services for (var index = 0; index < sets.Length; index++) { var value = sets[index].Split(' ', StringSplitOptions.RemoveEmptyEntries); - model.CurrentPalettes[index] = int.Parse(value[0]); - for (var innerIndex = 1; innerIndex < value.Length; innerIndex++) { if (value[innerIndex] == "*") continue; var point = value[innerIndex].Split(',', StringSplitOptions.RemoveEmptyEntries); - + foreach (var cel in model.Cels.Where(x => x.Id == innerIndex - 1)) - { cel.InitialPositions[index] = new Coordinate(int.Parse(point[0]), int.Parse(point[1])); - } } } } diff --git a/Services/FileParserService.cs b/Services/FileParserService.cs index 8243628..7d7438a 100644 --- a/Services/FileParserService.cs +++ b/Services/FileParserService.cs @@ -108,6 +108,8 @@ namespace fxl.codes.kisekae.Services cel.ImageByPalette = GetCelImages(buffer[32..], palettes.ToArray(), width, height, pixelBits); cel.Offset = new Coordinate(xOffset, yOffset); + cel.Height = height; + cel.Width = width; } else { @@ -115,6 +117,8 @@ namespace fxl.codes.kisekae.Services var height = BitConverter.ToInt16(buffer, 2); cel.ImageByPalette = GetCelImages(buffer[4..], palettes.ToArray(), width, height); + cel.Height = height; + cel.Width = width; } } diff --git a/Styles/main.css b/Styles/main.css deleted file mode 100644 index af897a7..0000000 --- a/Styles/main.css +++ /dev/null @@ -1,20 +0,0 @@ -/* Error: Can't find stylesheet to import. - * , - * 4 | / @use "~@material/theme" with ( - * 5 | | $primary: $fxl-orange, - * 6 | | $on-primary: $fxl-gray - * 7 | | ); - * | '-^ - * ' - * main.scss 4:1 root stylesheet */ - -body::before { - font-family: "Source Code Pro", "SF Mono", Monaco, Inconsolata, "Fira Mono", - "Droid Sans Mono", monospace, monospace; - white-space: pre; - display: block; - padding: 1em; - margin-bottom: 1em; - border-bottom: 2px solid black; - content: "Error: Can't find stylesheet to import.\a \2577 \a 4 \2502 \250c @use \"~@material/theme\" with (\a 5 \2502 \2502 $primary: $fxl-orange,\a 6 \2502 \2502 $on-primary: $fxl-gray\a 7 \2502 \2502 );\a \2502 \2514 \2500 ^\a \2575 \a main.scss 4:1 root stylesheet"; -} diff --git a/Styles/main.scss b/Styles/main.scss index cd7c520..f9e381c 100644 --- a/Styles/main.scss +++ b/Styles/main.scss @@ -52,9 +52,15 @@ body { display: flex; flex: 1; text-align: center; - - canvas { + + #play_space { margin: 2em auto; + position: relative; + + .cel-image { + visibility: hidden; + position: absolute; + } } } } diff --git a/Views/Home/Play.cshtml b/Views/Home/Play.cshtml index cc28120..24a3d2e 100644 --- a/Views/Home/Play.cshtml +++ b/Views/Home/Play.cshtml @@ -1,8 +1,7 @@ @model PlaysetModel @{ - ViewBag.Title = $"Play with {Model.Name}"; - Layout = "_Layout"; + ViewData["Title"] = $"Play with {Model.Name}"; }
@@ -17,10 +16,20 @@
  • Sets
  • -
    +
    +
    + @foreach (var cel in Model.Cels) + { +
    + } +
    +
    @section Scripts { } diff --git a/package-lock.json b/package-lock.json index e149118..a8e1c5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2046,9 +2046,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.3.864", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.864.tgz", - "integrity": "sha512-v4rbad8GO6/yVI92WOeU9Wgxc4NA0n4f6P1FvZTY+jyY7JHEhw3bduYu60v3Q1h81Cg6eo4ApZrFPuycwd5hGw==", + "version": "1.3.866", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.866.tgz", + "integrity": "sha512-iYze6TpDXWxk+sfcpUUdTs6Pv/3kG45Pnjer2DxEeFw0N08bZeNLuz97s2lMgy8yObon48o0WHY2Bkg3xuAPOA==", "dev": true }, "node_modules/emojis-list": { @@ -6018,9 +6018,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.864", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.864.tgz", - "integrity": "sha512-v4rbad8GO6/yVI92WOeU9Wgxc4NA0n4f6P1FvZTY+jyY7JHEhw3bduYu60v3Q1h81Cg6eo4ApZrFPuycwd5hGw==", + "version": "1.3.866", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.866.tgz", + "integrity": "sha512-iYze6TpDXWxk+sfcpUUdTs6Pv/3kG45Pnjer2DxEeFw0N08bZeNLuz97s2lMgy8yObon48o0WHY2Bkg3xuAPOA==", "dev": true }, "emojis-list": {