mirror of
https://github.com/litruv/picoGraph.git
synced 2026-07-24 02:36:04 +10:00
Add initial Pico-8 cartridges for testing
- Created test_cart.p8 with basic drawing functionality and a print statement. - Created test_unix.p8 with a simple initialization function.
This commit is contained in:
205
scripts/ui/SpriteEditorManager.js
Normal file
205
scripts/ui/SpriteEditorManager.js
Normal file
@@ -0,0 +1,205 @@
|
||||
import { SpriteEditor } from './SpriteEditor.js';
|
||||
import { SpriteSheet } from '../core/SpriteSheet.js';
|
||||
|
||||
/**
|
||||
* Manages the sprite editor modal integration.
|
||||
*/
|
||||
export class SpriteEditorManager {
|
||||
/**
|
||||
* @param {HTMLElement} modal Modal element.
|
||||
* @param {HTMLElement} container Container for sprite editor.
|
||||
*/
|
||||
constructor(modal, container) {
|
||||
this.modal = modal;
|
||||
this.container = container;
|
||||
this.spriteSheet = new SpriteSheet();
|
||||
this.editor = null;
|
||||
this.isOpen = false;
|
||||
|
||||
this.#setupModal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up modal event listeners.
|
||||
*/
|
||||
#setupModal() {
|
||||
// Close modal on backdrop click
|
||||
const backdrop = this.modal.querySelector('.modal__backdrop');
|
||||
backdrop?.addEventListener('click', () => this.close());
|
||||
|
||||
// Close modal on close button click
|
||||
const closeButtons = this.modal.querySelectorAll('[data-modal-close]');
|
||||
closeButtons.forEach((btn) => {
|
||||
btn.addEventListener('click', () => this.close());
|
||||
});
|
||||
|
||||
// Export to .p8
|
||||
const exportBtn = document.getElementById('exportP8Button');
|
||||
exportBtn?.addEventListener('click', () => this.#exportToP8());
|
||||
|
||||
// Import from .p8
|
||||
const importBtn = document.getElementById('importP8Button');
|
||||
importBtn?.addEventListener('click', () => this.#importFromP8());
|
||||
|
||||
// Initialize editor on first open
|
||||
this.modal.addEventListener('transitionend', () => {
|
||||
if (this.isOpen && !this.editor) {
|
||||
this.#initializeEditor();
|
||||
}
|
||||
}, { once: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the sprite editor.
|
||||
*/
|
||||
#initializeEditor() {
|
||||
if (this.editor) return;
|
||||
|
||||
this.editor = new SpriteEditor(this.container, this.spriteSheet);
|
||||
console.log('Sprite editor initialized');
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the sprite editor modal.
|
||||
*/
|
||||
open() {
|
||||
if (this.isOpen) return;
|
||||
|
||||
this.isOpen = true;
|
||||
this.modal.removeAttribute('hidden');
|
||||
this.modal.setAttribute('aria-hidden', 'false');
|
||||
document.body.classList.add('modal-open');
|
||||
|
||||
// Initialize editor immediately if not already done
|
||||
if (!this.editor) {
|
||||
this.#initializeEditor();
|
||||
}
|
||||
|
||||
// Focus trap
|
||||
requestAnimationFrame(() => {
|
||||
const closeBtn = this.modal.querySelector('[data-modal-close]');
|
||||
closeBtn?.focus();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the sprite editor modal.
|
||||
*/
|
||||
close() {
|
||||
if (!this.isOpen) return;
|
||||
|
||||
this.isOpen = false;
|
||||
this.modal.setAttribute('hidden', '');
|
||||
this.modal.setAttribute('aria-hidden', 'true');
|
||||
document.body.classList.remove('modal-open');
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports sprite data to .p8 format.
|
||||
*/
|
||||
#exportToP8() {
|
||||
if (!this.editor) return;
|
||||
|
||||
const gfxData = this.editor.getSpriteSheet().toP8Gfx();
|
||||
const flagData = this.editor.getSpriteSheet().toP8Flags();
|
||||
|
||||
const p8Content = `pico-8 cartridge // http://www.pico-8.com
|
||||
version 41
|
||||
__lua__
|
||||
-- generated by picoGraph
|
||||
-- paste your blueprinted code here
|
||||
|
||||
__gfx__
|
||||
${gfxData}
|
||||
__gff__
|
||||
${flagData}
|
||||
`;
|
||||
|
||||
const blob = new Blob([p8Content], { type: 'text/plain' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'sprites.p8';
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
|
||||
// Show success feedback
|
||||
const exportBtn = document.getElementById('exportP8Button');
|
||||
if (exportBtn) {
|
||||
exportBtn.classList.add('is-success');
|
||||
setTimeout(() => {
|
||||
exportBtn.classList.remove('is-success');
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports sprite data from .p8 format.
|
||||
*/
|
||||
#importFromP8() {
|
||||
if (!this.editor) return;
|
||||
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.accept = '.p8';
|
||||
|
||||
input.addEventListener('change', async (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
try {
|
||||
const text = await file.text();
|
||||
|
||||
// Extract __gfx__ section
|
||||
const gfxMatch = text.match(/__gfx__\s*\n([\s\S]*?)(?=\n__|$)/);
|
||||
if (gfxMatch) {
|
||||
this.editor.getSpriteSheet().fromP8Gfx(gfxMatch[1]);
|
||||
}
|
||||
|
||||
// Extract __gff__ section
|
||||
const gffMatch = text.match(/__gff__\s*\n([\s\S]*?)(?=\n__|$)/);
|
||||
if (gffMatch) {
|
||||
this.editor.getSpriteSheet().fromP8Flags(gffMatch[1]);
|
||||
}
|
||||
|
||||
// Re-render
|
||||
this.editor.setSpriteSheet(this.editor.getSpriteSheet());
|
||||
|
||||
// Show success feedback
|
||||
const importBtn = document.getElementById('importP8Button');
|
||||
if (importBtn) {
|
||||
importBtn.classList.add('is-success');
|
||||
setTimeout(() => {
|
||||
importBtn.classList.remove('is-success');
|
||||
}, 1500);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to import sprite data:', error);
|
||||
alert('Failed to import sprite data. Please ensure the file is a valid .p8 file.');
|
||||
}
|
||||
});
|
||||
|
||||
input.click();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current sprite sheet data.
|
||||
*
|
||||
* @returns {SpriteSheet}
|
||||
*/
|
||||
getSpriteSheet() {
|
||||
return this.spriteSheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets sprite sheet data.
|
||||
*
|
||||
* @param {SpriteSheet} spriteSheet New sprite sheet.
|
||||
*/
|
||||
setSpriteSheet(spriteSheet) {
|
||||
this.spriteSheet = spriteSheet;
|
||||
if (this.editor) {
|
||||
this.editor.setSpriteSheet(spriteSheet);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user