wip
This commit is contained in:
parent
e3aae009b4
commit
cd296d60d8
|
@ -5,10 +5,6 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="$style.root" class="_gaps">
|
<div :class="$style.root" class="_gaps">
|
||||||
<div>
|
|
||||||
<MkButton inline rounded primary @click="chooseFile">{{ i18n.ts.selectFile }}</MkButton>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<template v-if="layer.type === 'text'">
|
<template v-if="layer.type === 'text'">
|
||||||
<MkInput v-model="layer.text">
|
<MkInput v-model="layer.text">
|
||||||
<template #label>{{ i18n.ts._watermarkEditor.text }}</template>
|
<template #label>{{ i18n.ts._watermarkEditor.text }}</template>
|
||||||
|
@ -42,6 +38,41 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template #label>{{ i18n.ts._watermarkEditor.opacity }}</template>
|
<template #label>{{ i18n.ts._watermarkEditor.opacity }}</template>
|
||||||
</MkRange>
|
</MkRange>
|
||||||
|
|
||||||
|
<MkSwitch v-model="layer.repeat">
|
||||||
|
<template #label>{{ i18n.ts._watermarkEditor.repeat }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="layer.type === 'image'">
|
||||||
|
<MkButton inline rounded primary @click="chooseFile">{{ i18n.ts.selectFile }}</MkButton>
|
||||||
|
|
||||||
|
<FormSlot>
|
||||||
|
<template #label>{{ i18n.ts._watermarkEditor.position }}</template>
|
||||||
|
<MkPositionSelector
|
||||||
|
v-model:x="layer.alignX"
|
||||||
|
v-model:y="layer.alignY"
|
||||||
|
></MkPositionSelector>
|
||||||
|
</FormSlot>
|
||||||
|
|
||||||
|
<MkRange
|
||||||
|
v-model="layer.scale"
|
||||||
|
:min="0"
|
||||||
|
:max="1"
|
||||||
|
:step="0.01"
|
||||||
|
continuousUpdate
|
||||||
|
>
|
||||||
|
<template #label>{{ i18n.ts._watermarkEditor.scale }}</template>
|
||||||
|
</MkRange>
|
||||||
|
|
||||||
|
<MkRange
|
||||||
|
v-model="layer.opacity"
|
||||||
|
:min="0"
|
||||||
|
:max="1"
|
||||||
|
:step="0.01"
|
||||||
|
continuousUpdate
|
||||||
|
>
|
||||||
|
<template #label>{{ i18n.ts._watermarkEditor.opacity }}</template>
|
||||||
|
</MkRange>
|
||||||
|
|
||||||
<MkSwitch v-model="layer.repeat">
|
<MkSwitch v-model="layer.repeat">
|
||||||
<template #label>{{ i18n.ts._watermarkEditor.repeat }}</template>
|
<template #label>{{ i18n.ts._watermarkEditor.repeat }}</template>
|
||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
|
@ -84,14 +115,7 @@ onMounted(async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function chooseFile(ev: MouseEvent) {
|
function chooseFile(ev: MouseEvent) {
|
||||||
selectFile({
|
selectFile(ev.currentTarget ?? ev.target, i18n.ts.selectFile).then((file) => {
|
||||||
anchorElement: ev.currentTarget ?? ev.target,
|
|
||||||
multiple: false,
|
|
||||||
label: i18n.ts.selectFile,
|
|
||||||
features: {
|
|
||||||
watermark: false,
|
|
||||||
},
|
|
||||||
}).then((file) => {
|
|
||||||
if (!file.type.startsWith('image')) {
|
if (!file.type.startsWith('image')) {
|
||||||
os.alert({
|
os.alert({
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
|
@ -101,9 +125,8 @@ function chooseFile(ev: MouseEvent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileId.value = file.id;
|
layer.value.imageId = file.id;
|
||||||
fileUrl.value = file.url;
|
layer.value.imageUrl = file.url;
|
||||||
fileName.value = file.name;
|
|
||||||
driveFileError.value = false;
|
driveFileError.value = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,32 @@ function cancel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const type = ref(preset.layers[0].type);
|
const type = ref(preset.layers[0].type);
|
||||||
|
watch(type, () => {
|
||||||
|
if (type.value === 'text') {
|
||||||
|
preset.layers = [{
|
||||||
|
id: uuid(),
|
||||||
|
type: type.value,
|
||||||
|
text: `(c) @${$i.username}`,
|
||||||
|
alignX: 'right',
|
||||||
|
alignY: 'bottom',
|
||||||
|
scale: 0.3,
|
||||||
|
opacity: 0.75,
|
||||||
|
repeat: false,
|
||||||
|
}];
|
||||||
|
} else if (type.value === 'image') {
|
||||||
|
preset.layers = [{
|
||||||
|
id: uuid(),
|
||||||
|
type: type.value,
|
||||||
|
imageId: null,
|
||||||
|
imageUrl: null,
|
||||||
|
alignX: 'right',
|
||||||
|
alignY: 'bottom',
|
||||||
|
scale: 0.3,
|
||||||
|
opacity: 0.75,
|
||||||
|
repeat: false,
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
watch(preset, async (newValue, oldValue) => {
|
watch(preset, async (newValue, oldValue) => {
|
||||||
if (renderer != null) {
|
if (renderer != null) {
|
||||||
|
|
|
@ -68,11 +68,11 @@ type WatermarkerTextLayer = {
|
||||||
opacity: number;
|
opacity: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WatermarkerImageLayer = {
|
type WatermarkerImageLayer = {
|
||||||
id: string;
|
id: string;
|
||||||
type: 'image';
|
type: 'image';
|
||||||
imageUrl: string;
|
imageUrl: string | null;
|
||||||
imageId: string;
|
imageId: string | null;
|
||||||
repeat: boolean;
|
repeat: boolean;
|
||||||
scale: number;
|
scale: number;
|
||||||
alignX: 'left' | 'center' | 'right';
|
alignX: 'left' | 'center' | 'right';
|
||||||
|
@ -234,10 +234,17 @@ export class Watermarker {
|
||||||
img.src = layer.imageUrl;
|
img.src = layer.imageUrl;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const texture = this.createTexture();
|
||||||
gl.activeTexture(gl.TEXTURE0);
|
gl.activeTexture(gl.TEXTURE0);
|
||||||
gl.bindTexture(gl.TEXTURE_2D, this.originalImageTexture);
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, image.width, image.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, image.width, image.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
||||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||||
|
|
||||||
|
this.bakedTextures.set(layer.id, {
|
||||||
|
texture: texture,
|
||||||
|
width: image.width,
|
||||||
|
height: image.height,
|
||||||
|
});
|
||||||
} else if (layer.type === 'text') {
|
} else if (layer.type === 'text') {
|
||||||
const measureCtx = window.document.createElement('canvas').getContext('2d')!;
|
const measureCtx = window.document.createElement('canvas').getContext('2d')!;
|
||||||
measureCtx.canvas.width = this.renderWidth;
|
measureCtx.canvas.width = this.renderWidth;
|
||||||
|
@ -323,7 +330,7 @@ export class Watermarker {
|
||||||
return shaderProgram;
|
return shaderProgram;
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderTextLayer(layer: WatermarkerTextLayer) {
|
private renderTextOrImageLayer(layer: WatermarkerTextLayer | WatermarkerImageLayer) {
|
||||||
const gl = this.gl;
|
const gl = this.gl;
|
||||||
if (gl == null) {
|
if (gl == null) {
|
||||||
throw new Error('gl is not initialized');
|
throw new Error('gl is not initialized');
|
||||||
|
@ -385,9 +392,9 @@ export class Watermarker {
|
||||||
|
|
||||||
private renderLayer(layer: WatermarkerLayer) {
|
private renderLayer(layer: WatermarkerLayer) {
|
||||||
if (layer.type === 'image') {
|
if (layer.type === 'image') {
|
||||||
this.renderImageLayer(layer);
|
this.renderTextOrImageLayer(layer);
|
||||||
} else if (layer.type === 'text') {
|
} else if (layer.type === 'text') {
|
||||||
this.renderTextLayer(layer);
|
this.renderTextOrImageLayer(layer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue