Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement decal parsing and API #99

Merged
merged 1 commit into from
Oct 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions lib/vpt/decal/decal-api.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* VPDB - Virtual Pinball Database
* Copyright (C) 2019 freezy <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

import * as chai from 'chai';
import { expect } from 'chai';
import sinonChai = require('sinon-chai');
import { ThreeHelper } from '../../../test/three.helper';
import { Player } from '../../game/player';
import { NodeBinaryReader } from '../../io/binary-reader.node';
import { DecalType, ImageAlignment, SizingType } from '../enums';
import { Table } from '../table/table';

/* tslint:disable:no-unused-expression */
chai.use(sinonChai);
const three = new ThreeHelper();

describe('The VPinball decal API', () => {

let table: Table;
let player: Player;

beforeEach(async () => {
table = await Table.load(new NodeBinaryReader(three.fixturePath('table-decal.vpx')));
player = new Player(table).init();
});

it('should correctly read and write the properties', async () => {
const decal = table.decals.Decal001.getApi();

decal.Rotation = 128;
decal.Image = 'test_pattern';
decal.Width = 1685;
decal.Height = 115;
decal.X = 304;
decal.Y = 1.8;
decal.Surface = 'surface';
decal.Type = DecalType.Image; expect(decal.Type).to.equal(DecalType.Image);
decal.Type = DecalType.Text;
decal.Text = 'Text';
decal.SizingType = SizingType.AutoSize; expect(decal.SizingType).to.equal(SizingType.AutoSize);
decal.SizingType = SizingType.AutoWidth;
decal.FontColor = 0x913a8d;
decal.Material = 'Material';
decal.Font = 'Font';
decal.HasVerticalText = true; expect(decal.HasVerticalText).to.equal(true);
decal.HasVerticalText = false;

expect(decal.Rotation).to.equal(128);
expect(decal.Image).to.equal('test_pattern');
expect(decal.Width).to.equal(1685);
expect(decal.Height).to.equal(115);
expect(decal.X).to.equal(304);
expect(decal.Y).to.be.closeTo(1.8, 0.0001);
expect(decal.Surface).to.equal('surface');
expect(decal.Type).to.equal(DecalType.Text);
expect(decal.Text).to.equal('Text');
expect(decal.SizingType).to.equal(SizingType.AutoWidth);
expect(decal.FontColor).to.equal(0x913a8d);
expect(decal.Material).to.equal('Material');
expect(decal.Font).to.equal('Font');
expect(decal.HasVerticalText).to.equal(false);
});

});
54 changes: 54 additions & 0 deletions lib/vpt/decal/decal-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* VPDB - Virtual Pinball Database
* Copyright (C) 2019 freezy <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

import { ItemApi } from '../item-api';
import { DecalData } from './decal-data';

export class DecalApi extends ItemApi<DecalData> {

get Rotation() { return this.data.rotation; }
set Rotation(v) { this.data.rotation = v; }
get Image() { return this.data.szImage; }
set Image(v) { this._assertNonHdrImage(v); this.data.szImage = v; }
get Width() { return this.data.width; }
set Width(v) { this.data.width = v; }
get Height() { return this.data.height; }
set Height(v) { this.data.height = v; }
get X() { return this.data.center.x; }
set X(v) { this.data.center.x = v; }
get Y() { return this.data.center.y; }
set Y(v) { this.data.center.y = v; }
get Surface() { return this.data.szSurface; }
set Surface(v) { this.data.szSurface = v; }
get Type() { return this.data.decalType; }
set Type(v) { this.data.decalType = v; }
get Text() { return this.data.text; }
set Text(v) { this.data.text = v; }
get SizingType() { return this.data.sizingType; }
set SizingType(v) { this.data.sizingType = v; }
get FontColor() { return this.data.color; }
set FontColor(v) { this.data.color = v; }
get Material() { return this.data.szMaterial; }
set Material(v) { this.data.szMaterial = v; }
get Font() { return this.data.font; }
set Font(v) { this.data.font = v; }
get HasVerticalText() { return this.data.verticalText; }
set HasVerticalText(v) { this.data.verticalText = v; }

}
78 changes: 78 additions & 0 deletions lib/vpt/decal/decal-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* VPDB - Virtual Pinball Database
* Copyright (C) 2019 freezy <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

import { BiffParser } from '../../io/biff-parser';
import { Storage } from '../../io/ole-doc';
import { Vertex2D } from '../../math/vertex2d';
import { DecalType, SizingType } from '../enums';
import { ItemData } from '../item-data';

export class DecalData extends ItemData {

public center!: Vertex2D;
public width: number = 100.0;
public height: number = 100.0;
public rotation: number = 0.0;
public szImage?: string;
public szSurface?: string;
public text?: string;
public decalType: number = DecalType.Image;
public sizingType: number = SizingType.ManualSize;
public color: number = 0x000000;
public szMaterial?: string;
public verticalText: boolean = false;
private backglass: boolean = false;

public font: string = '';

public static async fromStorage(storage: Storage, itemName: string): Promise<DecalData> {
const decalData = new DecalData(itemName);
await storage.streamFiltered(itemName, 4, BiffParser.stream(decalData.fromTag.bind(decalData), {
streamedTags: [ 'FONT' ],
}));
return decalData;
}

private constructor(itemName: string) {
super(itemName);
}

private async fromTag(buffer: Buffer, tag: string, offset: number, len: number): Promise<number> {
switch (tag) {
case 'VCEN': this.center = Vertex2D.get(buffer); break;
case 'WDTH': this.width = this.getFloat(buffer); break;
case 'HIGH': this.height = this.getFloat(buffer); break;
case 'ROTA': this.rotation = this.getFloat(buffer); break;
case 'IMAG': this.szImage = this.getString(buffer, len); break;
case 'SURF': this.szSurface = this.getString(buffer, len); break;
case 'TEXT': this.text = this.getString(buffer, len); break;
case 'TYPE': this.decalType = this.getInt(buffer); break;
case 'SIZE': this.sizingType = this.getInt(buffer); break;
case 'COLR': this.color = BiffParser.bgrToRgb(this.getInt(buffer)); break;
case 'MATR': this.szMaterial = this.getString(buffer, len); break;
case 'VERT': this.verticalText = this.getBool(buffer); break;
case 'BGLS': this.backglass = this.getBool(buffer); break;
case 'FONT': break; // don't care for now
default:
this.getCommonBlock(buffer, tag, len);
break;
}
return 0;
}
}
54 changes: 54 additions & 0 deletions lib/vpt/decal/decal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* VPDB - Virtual Pinball Database
* Copyright (C) 2019 freezy <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

import { EventProxy } from '../../game/event-proxy';
import { IScriptable } from '../../game/iscriptable';
import { Player } from '../../game/player';
import { Storage } from '../../io/ole-doc';
import { Item } from '../item';
import { Table } from '../table/table';
import { DecalApi } from './decal-api';
import { DecalData } from './decal-data';

export class Decal extends Item<DecalData> implements IScriptable<DecalApi> {

private api?: DecalApi;

public static async fromStorage(storage: Storage, itemName: string): Promise<Decal> {
const data = await DecalData.fromStorage(storage, itemName);
return new Decal(data);
}

private constructor(data: DecalData) {
super(data);
}

public setupPlayer(player: Player, table: Table): void {
this.events = new EventProxy(this);
this.api = new DecalApi(this.data, this.events, player, table);
}

public getApi(): DecalApi {
return this.api!;
}

public getEventNames(): string[] {
return [];
}
}
11 changes: 11 additions & 0 deletions lib/vpt/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,14 @@ export class TextAlignment {
public static readonly Center = 1;
public static readonly Right = 2;
}

export class DecalType {
public static readonly Text = 0;
public static readonly Image = 1;
}

export class SizingType {
public static readonly AutoSize = 0;
public static readonly AutoWidth = 1;
public static readonly ManualSize = 2;
}
9 changes: 9 additions & 0 deletions lib/vpt/table/table-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { Timer } from '../timer/timer';
import { Trigger } from '../trigger/trigger';
import { TableLoadOptions } from './table';
import { TableData } from './table-data';
import { Decal } from '../decal/decal';

export class TableLoader {

Expand Down Expand Up @@ -124,6 +125,7 @@ export class TableLoader {
loadedTable.timers = [];
loadedTable.plungers = [];
loadedTable.textBoxes = [];
loadedTable.decals = [];

// go through all game items
for (let i = 0; i < numItems; i++) {
Expand Down Expand Up @@ -246,6 +248,12 @@ export class TableLoader {
return item;
}

case ItemType.Decal: {
const item = await Decal.fromStorage(storage, itemName);
loadedTable.decals!.push(item);
return item;
}

default:
// ignore the rest for now
return null;
Expand Down Expand Up @@ -307,6 +315,7 @@ export interface LoadedTable {
spinners?: Spinner[];
plungers?: Plunger[];
textBoxes?: Textbox[];
decals?: Decal[];

timers?: Timer[];
}
3 changes: 3 additions & 0 deletions lib/vpt/table/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import { TableExportOptions } from './table-exporter';
import { TableHitGenerator } from './table-hit-generator';
import { LoadedTable, TableLoader } from './table-loader';
import { TableMeshGenerator } from './table-mesh-generator';
import { Decal } from '../decal/decal';

/**
* A Visual Pinball table.
Expand Down Expand Up @@ -100,6 +101,7 @@ export class Table implements IScriptable<TableApi> {
public readonly textboxes: { [key: string]: Textbox } = {};
public readonly timers: { [key: string]: Timer } = {};
public readonly triggers: { [key: string]: Trigger } = {};
public readonly decals: { [key: string]: Decal } = {};

private readonly meshGenerator?: TableMeshGenerator;
private readonly hitGenerator?: TableHitGenerator;
Expand Down Expand Up @@ -147,6 +149,7 @@ export class Table implements IScriptable<TableApi> {
[loadedTable.textBoxes, this.textboxes],
[loadedTable.timers, this.timers],
[loadedTable.triggers, this.triggers],
[loadedTable.decals, this.decals],
];
for (const m of mapping) {
if (isLoaded(m[0])) {
Expand Down
Binary file added test/fixtures/table-decal.vpx
Binary file not shown.