feat: Selection mirroring

For now only horizontal flip (we can add vertical flip too, but it would
be redundant)

Signed-off-by: Victor Seiji Hariki <victorseijih@gmail.com>
This commit is contained in:
Victor Seiji Hariki 2023-04-08 23:05:22 -03:00
parent 64bc673f45
commit 1dcb897839
2 changed files with 60 additions and 6 deletions

View file

@ -488,7 +488,7 @@
src="js/ui/tool/colorbrush.js?v=84ff9fa" src="js/ui/tool/colorbrush.js?v=84ff9fa"
type="text/javascript"></script> type="text/javascript"></script>
<script <script
src="js/ui/tool/select.js?v=044d8f3" src="js/ui/tool/select.js?v=dfacef5"
type="text/javascript"></script> type="text/javascript"></script>
<script src="js/ui/tool/stamp.js?v=4494df6" type="text/javascript"></script> <script src="js/ui/tool/stamp.js?v=4494df6" type="text/javascript"></script>
<script <script

View file

@ -33,7 +33,9 @@ const selectTransformTool = () =>
keyboard.onShortcut({ctrl: true, key: "KeyC"}, state.ctrlccb); keyboard.onShortcut({ctrl: true, key: "KeyC"}, state.ctrlccb);
keyboard.onShortcut({ctrl: true, key: "KeyV"}, state.ctrlvcb); keyboard.onShortcut({ctrl: true, key: "KeyV"}, state.ctrlvcb);
keyboard.onShortcut({ctrl: true, key: "KeyX"}, state.ctrlxcb); keyboard.onShortcut({ctrl: true, key: "KeyX"}, state.ctrlxcb);
keyboard.onShortcut({key: "Equal"}, state.togglemirror);
state.ctxmenu.mirrorSelectionCheckbox.disabled = true;
state.selected = null; state.selected = null;
// Register Layer // Register Layer
@ -59,6 +61,7 @@ const selectTransformTool = () =>
keyboard.deleteShortcut(state.ctrlccb, "KeyC"); keyboard.deleteShortcut(state.ctrlccb, "KeyC");
keyboard.deleteShortcut(state.ctrlvcb, "KeyV"); keyboard.deleteShortcut(state.ctrlvcb, "KeyV");
keyboard.deleteShortcut(state.ctrlxcb, "KeyX"); keyboard.deleteShortcut(state.ctrlxcb, "KeyX");
keyboard.deleteShortcut(state.togglemirror, "Equal");
uil.onactive.clear(state.uilayeractivecb); uil.onactive.clear(state.uilayeractivecb);
@ -134,8 +137,12 @@ const selectTransformTool = () =>
} }
if (state.dragging) state.dragging = null; if (state.dragging) state.dragging = null;
else state.selected = null; else {
state.ctxmenu.mirrorSelectionCheckbox.disabled = true;
state.selected = null;
}
state.mirrorSetValue(false);
state.rotation = 0; state.rotation = 0;
state.original = null; state.original = null;
moving = null; moving = null;
@ -173,6 +180,11 @@ const selectTransformTool = () =>
} }
}; };
// Mirroring
state.togglemirror = () => {
state.mirrorSetValue(!state.mirrorSelection);
};
// Mouse Move Handler // Mouse Move Handler
state.movecb = (evn) => { state.movecb = (evn) => {
state.lastMouseMove = evn; state.lastMouseMove = evn;
@ -247,6 +259,7 @@ const selectTransformTool = () =>
state.selected.scale.y === 1 && state.selected.scale.y === 1 &&
state.selected.position.x === state.original.sx && state.selected.position.x === state.original.sx &&
state.selected.position.y === state.original.sy && state.selected.position.y === state.original.sy &&
!state.mirrorSelection &&
state.original.layer === uil.layer state.original.layer === uil.layer
) && ) &&
!isCanvasBlank( !isCanvasBlank(
@ -409,11 +422,17 @@ const selectTransformTool = () =>
const xs = lscursor.x / scaling.handle.x; const xs = lscursor.x / scaling.handle.x;
const xy = lscursor.y / scaling.handle.y; const xy = lscursor.y / scaling.handle.y;
if (!state.keepAspectRatio) state.selected.scale = {x: xs, y: xy}; let xscale = 1;
else { let yscale = 1;
const scale = Math.max(xs, xy);
state.selected.scale = {x: scale, y: scale}; if (!state.keepAspectRatio) {
xscale = xs;
yscale = ys;
} else {
xscale = yscale = Math.max(xs, xy);
} }
state.selected.scale = {x: xscale, y: yscale};
} }
if (rotating) { if (rotating) {
@ -460,6 +479,8 @@ const selectTransformTool = () =>
}; };
state.selected = new _tool.MarqueeSelection(canvas, bb.center); state.selected = new _tool.MarqueeSelection(canvas, bb.center);
state.ctxmenu.mirrorSelectionCheckbox.disabled = false;
state.redraw(); state.redraw();
}; };
@ -511,6 +532,7 @@ const selectTransformTool = () =>
}, },
} }
); );
state.ctxmenu.mirrorSelectionCheckbox.disabled = true;
state.selected = null; state.selected = null;
state.redraw(); state.redraw();
} }
@ -668,6 +690,37 @@ const selectTransformTool = () =>
"icon-maximize" "icon-maximize"
).checkbox; ).checkbox;
// Mirroring
state.onMirror = () => {
if (state.selected) {
const scale = state.selected.scale;
scale.x *= -1;
state.selected.scale = scale;
state.redraw();
}
};
const {checkbox: mirrorCheckbox, setValue: _mirrorSetValue} =
_toolbar_input.checkbox(
state,
"openoutpaint/select-mirror",
"mirrorSelection",
"Mirror Selection",
"icon-flip-horizontal",
(v) => {
state.onMirror();
}
);
state.ctxmenu.mirrorSelectionCheckbox = mirrorCheckbox;
state.ctxmenu.mirrorSelectionCheckbox.disabled = true;
_mirrorSetValue(false);
state.mirrorSetValue = (v) => {
_mirrorSetValue(v);
if (v !== state.mirrorSelection) {
state.onMirror();
}
};
// Use Clipboard // Use Clipboard
const clipboardCheckbox = _toolbar_input.checkbox( const clipboardCheckbox = _toolbar_input.checkbox(
state, state,
@ -817,6 +870,7 @@ const selectTransformTool = () =>
array.classList.add("checkbox-array"); array.classList.add("checkbox-array");
array.appendChild(state.ctxmenu.snapToGridLabel); array.appendChild(state.ctxmenu.snapToGridLabel);
array.appendChild(state.ctxmenu.keepAspectRatioLabel); array.appendChild(state.ctxmenu.keepAspectRatioLabel);
array.appendChild(state.ctxmenu.mirrorSelectionCheckbox);
array.appendChild(state.ctxmenu.useClipboardLabel); array.appendChild(state.ctxmenu.useClipboardLabel);
menu.appendChild(array); menu.appendChild(array);
menu.appendChild(state.ctxmenu.selectionPeekOpacitySlider); menu.appendChild(state.ctxmenu.selectionPeekOpacitySlider);