From d3a55460f32ccec9cdf789bcfea58fc4b89a0c6d Mon Sep 17 00:00:00 2001 From: tutu Date: Tue, 6 Feb 2024 10:44:05 +0800 Subject: [PATCH] chore: modify files according to the specification (#68) * fix: remove ts-ignore and resolve some type check * chore: modify files according to the specification * chore: remove project manage demo --- .../src/class/{AssetBase.ts => asset-base.ts} | 6 +- .../src/class/{AssetList.ts => asset-list.ts} | 6 +- spx-gui/src/class/backdrop.ts | 12 ++-- spx-gui/src/class/sound.ts | 9 ++- spx-gui/src/class/sprite.ts | 10 ++- spx-gui/src/interface/file.ts | 6 +- spx-gui/src/store/modules/project/index.ts | 28 ++++---- spx-gui/src/types/file.ts | 29 ++------ spx-gui/src/util/class.ts | 2 +- .../util/{FileSystem.ts => file-system.ts} | 0 spx-gui/src/util/file.ts | 42 +++++------ spx-gui/src/util/wasm.ts | 69 ------------------- spx-gui/src/view/demo.vue | 38 ---------- 13 files changed, 63 insertions(+), 194 deletions(-) rename spx-gui/src/class/{AssetBase.ts => asset-base.ts} (95%) rename spx-gui/src/class/{AssetList.ts => asset-list.ts} (77%) rename spx-gui/src/util/{FileSystem.ts => file-system.ts} (100%) delete mode 100644 spx-gui/src/util/wasm.ts delete mode 100644 spx-gui/src/view/demo.vue diff --git a/spx-gui/src/class/AssetBase.ts b/spx-gui/src/class/asset-base.ts similarity index 95% rename from spx-gui/src/class/AssetBase.ts rename to spx-gui/src/class/asset-base.ts index 281b51ed..8904c4f2 100644 --- a/spx-gui/src/class/AssetBase.ts +++ b/spx-gui/src/class/asset-base.ts @@ -3,10 +3,10 @@ * @Date: 2024-01-22 10:28:03 * @LastEditors: TuGitee tgb@std.uestc.edu.cn * @LastEditTime: 2024-01-25 15:03:08 - * @FilePath: \builder\spx-gui\src\class\AssetBase.ts + * @FilePath: \builder\spx-gui\src\class\asset-base.ts * @Description: The abstract class of an asset. */ -import type file from "@/interface/file"; +import type { AssetBaseInterface } from "@/interface/file"; import { getStorage } from "@/util/class"; import FileWithUrl from "@/class/FileWithUrl"; import { isObjectEmpty } from "@/util/global"; @@ -19,7 +19,7 @@ import type { Config } from '@/interface/file'; * @author tgb * @createDate 2024-01-18 */ -export default abstract class AssetBase implements file { +export abstract class AssetBase implements AssetBaseInterface { protected _files: FileWithUrl[]; public name: string; public abstract config: Config; diff --git a/spx-gui/src/class/AssetList.ts b/spx-gui/src/class/asset-list.ts similarity index 77% rename from spx-gui/src/class/AssetList.ts rename to spx-gui/src/class/asset-list.ts index 44a9f891..4da5ed08 100644 --- a/spx-gui/src/class/AssetList.ts +++ b/spx-gui/src/class/asset-list.ts @@ -1,6 +1,6 @@ -import AssetBase from "./AssetBase"; -import Sound from "./sound"; -import Sprite from "./sprite"; +import { AssetBase } from "./asset-base"; +import { Sound } from "./sound"; +import { Sprite } from "./sprite"; export abstract class AssetList { public list: T[] = []; diff --git a/spx-gui/src/class/backdrop.ts b/spx-gui/src/class/backdrop.ts index 30686015..d56c08de 100644 --- a/spx-gui/src/class/backdrop.ts +++ b/spx-gui/src/class/backdrop.ts @@ -7,9 +7,10 @@ * @Description: The class of a backdrop. */ import type { BackdropConfig, Scene } from "@/interface/file"; -import AssetBase from "./AssetBase"; +import { AssetBase } from "./asset-base"; import { isInstance, getAllFromLocal } from "@/util/class"; -import type { rawFile } from "@/types/file"; +import type { RawDir } from "@/types/file"; +import { useProjectStore } from "@/store/modules/project"; /** * @class Backdrop @@ -46,7 +47,7 @@ import type { rawFile } from "@/types/file"; * backdrop.config = backdrop.genDefualtConfig() */ -export default class Backdrop extends AssetBase implements file { +export class Backdrop extends AssetBase { /** * The root path of the backdrop. */ @@ -80,7 +81,6 @@ export default class Backdrop extends AssetBase implements file { * @returns all items in the storage */ static async getAllFromLocal() { - // @ts-ignore return await getAllFromLocal(Backdrop); } @@ -121,7 +121,7 @@ export default class Backdrop extends AssetBase implements file { "name": file.name.split(".")[0], "path": file.name })), - "zorder": [], + "zorder": useProjectStore().project?.sprite.list.map(sprite => sprite.name) || [], "sceneIndex": 0 } } @@ -166,7 +166,7 @@ export default class Backdrop extends AssetBase implements file { * Get the directory of the backdrop. */ get dir() { - const dir: Record = {} + const dir: RawDir = {} dir[`${this.path}index.json`] = this.config for (const file of this.files) { dir[`${this.path}${file.name}`] = file diff --git a/spx-gui/src/class/sound.ts b/spx-gui/src/class/sound.ts index 166bb4bb..fd54dc90 100644 --- a/spx-gui/src/class/sound.ts +++ b/spx-gui/src/class/sound.ts @@ -6,10 +6,9 @@ * @FilePath: \builder\spx-gui\src\class\sound.ts * @Description: The class of a sound. */ -import type file from "@/interface/file"; -import AssetBase from "./AssetBase"; +import { AssetBase } from "./asset-base"; import { isInstance, getAllFromLocal } from "@/util/class"; -import type { rawFile } from "@/types/file"; +import type { RawDir } from "@/types/file"; import type { SoundConfig } from '@/interface/file'; /** @@ -51,7 +50,7 @@ import type { SoundConfig } from '@/interface/file'; * snd1.config = snd1.genDefualtConfig() */ -export default class Sound extends AssetBase implements file { +export class Sound extends AssetBase { /** * The root path of the sounds. */ @@ -129,7 +128,7 @@ export default class Sound extends AssetBase implements file { * Get the directory of the sound. */ get dir() { - const dir: Record = {} + const dir: RawDir = {} dir[`${this.path}/index.json`] = this.config for (const file of this.files) { dir[`${this.path}/${file.name}`] = file diff --git a/spx-gui/src/class/sprite.ts b/spx-gui/src/class/sprite.ts index 34f16212..84549a20 100644 --- a/spx-gui/src/class/sprite.ts +++ b/spx-gui/src/class/sprite.ts @@ -7,11 +7,10 @@ * @Description: The class of a sprite. */ -import type file from "@/interface/file"; import type { Costume, SpriteConfig } from "@/interface/file"; -import AssetBase from "./AssetBase"; +import { AssetBase } from "./asset-base"; import { isInstance, getAllFromLocal } from "@/util/class"; -import type { rawFile } from "@/types/file"; +import type { RawDir } from "@/types/file"; /** * @class Sprite @@ -58,7 +57,7 @@ import type { rawFile } from "@/types/file"; * spt1.config = spt1.genDefualtConfig() */ -export default class Sprite extends AssetBase implements file { +export class Sprite extends AssetBase { /** * The root path of the sprites. */ @@ -97,7 +96,6 @@ export default class Sprite extends AssetBase implements file { * @returns all items in the storage */ static async getAllFromLocal() { - // @ts-ignore return await getAllFromLocal(Sprite); } @@ -265,7 +263,7 @@ export default class Sprite extends AssetBase implements file { * Get the directory of the sprite. */ get dir() { - const dir: Record = {} + const dir: RawDir = {} dir[`${this.path}/index.json`] = this.config for (const file of this.files) { dir[`${this.path}/${file.name}`] = file diff --git a/spx-gui/src/interface/file.ts b/spx-gui/src/interface/file.ts index f76d6d98..8189a3cd 100644 --- a/spx-gui/src/interface/file.ts +++ b/spx-gui/src/interface/file.ts @@ -8,15 +8,15 @@ */ import FileWithUrl from "@/class/FileWithUrl"; -import type { rawFile } from "@/types/file"; +import type { RawDir } from "@/types/file"; /** * file interface */ -export default interface file { +export interface AssetBaseInterface { files: FileWithUrl[]; config: Config; - dir?: Record; + dir?: RawDir; path?: string; /** diff --git a/spx-gui/src/store/modules/project/index.ts b/spx-gui/src/store/modules/project/index.ts index 1db9a69f..c17d2b78 100644 --- a/spx-gui/src/store/modules/project/index.ts +++ b/spx-gui/src/store/modules/project/index.ts @@ -9,12 +9,12 @@ import { ref, watch } from 'vue' import { defineStore } from 'pinia' -import * as fs from '@/util/FileSystem' -import type { FileType, dirPath, rawDir } from "@/types/file"; +import * as fs from '@/util/file-system' +import type { FileType, DirPath, RawDir } from "@/types/file"; import { convertDirPathToProject, convertRawDirToDirPath, convertRawDirToZip, getDirPathFromZip } from "@/util/file"; import saveAs from "file-saver"; -import { SoundList, SpriteList } from "@/class/AssetList"; -import Backdrop from '@/class/backdrop'; +import { SoundList, SpriteList } from "@/class/asset-list"; +import { Backdrop } from '@/class/backdrop'; const UNTITLED_NAME = 'Untitled' interface ProjectData { @@ -23,7 +23,7 @@ interface ProjectData { sound: SoundList backdrop: Backdrop entryCode: string - UnidentifiedFile: rawDir + UnidentifiedFile: RawDir } export class Project implements ProjectData { @@ -32,7 +32,7 @@ export class Project implements ProjectData { sound: SoundList; backdrop: Backdrop; entryCode: string; - UnidentifiedFile: rawDir; + UnidentifiedFile: RawDir; static ENTRY_FILE_NAME = 'index.gmx' @@ -40,7 +40,7 @@ export class Project implements ProjectData { return new Project(data.title, data.sprite, data.sound, data.backdrop, data.entryCode, data.UnidentifiedFile) } - constructor(title: string, sprite: SpriteList = new SpriteList(), sound: SoundList = new SoundList(), backdrop: Backdrop = new Backdrop(), entryCode: string = "", UnidentifiedFile: rawDir = {}) { + constructor(title: string, sprite: SpriteList = new SpriteList(), sound: SoundList = new SoundList(), backdrop: Backdrop = new Backdrop(), entryCode: string = "", UnidentifiedFile: RawDir = {}) { this.title = title this.sprite = sprite this.sound = sound @@ -66,7 +66,7 @@ export class Project implements ProjectData { async load(arg: string | File, title?: string): Promise { if (typeof arg === 'string') { const paths = await fs.readdir(arg) as string[] - const dirPath: dirPath = {} + const dirPath: DirPath = {} for (const path of paths) { const content = await fs.readFile(path) as FileType dirPath[path] = content @@ -80,9 +80,9 @@ export class Project implements ProjectData { /** * Load project from directory. - * @param dirPath The directory + * @param DirPath The directory */ - private _load(dirPath: dirPath): void; + private _load(dirPath: DirPath): void; /** * Load project. @@ -90,7 +90,7 @@ export class Project implements ProjectData { */ private _load(proj: Project): void; - private _load(arg: dirPath | Project): void { + private _load(arg: DirPath | Project): void { if (typeof arg === 'object' && arg instanceof Project) { this.title = arg.title this.sprite = arg.sprite @@ -126,8 +126,8 @@ export class Project implements ProjectData { } get rawDir() { - const dir: rawDir = {} - const files: rawDir = Object.assign({}, this.UnidentifiedFile, ...[this.backdrop, ...this.sprite.list, ...this.sound.list].map(item => item.dir)) + const dir: RawDir = {} + const files: RawDir = Object.assign({}, this.UnidentifiedFile, ...[this.backdrop, ...this.sprite.list, ...this.sound.list].map(item => item.dir)) files[Project.ENTRY_FILE_NAME] = this.entryCode for (const [path, value] of Object.entries(files)) { const fullPath = this.path + path @@ -136,7 +136,7 @@ export class Project implements ProjectData { return dir } - get dirPath(): Promise { + get dirPath(): Promise { return convertRawDirToDirPath(this.rawDir) } } diff --git a/spx-gui/src/types/file.ts b/spx-gui/src/types/file.ts index cdebf280..795e9298 100644 --- a/spx-gui/src/types/file.ts +++ b/spx-gui/src/types/file.ts @@ -7,25 +7,8 @@ * @Description: The type of file. */ -import Sprite from "@/class/sprite" -import Sound from "@/class/sound" -import Backdrop from "@/class/backdrop" import type { Config } from "@/interface/file" -export type codeType = { - path: string, - content: string -} - -export interface projectType { - title: string, - sprites: Sprite[], - sounds: Sound[], - backdrop: Backdrop, - defaultDir: dirPath, - code: codeType -} - export interface FileType { content: ArrayBuffer, path: string, @@ -34,16 +17,12 @@ export interface FileType { modifyTime: Date } -export interface dirPath { +export interface DirPath { [path: string]: FileType } -export type rawFile = string | File | Config - -export interface rawDir { - [path: string]: rawFile -} +export type RawFile = string | File | Config -export interface directory { - [path: string]: File +export interface RawDir { + [path: string]: RawFile } \ No newline at end of file diff --git a/spx-gui/src/util/class.ts b/spx-gui/src/util/class.ts index ce17a4ba..edfe5a7f 100644 --- a/spx-gui/src/util/class.ts +++ b/spx-gui/src/util/class.ts @@ -7,7 +7,7 @@ * @Description: The util of class. */ -import AssetBase from "@/class/AssetBase"; +import { AssetBase } from "@/class/asset-base"; import localforage from "localforage"; /** diff --git a/spx-gui/src/util/FileSystem.ts b/spx-gui/src/util/file-system.ts similarity index 100% rename from spx-gui/src/util/FileSystem.ts rename to spx-gui/src/util/file-system.ts diff --git a/spx-gui/src/util/file.ts b/spx-gui/src/util/file.ts index 329a8a79..4923952c 100644 --- a/spx-gui/src/util/file.ts +++ b/spx-gui/src/util/file.ts @@ -55,7 +55,7 @@ export const getMimeFromExt = (ext: string) => ext2mime[ext] || 'text/plain' * @param name the file name * @returns the content */ -export const ArrayBuffer2Content = (arr: ArrayBuffer, type: string, name: string = 'untitled'): rawFile => { +export const arrayBuffer2Content = (arr: ArrayBuffer, type: string, name: string = 'untitled'): RawFile => { switch (type) { case 'application/json': return JSON.parse(new TextDecoder().decode(arr)) @@ -72,7 +72,7 @@ export const ArrayBuffer2Content = (arr: ArrayBuffer, type: string, name: string * @param type the mime type * @returns the array buffer */ -export const Content2ArrayBuffer = async (content: any, type: string): Promise => { +export const content2ArrayBuffer = async (content: any, type: string): Promise => { switch (type) { case 'application/json': return new TextEncoder().encode(JSON.stringify(content)) @@ -104,11 +104,11 @@ export function getPrefix(dir: Record) { } import { Project } from "@/store/modules/project" -import Backdrop from "@/class/backdrop" -import Sound from "@/class/sound" -import Sprite from "@/class/sprite" +import { Backdrop } from "@/class/backdrop" +import { Sound } from "@/class/sound" +import { Sprite } from "@/class/sprite" import type { Config } from "@/interface/file" -import type{ FileType, dirPath, rawDir, rawFile } from "@/types/file" +import type { FileType, DirPath, RawDir, RawFile } from "@/types/file" import JSZip from "jszip" /** @@ -118,11 +118,11 @@ export function genFile(content: string, type: string, name: string) { return new File([new Blob([content], { type })], name) } -export async function convertRawDirToDirPath(dir: rawDir): Promise { - const directory: dirPath = {} +export async function convertRawDirToDirPath(dir: RawDir): Promise { + const directory: DirPath = {} for (const [path, value] of Object.entries(dir)) { const ext = path.split('.').pop()! - const content = await Content2ArrayBuffer(value, getMimeFromExt(ext)) + const content = await content2ArrayBuffer(value, getMimeFromExt(ext)) directory[path] = { content, path, @@ -137,7 +137,7 @@ export async function convertRawDirToDirPath(dir: rawDir): Promise { /** * Get directory from zip file. * @param {File} zipFile the zip file - * @returns {Promise} the directory of the zip + * @returns {Promise} the directory of the zip * * @example * const dir = await getDirPathFromZip(zipFile) @@ -166,10 +166,10 @@ export async function convertRawDirToDirPath(dir: rawDir): Promise { * ├─ 5.png * └─ index.json */ -export async function getDirPathFromZip(zipFile: File, title?: string): Promise { +export async function getDirPathFromZip(zipFile: File, title?: string): Promise { const zip = await JSZip.loadAsync(zipFile); const projectName = title || zipFile.name.split('.')[0] || 'project'; - const dir: dirPath = {}; + const dir: DirPath = {}; const prefix = getPrefix(zip.files) for (let [relativePath, zipEntry] of Object.entries(zip.files)) { if (zipEntry.dir) continue @@ -193,17 +193,17 @@ const UNTITLED_NAME = 'untitled'; /** * Parse directory to project. - * @param {dirPath} dir + * @param {DirPath} dir * @returns project */ -export function convertDirPathToProject(dir: dirPath): Project { +export function convertDirPathToProject(dir: DirPath): Project { function handleFile(file: FileType, filename: string, item: any) { switch (file.type) { case 'application/json': - item.config = ArrayBuffer2Content(file.content, file.type) as Config; + item.config = arrayBuffer2Content(file.content, file.type) as Config; break; default: - item.files.push(ArrayBuffer2Content(file.content, file.type, filename) as File); + item.files.push(arrayBuffer2Content(file.content, file.type, filename) as File); break; } } @@ -228,12 +228,12 @@ export function convertDirPathToProject(dir: dirPath): Project { handleFile(file, filename, sprite); } else if (/^(main|index)\.(spx|gmx)$/.test(path)) { - proj.entryCode = ArrayBuffer2Content(file.content, file.type, filename) as string + proj.entryCode = arrayBuffer2Content(file.content, file.type, filename) as string } else if (/^.+\.spx$/.test(path)) { const spriteName = path.match(/^(.+)\.spx$/)?.[1] || ''; const sprite: Sprite = findOrCreateItem(spriteName, proj.sprite.list, Sprite); - sprite.code = ArrayBuffer2Content(file.content, file.type) as string; + sprite.code = arrayBuffer2Content(file.content, file.type) as string; } else if (Sound.REG_EXP.test(path)) { const soundName = path.match(Sound.REG_EXP)?.[1] || ''; @@ -244,13 +244,13 @@ export function convertDirPathToProject(dir: dirPath): Project { handleFile(file, filename, proj.backdrop); } else { - proj.UnidentifiedFile[path] = ArrayBuffer2Content(file.content, file.type, filename) + proj.UnidentifiedFile[path] = arrayBuffer2Content(file.content, file.type, filename) } } return proj } -const zipFileValue = (key: string, value: rawFile): [string, string | File] => { +const zipFileValue = (key: string, value: RawFile): [string, string | File] => { if (typeof value === 'string' || value instanceof File) { return [key, value] } else { @@ -263,7 +263,7 @@ const zipFileValue = (key: string, value: rawFile): [string, string | File] => { * @param dir the directory object with raw files to be converted * @returns the zip */ -export async function convertRawDirToZip(dir: rawDir): Promise { +export async function convertRawDirToZip(dir: RawDir): Promise { const zip = new JSZip(); const prefix = getPrefix(dir) diff --git a/spx-gui/src/util/wasm.ts b/spx-gui/src/util/wasm.ts deleted file mode 100644 index 92e944b5..00000000 --- a/spx-gui/src/util/wasm.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * @Author: TuGitee tgb@std.uestc.edu.cn - * @Date: 2024-01-22 10:28:03 - * @LastEditors: TuGitee tgb@std.uestc.edu.cn - * @LastEditTime: 2024-01-24 08:50:56 - * @FilePath: \builder\spx-gui\src\util\wasm.ts - * @Description: A util to load and save wasm. - */ - -import JSzip from "jszip"; -import localforage from "localforage"; - -/** - * A localforage instance. It is an instance of localforage with name "wasm". - */ -const storage = localforage.createInstance({ - name: "wasm", - storeName: "wasm" -}) - -/** - * Read wasm from zip. - * @param zip the zip - * @returns the wasm buffer - */ -export const readWasmFromZip = async (zip: Blob): Promise => { - const zipFile = await JSzip.loadAsync(zip); - const arrayBuffer = await Object.values(zipFile.files)[0]?.async("arraybuffer"); - return new Uint8Array(arrayBuffer); -} - -/** - * Read wasm from url. The url should be a wasm file. - * @param url the url - * @returns the wasm buffer - */ -export const readWasmFromURL = async (url: string): Promise => { - const response = await fetch(url); - const arrayBuffer = await response.arrayBuffer(); - return new Uint8Array(arrayBuffer); -} - -/** - * Save wasm to storage (IndexedDB). - * @param buffer the wasm buffer - * @param name the name of the wasm - */ -export const saveWasm = async (buffer: Uint8Array, name: string = "main.wasm") => { - storage.setItem(name, buffer); -} - -/** - * Read wasm from storage (IndexedDB). - * @param name the name of the wasm - * @returns the wasm buffer - */ -export const readWasmFromStorage = async (name: string = "main.wasm") => { - const buffer = await storage.getItem(name) as Uint8Array; - return buffer || null; -} - -/** - * Init wasm. - * @param buffer the wasm buffer - */ -export const initWasm = async (buffer: Uint8Array) => { - // TODO: reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate and builder/offlineSpx/main.html - // const wasm = await WebAssembly.instantiate(buffer, importObject); -} \ No newline at end of file diff --git a/spx-gui/src/view/demo.vue b/spx-gui/src/view/demo.vue deleted file mode 100644 index e35c007d..00000000 --- a/spx-gui/src/view/demo.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - \ No newline at end of file