aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--public/bluebey-studio/src/exporter.js92
-rw-r--r--public/bluebey-studio/src/main.js28
-rw-r--r--public/bluebey-studio/src/panel.js15
-rw-r--r--src/content/docs/bluebey/index.mdx1
4 files changed, 0 insertions, 136 deletions
diff --git a/public/bluebey-studio/src/exporter.js b/public/bluebey-studio/src/exporter.js
index ea9356e..cc9c1ca 100644
--- a/public/bluebey-studio/src/exporter.js
+++ b/public/bluebey-studio/src/exporter.js
@@ -1,6 +1,5 @@
import { traceAlphaContours, contoursToPathData } from './trace.js';
import { roughenContours } from './handDrawn.js';
-import { EYE_LAYOUT, MOUTH_LAYOUT } from './faceArt.js';
/**
* Export helpers.
@@ -175,97 +174,6 @@ ${rect}<path fill="${lineColor}"${widthAttr} fill-rule="evenodd" d="${d}"/>
};
}
-/** Alignment guides: blue on the white paper, light enough to paint over. */
-const FACE_MAP_GUIDE = 'rgba(90, 140, 220, 0.55)';
-/** Half-length of the centre ticks, in artwork-window pixels. */
-const FACE_MAP_TICK = 16;
-
-/**
- * Build the「下地」image an author paints a custom face texture on.
- *
- * The studio loads a hand-drawn image by drawing it at the artwork window's own
- * offset and size (see `Face.loadImage` / `placeInWindow`), so an image the size
- * of the *plate canvas*, with its artwork aligned to `offsetX/offsetY`, imports
- * 1:1. That is exactly what this hands out: the live drawing as a reference, an
- * opaque white window to paint on, and faint guides for the eye centres, the lid
- * line or the mouth chord.
- *
- * The white and the guides go on a **copy**: the plate canvas *is* the live
- * texture, and painting it would show up in the view.
- *
- * @param {import('./face.js').Face} face
- * @param {'eyes'|'mouth'} kind
- * @returns {HTMLCanvasElement}
- */
-export function buildFaceMap(face, kind) {
- const eyes = kind === 'eyes';
- const layout = eyes ? face.eyeLayout : face.mouthLayout;
- const plate = eyes ? face.eyeCanvas : face.mouthCanvas;
-
- const canvas = document.createElement('canvas');
- canvas.width = layout.width;
- canvas.height = layout.height;
- const ctx = canvas.getContext('2d');
- ctx.drawImage(plate, 0, 0);
-
- const { offsetX, offsetY, window: win } = layout;
- // `destination-over` so the white paper lands *under* the copy: filling it
- // normally would erase the very drawing the author lines the new art up against.
- ctx.globalCompositeOperation = 'destination-over';
- ctx.fillStyle = '#ffffff';
- ctx.fillRect(offsetX, offsetY, win.width, win.height);
- ctx.globalCompositeOperation = 'source-over';
-
- // The plate canvas keeps the artwork at its original pixel size (only the canvas
- // grows around it), so a fixed-width stroke reads the same on both parts.
- ctx.strokeStyle = FACE_MAP_GUIDE;
- ctx.fillStyle = FACE_MAP_GUIDE;
- ctx.lineWidth = 2;
-
- // Where the drawing has to fit, and where its middle is. The cross uses short
- // ticks, not full-width lines, so it cannot be mistaken for artwork.
- ctx.strokeRect(offsetX, offsetY, win.width, win.height);
- const cx = offsetX + win.width / 2;
- const cy = offsetY + win.height / 2;
- guideLine(ctx, cx - FACE_MAP_TICK, cy, cx + FACE_MAP_TICK, cy);
- guideLine(ctx, cx, cy - FACE_MAP_TICK, cx, cy + FACE_MAP_TICK);
-
- if (eyes) {
- // Both eyeballs (`radius`) and the lid line through their centres, so a
- // hand-drawn brow or eye can be placed against the parametric ones.
- const [a, b] = EYE_LAYOUT.eyes;
- const y = offsetY + a.cy;
- guideLine(ctx, offsetX + a.cx, y, offsetX + b.cx, y);
- for (const eye of EYE_LAYOUT.eyes) {
- const ex = offsetX + eye.cx;
- const ey = offsetY + eye.cy;
- ctx.beginPath();
- ctx.arc(ex, ey, EYE_LAYOUT.radius, 0, Math.PI * 2);
- ctx.stroke();
- // A small dot marks the exact centre, where the eyeball pivots.
- ctx.beginPath();
- ctx.arc(ex, ey, ctx.lineWidth * 1.5, 0, Math.PI * 2);
- ctx.fill();
- }
- } else {
- // The lip line the mouth is drawn around: end to end, plus a tick at the centre.
- const y = offsetY + MOUTH_LAYOUT.chordY;
- const { centreX, halfChord } = MOUTH_LAYOUT;
- guideLine(ctx, offsetX + centreX - halfChord, y, offsetX + centreX + halfChord, y);
- guideLine(ctx, offsetX + centreX, y - FACE_MAP_TICK, offsetX + centreX, y + FACE_MAP_TICK);
- }
-
- return canvas;
-}
-
-/** One guide segment, kept out of the map builders so the placements stay readable. */
-function guideLine(ctx, x0, y0, x1, y1) {
- ctx.beginPath();
- ctx.moveTo(x0, y0);
- ctx.lineTo(x1, y1);
- ctx.stroke();
-}
-
export function downloadBlob(blob, filename) {
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
diff --git a/public/bluebey-studio/src/main.js b/public/bluebey-studio/src/main.js
index f861ade..e6bc785 100644
--- a/public/bluebey-studio/src/main.js
+++ b/public/bluebey-studio/src/main.js
@@ -1301,8 +1301,6 @@ async function init() {
imageCanvas: (options) => captureImage(options),
savePNG: (options = {}) => savePNG(options),
copyPNG: () => copyPNG(),
- faceMapCanvas: (kind) => faceMapCanvas(kind),
- saveFaceMap: (kind) => saveFaceMap(kind),
addGionStamp: (item) => addGionStamp(item),
saveSettings: () => exporter.downloadText(JSON.stringify(state, null, 2), `bluebey-settings-${exporter.timestamp()}.json`),
loadSettings: (text) => {
@@ -1916,32 +1914,6 @@ async function init() {
toast(`PNGを書き出しました(${result.width}×${result.height})`);
}
- /**
- * The canvas the 下地 export paints on, *without* downloading it. Kept separate
- * from `saveFaceMap` so the in-page round-trip check can look at exactly the
- * pixels the button writes.
- */
- function faceMapCanvas(kind) {
- // A redraw is throttled while the render loop runs (see the loop's
- // `face.flush(now, 26)`), so force any pending one through first or the map
- // would show the expression before last.
- face.flush(performance.now(), 0);
- return exporter.buildFaceMap(face, kind);
- }
-
- async function saveFaceMap(kind) {
- const canvas = faceMapCanvas(kind);
- if (!canvas) {
- toast('この下地は書き出せませんでした');
- return;
- }
- const blob = await exporter.canvasToBlob(canvas);
- const label = kind === 'eyes' ? '目' : '口';
- exporter.downloadBlob(blob, `bluebey-face-${kind}-${exporter.timestamp()}.png`);
- toast(`${label}の下地を書き出しました(${canvas.width}×${canvas.height})。`
- + `この画像に描いて「${label}の画像を読み込む(PNG)」で読み込めます`);
- }
-
/** Hide the gizmo and helpers so they never end up in an export. */
async function withHiddenHelpers(fn) {
const wasVisible = rig.helper.visible;
diff --git a/public/bluebey-studio/src/panel.js b/public/bluebey-studio/src/panel.js
index a6e971d..2b405bd 100644
--- a/public/bluebey-studio/src/panel.js
+++ b/public/bluebey-studio/src/panel.js
@@ -38,7 +38,6 @@ const SECTION_ICONS = {
'画像': 'M4 5h16v14H4zM4 15l5-4 4 3 4-3.5 3 2.5M15.5 9h.01',
'まんが': 'M4 4h7v7H4zM13 4h7v7h-7zM4 13h7v7H4zM13 13h7v7h-7z',
'共有': 'M8.2 10.6a2 2 0 1 0 0-3.2 2 2 0 0 0 0 3.2ZM17 6.4a2 2 0 1 0 0-3.2 2 2 0 0 0 0 3.2ZM17 20.8a2 2 0 1 0 0-3.2 2 2 0 0 0 0 3.2ZM10 10.4l5-2.6M10 13.6l5 2.6',
- 'テクスチャの下地を書き出す': 'M4 4h16v16H4zM4 9.3h16M4 14.7h16M9.3 4v16M14.7 4v16',
'設定': 'M12 8.6a3.4 3.4 0 1 0 0 6.8 3.4 3.4 0 0 0 0-6.8ZM12 2.6v2.4M12 19v2.4M2.6 12H5M19 12h2.4M5.2 5.2l1.7 1.7M17.1 17.1l1.7 1.7M18.8 5.2l-1.7 1.7M6.9 17.1l-1.7 1.7',
};
@@ -2241,20 +2240,6 @@ export function buildPanel(app, root) {
extraExportSection.add(hint('いまの画面を画像にして「#ぶるべースタジオ」を付けて投稿します。'
+ 'スマートフォンでは端末の共有画面が開きます。パソコンでは画像をコピーして投稿画面を開くので、貼り付けて投稿してください(Ctrl+V)。'));
- // 手描きの顔パーツを描くための下地。画面を切り取る他の書き出しと違って、これは
- // 「スタジオが読み込む大きさ・位置そのまま」の素材なので、別のセクションにして
- // 共有のあとに置く(素材を作る → 見せる、の順)。
- const faceMapSection = section(tabExport, 'テクスチャの下地を書き出す');
- faceMapSection.add(buttons({
- items: [
- { id: 'facemap-eyes', label: '目の下地を書き出す', onClick: () => app.actions.saveFaceMap('eyes') },
- { id: 'facemap-mouth', label: '口の下地を書き出す', onClick: () => app.actions.saveFaceMap('mouth') },
- ],
- }));
- faceMapSection.add(hint('書き出したPNGは、スタジオが読み込む大きさ・位置そのものです。'
- + 'そのまま絵を描いて「目の画像を読み込む(PNG)」や「口の画像を読み込む(PNG)」で読み込むと、'
- + '描いた場所にそのまま入ります。青い線は位置合わせの目安です。使う前に消すか、上から塗ってください。'));
-
/* --------------------------------------------------------------- settings */
const settingsSection = section(tabExport, '設定');
diff --git a/src/content/docs/bluebey/index.mdx b/src/content/docs/bluebey/index.mdx
index 08e5427..3eb1049 100644
--- a/src/content/docs/bluebey/index.mdx
+++ b/src/content/docs/bluebey/index.mdx
@@ -30,7 +30,6 @@ draft: true
- **2D化**: リアル・フラット・線画の3つのスタイルを切り替えられます。
- **素材**: 写真の背景のほか、マンガの効果線(集中線・楕円集中線など6種類)、単色、透明から選べます。
- **書き出し**: PNG(1~4倍の大きさ)、クリップボードへのコピー、設定の保存。
-- **テクスチャの下地**: 目と口の下地画像を書き出せるので、自作の目や口の絵を描いて読み込めます。
- **共有**: いまの画面を画像にして「#ぶるべースタジオ」を付けて投稿できます。
## 使い方