Skip to content

Commit

Permalink
Merge branch 'gh-pages' of https://github.com/LivelyKernel/lively4-core
Browse files Browse the repository at this point in the history
… into gh-pages
  • Loading branch information
JensLincke committed Sep 25, 2023
2 parents 855afd7 + 5e35fcd commit a2b5a8a
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 13 deletions.
14 changes: 14 additions & 0 deletions demos/stefan/untitled-board-game/ubg-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ export default class Card {
this.versions.last.cost = cost;
}

getBaseVP() {
return this.versions.last.baseVP;
}

setBaseVP(baseVP) {
this.ensureUnprintedVersion();

if (!baseVP) {
delete this.versions.last.baseVP;
} else {
this.versions.last.baseVP = baseVP;
}
}

getText() {
return this.versions.last.text;
}
Expand Down
5 changes: 4 additions & 1 deletion src/components/widgets/ubg-cards-editor.html
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,15 @@
#form-layout {
display: grid;
grid-template-columns: min-content auto 2.5in;
grid-template-rows: repeat(6, auto) 1fr .5fr auto;
grid-template-rows: repeat(7, auto) 1fr .5fr auto;
grid-template-areas:
"isPrinted-key isPrinted-value preview"
"id-key id-value preview"
"name-key name-value preview"
"type-key type-value preview"
"element-key element-value preview"
"cost-key cost-value preview"
"vp-key vp-value preview"
"text-key text-value preview"
"notes-key notes-value preview"
"art-key art-value preview"
Expand Down Expand Up @@ -216,6 +217,8 @@
<input id='element' class='value' style='grid-area: element-value;' />
<span class='key' style='grid-area: cost-key;'>cost</span>
<input id='cost' class='value' style='grid-area: cost-value;' />
<span class='key' style='grid-area: vp-key;'>base vp</span>
<input id='vp' class='value' style='grid-area: vp-value;' />
<span class='key' style='grid-area: text-key;'>text</span>
<textarea id='text' class='value' style='grid-area: text-value;'></textarea>
<span class='key' style='grid-area: notes-key;'>notes</span>
Expand Down
34 changes: 34 additions & 0 deletions src/components/widgets/ubg-cards-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default class UBGCardsEditor extends Morph {
this.$type.addEventListener(eventName, evt => this.modify$type(evt), false);
this.$element.addEventListener(eventName, evt => this.modify$element(evt), false);
this.$cost.addEventListener(eventName, evt => this.modify$cost(evt), false);
this.$vp.addEventListener(eventName, evt => this.modify$vp(evt), false);
this.$text.addEventListener(eventName, evt => this.modify$text(evt), false);
this.$notes.addEventListener(eventName, evt => this.modify$notes(evt), false);
this.$art.addEventListener(eventName, evt => this.modify$art(evt), false);
Expand Down Expand Up @@ -212,6 +213,9 @@ export default class UBGCardsEditor extends Morph {
get $cost() {
return this.get('#cost');
}
get $vp() {
return this.get('#vp');
}
get $text() {
return this.get('#text');
}
Expand Down Expand Up @@ -349,6 +353,35 @@ export default class UBGCardsEditor extends Morph {
this.$cost.value = cost;
}

modify$vp(evt) {
const vp = this.$vp.value;

if (vp === '') {
this.card.setBaseVP();
} else if ('*+-'.split('').some(char => vp.endsWith(char))) {
this.card.setBaseVP(vp);
} else {
const intCost = parseInt(vp);
if (_.isNaN(intCost)) {
this.card.setBaseVP();
} else {
this.card.setBaseVP(intCost);
}
}

this.propagateChange()
}
display$vp() {
const vp = this.card.getBaseVP();

if (vp === undefined) {
this.$vp.value = '';
return;
}

this.$vp.value = vp;
}

modify$text(evt) {
const text = this.$text.value;
if (text === '') {
Expand Down Expand Up @@ -444,6 +477,7 @@ export default class UBGCardsEditor extends Morph {
this.display$type();
this.display$element();
this.display$cost();
this.display$vp();
this.display$text();
this.display$notes();
this.display$art();
Expand Down
4 changes: 4 additions & 0 deletions src/components/widgets/ubg-cards-entry.html
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@
#cost {
color: goldenrod;
}
#vp {
color: violet;
}
#name {
font-weight: 600;
}
Expand All @@ -152,6 +155,7 @@
<i id='type'></i>
<span id='element'></span>
<span id='cost'></span>
<span id='vp'></span>
<span id='name'></span>
<span id='text'></span>
<span id='art'></span>
Expand Down
1 change: 1 addition & 0 deletions src/components/widgets/ubg-cards-entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export default class UBGCardEntry extends Morph {
this.renderElement(v);

this.get('#cost').innerHTML = v.cost || '/';
this.get('#vp').innerHTML = card.getBaseVP() || '-';

this.get('#name').innerHTML = card.versions.last.name || 'no name yet';
this.get('#text').innerHTML = card.versions.last.text || 'no text';
Expand Down
1 change: 1 addition & 0 deletions src/components/widgets/ubg-cards.html
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
<button id="sortById" title="sort cards by id"><i class="fa fa-sort" aria-hidden="true"></i>by id</button>
<button id="sortByName" title="sort cards by name"><i class="fa fa-sort" aria-hidden="true"></i>by name</button>
<button id="import new cards" class="shortcut-supported" title="import new cards (Ctrl+I)">import <i class="fa fa-download"></i></button>
<button id="artDesc" class="shortcut-supported" title="copy to clipboard art descriptions of card that do not have art yet">art <i class="fa fa-clipboard"></i></button>
<button id="printAll" title="print all cards (Ctrl+Shift+P)">all <i class="fa fa-print"></i></button>
<button id="printChanges" title="print changed cards (Ctrl+P)">changes <i class="fa fa-print"></i></button>
<button id="saveJSON" class="shortcut-supported" title="save json (Ctrl+S)">json <i class="fa fa-floppy-o"></i></button>
Expand Down
137 changes: 125 additions & 12 deletions src/components/widgets/ubg-cards.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ContextMenu from 'src/client/contextmenu.js';
import { Paper } from 'src/client/literature.js';
import Bibliography from "src/client/bibliography.js";
import pdf from "src/external/pdf.js";
import { shake } from 'utils';

import { serialize, deserialize } from 'src/client/serialize.js';
import Card from 'demos/stefan/untitled-board-game/ubg-card.js';
Expand Down Expand Up @@ -196,6 +197,9 @@ const SORT_BY = {
NAME: 'name'
};

const VP_FILL = 'violet';
const VP_STROKE = '#9400d3'; // darkviolet

export default class Cards extends Morph {
async initialize() {

Expand Down Expand Up @@ -585,6 +589,10 @@ export default class Cards extends Morph {
return this.buildCards(doc, cards); // .slice(0,12)
}

async fetchAssetsInfo() {
return (await this.assetsFolder.fetchStats()).contents;
}

async buildCards(doc, cardsToPrint) {
const GAP = lively.pt(.2, .2);

Expand All @@ -600,8 +608,7 @@ export default class Cards extends Morph {
const progress = await lively.showProgress(progressLabel(0));

try {
const ASSET_FOLDER = this.assetsFolder;
const assetsInfo = (await ASSET_FOLDER.fetchStats()).contents;
const assetsInfo = await this.fetchAssetsInfo();

let i = 0;
let currentPage = 0;
Expand Down Expand Up @@ -1172,10 +1179,13 @@ export default class Cards extends Morph {
// cost
const coinCenter = coinLeftCenter.addXY(costCoinRadius, 0);
this.renderCost(doc, cardDesc, coinCenter, costCoinRadius)
const vpCenter = coinCenter.addY(costCoinRadius * 2.75);
this.renderBaseVP(doc, cardDesc, vpCenter, costCoinRadius)
}

renderCost(doc, cardDesc, pos, coinRadius) {
const COST_SIZE = coinRadius / 4;
const costSize = coinRadius / 4;

const costDesc = cardDesc.getCost();
const cost = Array.isArray(costDesc) ? costDesc.first : costDesc;

Expand All @@ -1184,17 +1194,54 @@ export default class Cards extends Morph {
doc.setGState(new doc.GState({ opacity: 0.9 }));
doc.setFillColor('#b8942d');
doc.setDrawColor(148, 0, 211);
doc.setLineWidth(0.2 * COST_SIZE)
doc.setLineWidth(0.2 * costSize)
doc.circle(...coinCenter.toPair(), coinRadius, 'DF');
});

if (cost !== undefined) {
doc::withGraphicsState(() => {
doc.setFontSize(12 * COST_SIZE);
doc.setTextColor('#000000');
doc.text('' + cost, ...coinCenter.toPair(), { align: 'center', baseline: 'middle' });
});
this.renderIconText(doc, coinCenter, costSize, cost)
}

renderBaseVP(doc, cardDesc, pos, coinRadius) {
const costSize = coinRadius / 4;

const vp = cardDesc.getBaseVP();
if (!vp) {
return;
}

const iconCenter = pos;
doc::withGraphicsState(() => {
doc.setGState(new doc.GState({ opacity: 0.9 }))
// doc.setFillColor('#b8942d');
doc.setDrawColor(VP_STROKE)
doc.setLineWidth(0.2 * costSize)
// doc.circle(...coinCenter.toPair(), coinRadius, 'DF');
doc.setFillColor(VP_FILL)
// doc.rect(coinCenter.x - coinRadius, coinCenter.y - coinRadius, 2 * coinRadius, 2 * coinRadius, 'DF');

// diamond shape
const diagonal = coinRadius * .9 * Math.sqrt(2)
const rightAbsolute = iconCenter.addX(diagonal).toPair()
const down = lively.pt(-diagonal, diagonal).toPair()
const left = lively.pt(-diagonal, -diagonal).toPair()
const up = lively.pt(diagonal, -diagonal).toPair()
const rightAgain = lively.pt(diagonal, diagonal).toPair()
doc.lines([down, left, up, rightAgain], ...rightAbsolute, [1,1], 'DF', true)
});

this.renderIconText(doc, iconCenter, costSize, vp)
}

renderIconText(doc, centerPos, size, text) {
if (text === undefined) {
return
}

doc::withGraphicsState(() => {
doc.setFontSize(12 * size);
doc.setTextColor('#000000');
doc.text('' + text, ...centerPos.toPair(), { align: 'center', baseline: 'middle' });
});
}

// #important
Expand Down Expand Up @@ -1240,6 +1287,13 @@ ${smallElementIcon(others[2], lively.pt(11, 7))}
</svg>`;
}

function printVP(vp) {
return `<span style="font-size: 1em; transform: translate(.5em, 0) rotate(45deg);"><svg viewbox="0 0 10 10" overflow="visible" style="height: 1em; width: 1em;" xmlns="http://www.w3.org/2000/svg">
<rect x="0" y="0" width="10" height="10" fill="${VP_FILL}" stroke="${VP_STROKE}"></rect>
<text x="50%" y="50%" text-anchor="middle" dy="0.35em" transform="rotate(-45, 5, 5)" style="font: .5em sans-serif; text-shadow: initial;">${vp}</text>
</svg></span>`;
}

let printedRules = rulesText;
printedRules = printedRules.replace(/t3x(fire|water|earth|wind|gray)/gmi, 'tap 3x$1');
printedRules = printedRules.replace(/(^|\n)tap 3x(fire|water|earth|wind|gray)([^\n]*)/gi, function replacer(match, p1, pElement, pText, offset, string, groups) {
Expand All @@ -1259,6 +1313,9 @@ ${smallElementIcon(others[2], lively.pt(11, 7))}
printedRules = printedRules.replace(/(fire|water|earth|wind|gray)/gmi, function replacer(match, pElement, offset, string, groups) {
return element(pElement);
});
printedRules = printedRules.replace(/(\d+|\*|d+\*|\d+x|x|\b)VP\b/gmi, function replacer(match, vp, offset, string, groups) {
return printVP(vp);
});
printedRules = printedRules.replace(/\(([*0-9x+-]*)\)/gmi, function replacer(match, p1, offset, string, groups) {
return coin(p1);
});
Expand Down Expand Up @@ -1510,7 +1567,7 @@ width: ${ruleTextBox.width}mm; min-height: ${ruleTextBox.height}mm;`}></div>;
if (that && that.localName === 'lively-code-mirror' && document.contains(that)) {
lively.showElement(that)

const matches = that.value.matchAll(/^([^0-9]+)?\s([0-9]+)?\s?([a-zA-Z ]+)?\s?(?:\(([0-9,]+)\))?\.\s(.*)?$/gmi);
const matches = that.value.matchAll(/^([^0-9]+)?\s([0-9]+)?\s?([a-zA-Z ]+)?\s?(?:\(([0-9,]+)\))?(?:\s?([0-9*+-]+))?\.\s(.*)?$/gmi);

const newCards = [...matches].map(match => {
const card = new Card();
Expand All @@ -1525,7 +1582,7 @@ width: ${ruleTextBox.width}mm; min-height: ${ruleTextBox.height}mm;`}></div>;

card.setName(match[1])
card.setType(match[3])
card.setText(match[5])
card.setText(match[6])

let type = ''
let element;
Expand Down Expand Up @@ -1562,6 +1619,16 @@ width: ${ruleTextBox.width}mm; min-height: ${ruleTextBox.height}mm;`}></div>;
}
}

const baseVP = match[5];
const intBaseVP = parseInt(baseVP);
if (!_.isNaN(intBaseVP)) {
card.setBaseVP(intBaseVP)
} else {
if (baseVP) {
card.setBaseVP(baseVP)
}
}

return card;
});

Expand All @@ -1582,6 +1649,52 @@ width: ${ruleTextBox.width}mm; min-height: ${ruleTextBox.height}mm;`}></div>;
}
}

async onArtDesc(evt) {
const text = do {
const assetsInfo = await this.fetchAssetsInfo();
let ids = []
for (let entry of assetsInfo) {
if (entry.type !== 'file') {
continue
}

const match = entry.name.match(/^(.+)\.jpg$/)
if (!match) {
continue
}

// const id = parseInt(match[1])
// if (_.isInteger(id)) {
// ids.push(id)
// }
ids.push(match[1])
}

let cards = this.cards;
cards = cards
.filter(c => !c.getIsBad())
// we just use a string match for now
.filter(c => !ids.includes(c.getId() + '')).sortBy('id')
cards.map(c => {
const artDesc = c.getArtDirection() || c.getName();
return `[${c.getId()}, '${artDesc}'],`
}).join('\n')
};

const type = "text/plain";
const blob = new Blob([text], { type });
// evt.clipboardData.setData('text/html', html);
const data = [new ClipboardItem({ [type]: blob })];

try {
await navigator.clipboard.write(data);
lively.success('copied art description!');
} catch (e) {
shake(this.get('#artDesc'));
lively.error('copying failed', e.message);
}
}

async onPrintAll(evt) {
if (!this.cards) {
return;
Expand Down

0 comments on commit a2b5a8a

Please sign in to comment.