remove debug prints, axe testbed-only APIs
This commit is contained in:
parent
f720acc738
commit
b6b069450d
3 changed files with 103 additions and 119 deletions
|
@ -13,39 +13,40 @@ function dwAlign(off: number): number {
|
||||||
return ul;
|
return ul;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// animation state (used during animation playback)
|
||||||
class AgentAnimationState {
|
class AgentAnimationState {
|
||||||
char: Agent;
|
char: Agent;
|
||||||
anim: AcsAnimation;
|
anim: AcsAnimation;
|
||||||
|
|
||||||
finishCallback: () => void;
|
finishCallback: () => void;
|
||||||
frameIndex = 0;
|
frameIndex = 0;
|
||||||
|
|
||||||
interval = 0;
|
interval = 0;
|
||||||
|
|
||||||
constructor(char: Agent, anim: AcsAnimation, finishCallback: () => void) {
|
constructor(char: Agent, anim: AcsAnimation, finishCallback: () => void) {
|
||||||
this.char = char;
|
this.char = char;
|
||||||
this.anim = anim;
|
this.anim = anim;
|
||||||
this.finishCallback = finishCallback;
|
this.finishCallback = finishCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
// start playing the animation
|
// start playing the animation
|
||||||
play() {
|
play() {
|
||||||
this.nextFrame();
|
this.nextFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
nextFrame() {
|
nextFrame() {
|
||||||
this.char.renderFrame(this.anim.frameInfo[this.frameIndex++]);
|
this.char.renderFrame(this.anim.frameInfo[this.frameIndex++]);
|
||||||
|
|
||||||
if(this.frameIndex >= this.anim.frameInfo.length) {
|
if (this.frameIndex >= this.anim.frameInfo.length) {
|
||||||
this.finishCallback();
|
this.finishCallback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//@ts-ignore
|
|
||||||
this.interval = setTimeout(() => {
|
|
||||||
this.nextFrame();
|
|
||||||
}, this.anim.frameInfo[this.frameIndex].frameDuration * 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
this.interval = setTimeout(() => {
|
||||||
|
this.nextFrame();
|
||||||
|
}, this.anim.frameInfo[this.frameIndex].frameDuration * 10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Agent {
|
export class Agent {
|
||||||
|
@ -53,11 +54,11 @@ export class Agent {
|
||||||
private cnv: HTMLCanvasElement;
|
private cnv: HTMLCanvasElement;
|
||||||
private ctx: CanvasRenderingContext2D;
|
private ctx: CanvasRenderingContext2D;
|
||||||
|
|
||||||
private dragging: boolean;
|
private dragging: boolean;
|
||||||
private x: number;
|
private x: number;
|
||||||
private y: number;
|
private y: number;
|
||||||
|
|
||||||
private animState: AgentAnimationState | null = null;
|
private animState: AgentAnimationState | null = null;
|
||||||
|
|
||||||
constructor(data: AcsData) {
|
constructor(data: AcsData) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
@ -68,44 +69,48 @@ export class Agent {
|
||||||
this.cnv.style.position = 'fixed';
|
this.cnv.style.position = 'fixed';
|
||||||
this.cnv.style.display = 'none';
|
this.cnv.style.display = 'none';
|
||||||
|
|
||||||
this.dragging = false;
|
this.dragging = false;
|
||||||
this.x = 0;
|
this.x = 0;
|
||||||
this.y = 0;
|
this.y = 0;
|
||||||
this.setLoc();
|
this.setLoc();
|
||||||
this.cnv.addEventListener('mousedown', () => {
|
this.cnv.addEventListener('mousedown', () => {
|
||||||
this.dragging = true;
|
this.dragging = true;
|
||||||
document.addEventListener('mouseup', () => {
|
document.addEventListener(
|
||||||
this.dragging = false;
|
'mouseup',
|
||||||
}, {once: true});
|
() => {
|
||||||
});
|
this.dragging = false;
|
||||||
document.addEventListener('mousemove', e => {
|
},
|
||||||
if (!this.dragging) return;
|
{ once: true }
|
||||||
this.x += e.movementX;
|
);
|
||||||
this.y += e.movementY;
|
});
|
||||||
this.setLoc();
|
document.addEventListener('mousemove', (e) => {
|
||||||
});
|
if (!this.dragging) return;
|
||||||
window.addEventListener('resize', () => {
|
this.x += e.movementX;
|
||||||
this.setLoc();
|
this.y += e.movementY;
|
||||||
});
|
this.setLoc();
|
||||||
|
});
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
this.setLoc();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private setLoc() {
|
private setLoc() {
|
||||||
if (this.x < 0) this.x = 0;
|
if (this.x < 0) this.x = 0;
|
||||||
if (this.y < 0) this.y = 0;
|
if (this.y < 0) this.y = 0;
|
||||||
if (this.x > document.documentElement.clientWidth - this.cnv.width) this.x = document.documentElement.clientWidth - this.cnv.width;
|
if (this.x > document.documentElement.clientWidth - this.cnv.width) this.x = document.documentElement.clientWidth - this.cnv.width;
|
||||||
if (this.y > document.documentElement.clientHeight - this.cnv.height) this.y = document.documentElement.clientHeight - this.cnv.height;
|
if (this.y > document.documentElement.clientHeight - this.cnv.height) this.y = document.documentElement.clientHeight - this.cnv.height;
|
||||||
this.cnv.style.top = this.y + "px";
|
this.cnv.style.top = this.y + 'px';
|
||||||
this.cnv.style.left = this.x + "px";
|
this.cnv.style.left = this.x + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFrame(frame: AcsAnimationFrameInfo) {
|
renderFrame(frame: AcsAnimationFrameInfo) {
|
||||||
this.ctx.clearRect(0, 0, this.cnv.width, this.cnv.height);
|
this.ctx.clearRect(0, 0, this.cnv.width, this.cnv.height);
|
||||||
for (const mimg of frame.images) {
|
for (const mimg of frame.images) {
|
||||||
this.drawImage(this.data.images[mimg.imageIndex], mimg.xOffset, mimg.yOffset);
|
this.drawImage(this.data.images[mimg.imageIndex], mimg.xOffset, mimg.yOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a single image from the agent's image table.
|
// Draw a single image from the agent's image table.
|
||||||
drawImage(imageEntry: AcsImageEntry, xOffset: number, yOffset: number) {
|
drawImage(imageEntry: AcsImageEntry, xOffset: number, yOffset: number) {
|
||||||
let rgbaBuffer = new Uint32Array(imageEntry.image.width * imageEntry.image.height);
|
let rgbaBuffer = new Uint32Array(imageEntry.image.width * imageEntry.image.height);
|
||||||
|
|
||||||
|
@ -114,20 +119,20 @@ export class Agent {
|
||||||
|
|
||||||
let rows = new Array<Uint8Array>(imageEntry.image.height - 1);
|
let rows = new Array<Uint8Array>(imageEntry.image.height - 1);
|
||||||
|
|
||||||
// Read all the rows bottom-up first. This idiosyncracy is due to the fact
|
// Read all the rows bottom-up first. This idiosyncracy is due to the fact
|
||||||
// that the bitmap data is actually formatted to be used as a GDI DIB
|
// that the bitmap data is actually formatted to be used as a GDI DIB
|
||||||
// (device-independent bitmap), so it inherits all the strange baggage from that.
|
// (device-independent bitmap), so it inherits all the strange baggage from that.
|
||||||
for (let y = imageEntry.image.height - 1; y >= 0; --y) {
|
for (let y = imageEntry.image.height - 1; y >= 0; --y) {
|
||||||
let row = bufStream.subBuffer(imageEntry.image.width).raw();
|
let row = bufStream.subBuffer(imageEntry.image.width).raw();
|
||||||
let rowResized = row.slice(0, imageEntry.image.width);
|
let rowResized = row.slice(0, imageEntry.image.width);
|
||||||
rows[y] = rowResized;
|
rows[y] = rowResized;
|
||||||
|
|
||||||
// Seek to the next DWORD aligned spot to get to the next row.
|
// Seek to the next DWORD aligned spot to get to the next row.
|
||||||
// For most images this may mean not seeking at all.
|
// For most images this may mean not seeking at all.
|
||||||
bufStream.seek(dwAlign(bufStream.tell()), SeekDir.BEG);
|
bufStream.seek(dwAlign(bufStream.tell()), SeekDir.BEG);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next, draw the rows converted to RGBA, top down (so it's drawn as you'd expect)
|
// Next, draw the rows converted to RGBA, top down (so it's drawn as you'd expect)
|
||||||
for (let y = 0; y < imageEntry.image.height - 1; ++y) {
|
for (let y = 0; y < imageEntry.image.height - 1; ++y) {
|
||||||
let row = rows[y];
|
let row = rows[y];
|
||||||
for (let x = 0; x < imageEntry.image.width; ++x) {
|
for (let x = 0; x < imageEntry.image.width; ++x) {
|
||||||
|
@ -143,46 +148,41 @@ export class Agent {
|
||||||
parent.appendChild(this.cnv);
|
parent.appendChild(this.cnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove() {
|
remove() {
|
||||||
this.cnv.parentElement?.removeChild(this.cnv);
|
this.cnv.parentElement?.removeChild(this.cnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add promise versions later.
|
// add promise versions later.
|
||||||
playAnimation(index: number, finishCallback: () => void) {
|
playAnimation(index: number, finishCallback: () => void) {
|
||||||
if(this.animState != null)
|
if (this.animState != null) throw new Error('Cannot play multiple animations at once.');
|
||||||
throw new Error('Cannot play multiple animations at once.');
|
let animInfo = this.data.animInfo[index];
|
||||||
let animInfo = this.data.animInfo[index];
|
|
||||||
|
|
||||||
// Create and start the animation state
|
// Create and start the animation state
|
||||||
this.animState = new AgentAnimationState(this, animInfo.animationData, () => {
|
this.animState = new AgentAnimationState(this, animInfo.animationData, () => {
|
||||||
this.animationFinished();
|
this.animationFinished();
|
||||||
finishCallback();
|
finishCallback();
|
||||||
});
|
});
|
||||||
this.animState.play();
|
this.animState.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
playAnimationByName(name: String, finishCallback: () => void) {
|
playAnimationByName(name: String, finishCallback: () => void) {
|
||||||
let index = this.data.animInfo.findIndex((n) => n.name == name);
|
let index = this.data.animInfo.findIndex((n) => n.name == name);
|
||||||
if(index !== -1)
|
if (index !== -1) this.playAnimation(index, finishCallback);
|
||||||
this.playAnimation(index, finishCallback);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
animationFinished() {
|
animationFinished() {
|
||||||
this.animState = null;
|
this.animState = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
show() {
|
show() {
|
||||||
this.cnv.style.display = 'block';
|
this.cnv.style.display = 'block';
|
||||||
this.playAnimationByName("Show", () => {});
|
this.playAnimationByName('Show', () => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
hide(remove: boolean = false) {
|
hide(remove: boolean = false) {
|
||||||
this.playAnimationByName("Hide", () => {
|
this.playAnimationByName('Hide', () => {
|
||||||
if(remove)
|
if (remove) this.remove();
|
||||||
this.remove();
|
else this.cnv.style.display = 'none';
|
||||||
else
|
});
|
||||||
this.cnv.style.display = 'none';
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,19 +6,14 @@ import { AcsAnimationEntry } from './structs/animation.js';
|
||||||
import { AcsImageEntry } from './structs/image.js';
|
import { AcsImageEntry } from './structs/image.js';
|
||||||
import { Agent } from './agent.js';
|
import { Agent } from './agent.js';
|
||||||
|
|
||||||
// Experiment for storing parsed data
|
// Data
|
||||||
export class AcsData {
|
export class AcsData {
|
||||||
characterInfo = new AcsCharacterInfo();
|
characterInfo = new AcsCharacterInfo();
|
||||||
animInfo: AcsAnimationEntry[] = [];
|
animInfo: AcsAnimationEntry[] = [];
|
||||||
images: AcsImageEntry[] = [];
|
images: AcsImageEntry[] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function logOffset(o: number, name: string) {
|
function agentCharacterParseACS(buffer: BufferStream): AcsData {
|
||||||
let n = o >>> 0;
|
|
||||||
console.log(name, 'offset:', '0x' + n.toString(16));
|
|
||||||
}
|
|
||||||
|
|
||||||
function agentCharacterParseACS(buffer: BufferStream) {
|
|
||||||
// Make sure the magic is correct for the ACS file.
|
// Make sure the magic is correct for the ACS file.
|
||||||
if (buffer.readU32LE() != 0xabcdabc3) {
|
if (buffer.readU32LE() != 0xabcdabc3) {
|
||||||
throw new Error('The provided data buffer does not contain valid ACS data.');
|
throw new Error('The provided data buffer does not contain valid ACS data.');
|
||||||
|
@ -32,10 +27,6 @@ function agentCharacterParseACS(buffer: BufferStream) {
|
||||||
let imageInfoLocation = LOCATION.read(buffer);
|
let imageInfoLocation = LOCATION.read(buffer);
|
||||||
let audioInfoLocation = LOCATION.read(buffer);
|
let audioInfoLocation = LOCATION.read(buffer);
|
||||||
|
|
||||||
logOffset(characterInfoLocation.offset, 'character info');
|
|
||||||
logOffset(animationInfoLocation.offset, 'animation info');
|
|
||||||
logOffset(imageInfoLocation.offset, 'image info');
|
|
||||||
logOffset(audioInfoLocation.offset, 'audio info');
|
|
||||||
|
|
||||||
buffer.withOffset(characterInfoLocation.offset, () => {
|
buffer.withOffset(characterInfoLocation.offset, () => {
|
||||||
acsData.characterInfo = AcsCharacterInfo.read(buffer);
|
acsData.characterInfo = AcsCharacterInfo.read(buffer);
|
||||||
|
@ -53,19 +44,12 @@ function agentCharacterParseACS(buffer: BufferStream) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(acsData);
|
|
||||||
return acsData;
|
return acsData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the testbed code only, remove when that gets axed
|
|
||||||
// (or don't, I'm not your dad)
|
|
||||||
export function agentParseCharacterTestbed(buffer: Uint8Array) {
|
|
||||||
return new Agent(agentCharacterParseACS(new BufferStream(buffer)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO this will be the public API
|
// TODO this will be the public API
|
||||||
// Dunno about maintaining canvases. We can pass a div into agentInit and add a characterInit() which recieves it
|
// Dunno about maintaining canvases. We can pass a div into agentInit and add a characterInit() which recieves it
|
||||||
// (which we then mount characters and their wordballoons into?)
|
// (which we then mount characters and their wordballoons into?)
|
||||||
export function agentCreateCharacter(data: Uint8Array): Promise<void> {
|
export function agentCreateCharacter(data: Uint8Array): Agent {
|
||||||
throw new Error('Not implemented yet');
|
return new Agent(agentCharacterParseACS(new BufferStream(data)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ let input = document.getElementById("testbed-input") as HTMLInputElement;
|
||||||
input.addEventListener("change", async () => {
|
input.addEventListener("change", async () => {
|
||||||
let buffer = await input.files![0].arrayBuffer();
|
let buffer = await input.files![0].arrayBuffer();
|
||||||
|
|
||||||
console.log("About to parse character");
|
console.log("Creating agent");
|
||||||
let agent = msagent.agentParseCharacterTestbed(new Uint8Array(buffer));
|
let agent = msagent.agentCreateCharacter(new Uint8Array(buffer));
|
||||||
|
|
||||||
// destroy the previous agent
|
// destroy the previous agent
|
||||||
if(w.agent != null) {
|
if(w.agent != null) {
|
||||||
|
@ -20,7 +20,7 @@ input.addEventListener("change", async () => {
|
||||||
agent.addToDom(document.body);
|
agent.addToDom(document.body);
|
||||||
|
|
||||||
agent.show();
|
agent.show();
|
||||||
console.log("parsed character");
|
console.log("Agent created");
|
||||||
})
|
})
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", async () => {
|
document.addEventListener("DOMContentLoaded", async () => {
|
||||||
|
|
Loading…
Reference in a new issue