wip
This commit is contained in:
parent
dc7d50f583
commit
7a17f021d1
|
@ -12236,9 +12236,9 @@ export interface Locale extends ILocale {
|
||||||
*/
|
*/
|
||||||
"text": string;
|
"text": string;
|
||||||
/**
|
/**
|
||||||
* 二次元コード (アカウント)
|
* 二次元コード
|
||||||
*/
|
*/
|
||||||
"accountQr": string;
|
"qr": string;
|
||||||
/**
|
/**
|
||||||
* 位置
|
* 位置
|
||||||
*/
|
*/
|
||||||
|
@ -12303,6 +12303,10 @@ export interface Locale extends ILocale {
|
||||||
* サブドットの数
|
* サブドットの数
|
||||||
*/
|
*/
|
||||||
"polkadotSubDotDivisions": string;
|
"polkadotSubDotDivisions": string;
|
||||||
|
/**
|
||||||
|
* 空欄にするとアカウントのURLになります
|
||||||
|
*/
|
||||||
|
"leaveBlankToAccountUrl": string;
|
||||||
};
|
};
|
||||||
"_imageEffector": {
|
"_imageEffector": {
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3275,7 +3275,7 @@ _watermarkEditor:
|
||||||
opacity: "不透明度"
|
opacity: "不透明度"
|
||||||
scale: "サイズ"
|
scale: "サイズ"
|
||||||
text: "テキスト"
|
text: "テキスト"
|
||||||
accountQr: "二次元コード (アカウント)"
|
qr: "二次元コード"
|
||||||
position: "位置"
|
position: "位置"
|
||||||
margin: "マージン"
|
margin: "マージン"
|
||||||
type: "タイプ"
|
type: "タイプ"
|
||||||
|
@ -3292,6 +3292,7 @@ _watermarkEditor:
|
||||||
polkadotSubDotOpacity: "サブドットの不透明度"
|
polkadotSubDotOpacity: "サブドットの不透明度"
|
||||||
polkadotSubDotRadius: "サブドットの大きさ"
|
polkadotSubDotRadius: "サブドットの大きさ"
|
||||||
polkadotSubDotDivisions: "サブドットの数"
|
polkadotSubDotDivisions: "サブドットの数"
|
||||||
|
leaveBlankToAccountUrl: "空欄にするとアカウントのURLになります"
|
||||||
|
|
||||||
_imageEffector:
|
_imageEffector:
|
||||||
title: "エフェクト"
|
title: "エフェクト"
|
||||||
|
|
|
@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
:step="0.01"
|
:step="0.01"
|
||||||
:textConverter="(v) => (v * 100).toFixed(1) + '%'"
|
:textConverter="(v) => (v * 100).toFixed(1) + '%'"
|
||||||
continuousUpdate
|
continuousUpdate
|
||||||
@update:modelValue="(v) => (layer as Extract<WatermarkPreset['layers'][number], { type: 'account-qr' }>).align.margin = v"
|
@update:modelValue="(v) => (layer as Extract<WatermarkPreset['layers'][number], { type: 'text' }>).align.margin = v"
|
||||||
>
|
>
|
||||||
<template #label>{{ i18n.ts._watermarkEditor.margin }}</template>
|
<template #label>{{ i18n.ts._watermarkEditor.margin }}</template>
|
||||||
</MkRange>
|
</MkRange>
|
||||||
|
@ -85,7 +85,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
:step="0.01"
|
:step="0.01"
|
||||||
:textConverter="(v) => (v * 100).toFixed(1) + '%'"
|
:textConverter="(v) => (v * 100).toFixed(1) + '%'"
|
||||||
continuousUpdate
|
continuousUpdate
|
||||||
@update:modelValue="(v) => (layer as Extract<WatermarkPreset['layers'][number], { type: 'account-qr' }>).align.margin = v"
|
@update:modelValue="(v) => (layer as Extract<WatermarkPreset['layers'][number], { type: 'image' }>).align.margin = v"
|
||||||
>
|
>
|
||||||
<template #label>{{ i18n.ts._watermarkEditor.margin }}</template>
|
<template #label>{{ i18n.ts._watermarkEditor.margin }}</template>
|
||||||
</MkRange>
|
</MkRange>
|
||||||
|
@ -131,7 +131,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else-if="layer.type === 'account-qr'">
|
<template v-else-if="layer.type === 'qr'">
|
||||||
|
<MkInput v-model="layer.data" debounce>
|
||||||
|
<template #label>{{ i18n.ts._watermarkEditor.text }}</template>
|
||||||
|
<template #caption>{{ i18n.ts._watermarkEditor.leaveBlankToAccountUrl }}</template>
|
||||||
|
</MkInput>
|
||||||
|
|
||||||
<FormSlot>
|
<FormSlot>
|
||||||
<template #label>{{ i18n.ts._watermarkEditor.position }}</template>
|
<template #label>{{ i18n.ts._watermarkEditor.position }}</template>
|
||||||
<MkPositionSelector
|
<MkPositionSelector
|
||||||
|
@ -147,7 +152,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
:step="0.01"
|
:step="0.01"
|
||||||
:textConverter="(v) => (v * 100).toFixed(1) + '%'"
|
:textConverter="(v) => (v * 100).toFixed(1) + '%'"
|
||||||
continuousUpdate
|
continuousUpdate
|
||||||
@update:modelValue="(v) => (layer as Extract<WatermarkPreset['layers'][number], { type: 'account-qr' }>).align.margin = v"
|
@update:modelValue="(v) => (layer as Extract<WatermarkPreset['layers'][number], { type: 'qr' }>).align.margin = v"
|
||||||
>
|
>
|
||||||
<template #label>{{ i18n.ts._watermarkEditor.margin }}</template>
|
<template #label>{{ i18n.ts._watermarkEditor.margin }}</template>
|
||||||
</MkRange>
|
</MkRange>
|
||||||
|
|
|
@ -35,7 +35,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template #label>
|
<template #label>
|
||||||
<div v-if="layer.type === 'text'">{{ i18n.ts._watermarkEditor.text }}</div>
|
<div v-if="layer.type === 'text'">{{ i18n.ts._watermarkEditor.text }}</div>
|
||||||
<div v-if="layer.type === 'image'">{{ i18n.ts._watermarkEditor.image }}</div>
|
<div v-if="layer.type === 'image'">{{ i18n.ts._watermarkEditor.image }}</div>
|
||||||
<div v-if="layer.type === 'account-qr'">{{ i18n.ts._watermarkEditor.accountQr }}</div>
|
<div v-if="layer.type === 'qr'">{{ i18n.ts._watermarkEditor.qr }}</div>
|
||||||
<div v-if="layer.type === 'stripe'">{{ i18n.ts._watermarkEditor.stripe }}</div>
|
<div v-if="layer.type === 'stripe'">{{ i18n.ts._watermarkEditor.stripe }}</div>
|
||||||
<div v-if="layer.type === 'polkadot'">{{ i18n.ts._watermarkEditor.polkadot }}</div>
|
<div v-if="layer.type === 'polkadot'">{{ i18n.ts._watermarkEditor.polkadot }}</div>
|
||||||
<div v-if="layer.type === 'checker'">{{ i18n.ts._watermarkEditor.checker }}</div>
|
<div v-if="layer.type === 'checker'">{{ i18n.ts._watermarkEditor.checker }}</div>
|
||||||
|
@ -108,10 +108,11 @@ function createImageLayer(): WatermarkPreset['layers'][number] {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAccountQrLayer(): WatermarkPreset['layers'][number] {
|
function createQrLayer(): WatermarkPreset['layers'][number] {
|
||||||
return {
|
return {
|
||||||
id: genId(),
|
id: genId(),
|
||||||
type: 'account-qr',
|
type: 'qr',
|
||||||
|
data: '',
|
||||||
align: { x: 'right', y: 'bottom', margin: 0 },
|
align: { x: 'right', y: 'bottom', margin: 0 },
|
||||||
scale: 0.3,
|
scale: 0.3,
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
|
@ -317,9 +318,9 @@ function addLayer(ev: MouseEvent) {
|
||||||
preset.layers.push(createImageLayer());
|
preset.layers.push(createImageLayer());
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
text: i18n.ts._watermarkEditor.accountQr,
|
text: i18n.ts._watermarkEditor.qr,
|
||||||
action: () => {
|
action: () => {
|
||||||
preset.layers.push(createAccountQrLayer());
|
preset.layers.push(createQrLayer());
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
text: i18n.ts._watermarkEditor.stripe,
|
text: i18n.ts._watermarkEditor.stripe,
|
||||||
|
|
|
@ -67,7 +67,7 @@ interface TextureParamDef extends CommonParamDef {
|
||||||
} | {
|
} | {
|
||||||
type: 'url'; url: string | null;
|
type: 'url'; url: string | null;
|
||||||
} | {
|
} | {
|
||||||
type: 'account-qr';
|
type: 'qr'; data: string | null;
|
||||||
} | null;
|
} | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ export class ImageEffector<IEX extends ReadonlyArray<ImageEffectorFx<any, any, a
|
||||||
const texture =
|
const texture =
|
||||||
v.type === 'text' ? await createTextureFromText(this.gl, v.text) :
|
v.type === 'text' ? await createTextureFromText(this.gl, v.text) :
|
||||||
v.type === 'url' ? await createTextureFromUrl(this.gl, v.url) :
|
v.type === 'url' ? await createTextureFromUrl(this.gl, v.url) :
|
||||||
v.type === 'account-qr' ? await createTextureFromAccountQr(this.gl) :
|
v.type === 'qr' ? await createTextureFromQr(this.gl, { data: v.data }) :
|
||||||
null;
|
null;
|
||||||
if (texture == null) continue;
|
if (texture == null) continue;
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ export class ImageEffector<IEX extends ReadonlyArray<ImageEffectorFx<any, any, a
|
||||||
return (
|
return (
|
||||||
v.type === 'text' ? `text:${v.text}` :
|
v.type === 'text' ? `text:${v.text}` :
|
||||||
v.type === 'url' ? `url:${v.url}` :
|
v.type === 'url' ? `url:${v.url}` :
|
||||||
v.type === 'account-qr' ? 'account-qr' :
|
v.type === 'qr' ? `qr:${v.data}` :
|
||||||
''
|
''
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -487,7 +487,7 @@ async function createTextureFromText(gl: WebGL2RenderingContext, text: string |
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createTextureFromAccountQr(gl: WebGL2RenderingContext, resolution = 512): Promise<{ texture: WebGLTexture, width: number, height: number } | null> {
|
async function createTextureFromQr(gl: WebGL2RenderingContext, options: { data: string | null }, resolution = 512): Promise<{ texture: WebGLTexture, width: number, height: number } | null> {
|
||||||
const $i = ensureSignin();
|
const $i = ensureSignin();
|
||||||
|
|
||||||
const qrCodeInstance = new QRCodeStyling({
|
const qrCodeInstance = new QRCodeStyling({
|
||||||
|
@ -495,7 +495,7 @@ async function createTextureFromAccountQr(gl: WebGL2RenderingContext, resolution
|
||||||
height: resolution,
|
height: resolution,
|
||||||
margin: 42,
|
margin: 42,
|
||||||
type: 'canvas',
|
type: 'canvas',
|
||||||
data: `${url}/users/${$i.id}`,
|
data: options.data == null || options.data === '' ? `${url}/users/${$i.id}` : options.data,
|
||||||
image: $i.avatarUrl,
|
image: $i.avatarUrl,
|
||||||
qrOptions: {
|
qrOptions: {
|
||||||
typeNumber: 0,
|
typeNumber: 0,
|
||||||
|
@ -522,12 +522,12 @@ async function createTextureFromAccountQr(gl: WebGL2RenderingContext, resolution
|
||||||
const blob = await qrCodeInstance.getRawData('png') as Blob | null;
|
const blob = await qrCodeInstance.getRawData('png') as Blob | null;
|
||||||
if (blob == null) return null;
|
if (blob == null) return null;
|
||||||
|
|
||||||
const data = await window.createImageBitmap(blob);
|
const image = await window.createImageBitmap(blob);
|
||||||
|
|
||||||
const texture = createTexture(gl);
|
const texture = createTexture(gl);
|
||||||
gl.activeTexture(gl.TEXTURE0);
|
gl.activeTexture(gl.TEXTURE0);
|
||||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, resolution, resolution, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, resolution, resolution, 0, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -44,7 +44,8 @@ export type WatermarkPreset = {
|
||||||
opacity: number;
|
opacity: number;
|
||||||
} | {
|
} | {
|
||||||
id: string;
|
id: string;
|
||||||
type: 'account-qr';
|
type: 'qr';
|
||||||
|
data: string;
|
||||||
scale: number;
|
scale: number;
|
||||||
align: Align;
|
align: Align;
|
||||||
opacity: number;
|
opacity: number;
|
||||||
|
@ -133,7 +134,7 @@ export class WatermarkRenderer {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} else if (layer.type === 'account-qr') {
|
} else if (layer.type === 'qr') {
|
||||||
return {
|
return {
|
||||||
fxId: 'watermarkPlacement',
|
fxId: 'watermarkPlacement',
|
||||||
id: layer.id,
|
id: layer.id,
|
||||||
|
@ -145,7 +146,8 @@ export class WatermarkRenderer {
|
||||||
opacity: layer.opacity,
|
opacity: layer.opacity,
|
||||||
cover: false,
|
cover: false,
|
||||||
watermark: {
|
watermark: {
|
||||||
type: 'account-qr',
|
type: 'qr',
|
||||||
|
data: layer.data,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue