allow stamp rotation(drag) and scaling(wheel)

also adds shift as a 'finetune' for wheel. works for dream and stamp. if
shift is pressed, wheel will scale slower (not snapping to 128 for
dream, or 0.1 for stamp)

Signed-off-by: Victor Seiji Hariki <victorseijih@gmail.com>
This commit is contained in:
Victor Seiji Hariki 2023-01-12 23:00:34 -03:00
parent b2e28e77c0
commit e198cf9af4
5 changed files with 147 additions and 37 deletions

View file

@ -355,7 +355,7 @@
type="text/javascript"></script> type="text/javascript"></script>
<!-- Configuration --> <!-- Configuration -->
<script src="js/config.js?v=36739c9" type="text/javascript"></script> <script src="js/config.js?v=e0345e0" type="text/javascript"></script>
<!-- Content --> <!-- Content -->
<script src="js/prompt.js?v=7a1c68c" type="text/javascript"></script> <script src="js/prompt.js?v=7a1c68c" type="text/javascript"></script>
@ -373,7 +373,7 @@
src="js/ui/tool/generic.js?v=f5ad9d7" src="js/ui/tool/generic.js?v=f5ad9d7"
type="text/javascript"></script> type="text/javascript"></script>
<script src="js/ui/tool/dream.js?v=3db7d6c" type="text/javascript"></script> <script src="js/ui/tool/dream.js?v=f20dd01" type="text/javascript"></script>
<script <script
src="js/ui/tool/maskbrush.js?v=1e8a893" src="js/ui/tool/maskbrush.js?v=1e8a893"
type="text/javascript"></script> type="text/javascript"></script>
@ -381,9 +381,9 @@
src="js/ui/tool/colorbrush.js?v=3f8c01a" src="js/ui/tool/colorbrush.js?v=3f8c01a"
type="text/javascript"></script> type="text/javascript"></script>
<script <script
src="js/ui/tool/select.js?v=fae1b04" src="js/ui/tool/select.js?v=95eba41"
type="text/javascript"></script> type="text/javascript"></script>
<script src="js/ui/tool/stamp.js?v=3c07ac8" type="text/javascript"></script> <script src="js/ui/tool/stamp.js?v=1bba5f4" type="text/javascript"></script>
<script <script
src="js/ui/tool/interrogate.js?v=e579ff1" src="js/ui/tool/interrogate.js?v=e579ff1"
type="text/javascript"></script> type="text/javascript"></script>

View file

@ -25,15 +25,15 @@ const config = makeReadOnly(
rotationSnappingDistance: (10 * Math.PI) / 180, rotationSnappingDistance: (10 * Math.PI) / 180,
// Rotation Snapping Angles // Rotation Snapping Angles
rotationSnappingAngles: [ rotationSnappingAngles: [
(-Math.PI * 4) / 4,
(-Math.PI * 3) / 4,
(-Math.PI * 2) / 4,
(-Math.PI * 1) / 4,
0, 0,
Math.PI / 4, (Math.PI * 1) / 4,
Math.PI / 2, (Math.PI * 2) / 4,
(Math.PI * 3) / 4, (Math.PI * 3) / 4,
Math.PI, (Math.PI * 4) / 4,
(Math.PI * 5) / 4,
(Math.PI * 6) / 4,
(Math.PI * 7) / 4,
Math.PI * 2,
], ],
// Endpoint // Endpoint

View file

@ -1255,10 +1255,16 @@ const _dream_onwheel = (evn, state) => {
return; return;
} }
// A simple but (I hope) effective fix for mouse wheel behavior let delta = evn.delta;
_dream_wheel_accum += evn.delta; if (evn.evn.shiftKey) delta *= 0.01;
if (Math.abs(_dream_wheel_accum) > config.wheelTickSize) { // A simple but (I hope) effective fix for mouse wheel behavior
_dream_wheel_accum += delta;
if (
!evn.evn.shiftKey &&
Math.abs(_dream_wheel_accum) > config.wheelTickSize
) {
// Snap to next or previous position // Snap to next or previous position
const v = const v =
state.cursorSize - state.cursorSize -
@ -1267,6 +1273,12 @@ const _dream_onwheel = (evn, state) => {
state.cursorSize = state.setCursorSize(v + snap(v, 0, 128)); state.cursorSize = state.setCursorSize(v + snap(v, 0, 128));
state.mousemovecb(evn); state.mousemovecb(evn);
_dream_wheel_accum = 0; // Zero accumulation
} else if (evn.evn.shiftKey && Math.abs(_dream_wheel_accum) >= 1) {
const v = state.cursorSize - _dream_wheel_accum;
state.cursorSize = state.setCursorSize(v);
state.mousemovecb(evn);
_dream_wheel_accum = 0; // Zero accumulation _dream_wheel_accum = 0; // Zero accumulation
} }
}; };

View file

@ -375,7 +375,7 @@ const selectTransformTool = () =>
angle = angle =
config.rotationSnappingAngles.find( config.rotationSnappingAngles.find(
(v) => Math.abs(v - angle) < config.rotationSnappingDistance (v) => Math.abs(v - angle) < config.rotationSnappingDistance
) || angle; ) ?? angle;
state.selected.rotation = angle; state.selected.rotation = angle;
} }

View file

@ -1,3 +1,41 @@
/**
* Generic wheel handler
*/
let _stamp_wheel_accum = 0;
const _stamp_onwheel = (evn, state) => {
if (evn.mode !== WheelEvent.DOM_DELTA_PIXEL) {
// We don't really handle non-pixel scrolling
return;
}
let delta = evn.delta;
if (evn.evn.shiftKey) delta *= 0.01;
// A simple but (I hope) effective fix for mouse wheel behavior
_stamp_wheel_accum += delta;
if (
!evn.evn.shiftKey &&
Math.abs(_stamp_wheel_accum) > config.wheelTickSize
) {
// Snap to next or previous position
const v =
state.scale - 0.1 * (_stamp_wheel_accum / Math.abs(_stamp_wheel_accum));
state.setScale(v + snap(v, 0, 0.1));
state.redraw(evn);
_stamp_wheel_accum = 0; // Zero accumulation
} else if (evn.evn.shiftKey && Math.abs(_stamp_wheel_accum) >= 1) {
const v = state.scale - _stamp_wheel_accum * 0.01;
state.setScale(v);
state.redraw(evn);
_stamp_wheel_accum = 0; // Zero accumulation
}
};
const stampTool = () => const stampTool = () =>
toolbar.registerTool( toolbar.registerTool(
"./res/icons/file-up.svg", "./res/icons/file-up.svg",
@ -14,6 +52,12 @@ const stampTool = () =>
mouse.listen.world.btn.left.onclick.on(state.drawcb); mouse.listen.world.btn.left.onclick.on(state.drawcb);
mouse.listen.world.btn.right.onclick.on(state.cancelcb); mouse.listen.world.btn.right.onclick.on(state.cancelcb);
mouse.listen.world.btn.left.ondragstart.on(state.dragstartcb);
mouse.listen.world.btn.left.ondrag.on(state.dragcb);
mouse.listen.world.btn.left.ondragend.on(state.dragendcb);
mouse.listen.world.onwheel.on(state.onwheelcb);
// For calls from other tools to paste image // For calls from other tools to paste image
if (opt && opt.image) { if (opt && opt.image) {
state.addResource( state.addResource(
@ -41,6 +85,12 @@ const stampTool = () =>
mouse.listen.world.btn.left.onclick.clear(state.drawcb); mouse.listen.world.btn.left.onclick.clear(state.drawcb);
mouse.listen.world.btn.right.onclick.clear(state.cancelcb); mouse.listen.world.btn.right.onclick.clear(state.cancelcb);
mouse.listen.world.btn.left.ondragstart.clear(state.dragstartcb);
mouse.listen.world.btn.left.ondrag.clear(state.dragcb);
mouse.listen.world.btn.left.ondragend.clear(state.dragendcb);
mouse.listen.world.onwheel.clear(state.onwheelcb);
ovLayer.clear(); ovLayer.clear();
}, },
{ {
@ -54,7 +104,15 @@ const stampTool = () =>
state.lastMouseMove = {x: 0, y: 0}; state.lastMouseMove = {x: 0, y: 0};
state.block_res_change = true; state.block_res_change = true;
// Current Rotation
let rotation = 0;
let rotating = null;
// Current Scale
state.scale = 1;
state.selectResource = (resource, nolock = true, deselect = true) => { state.selectResource = (resource, nolock = true, deselect = true) => {
rotation = 0;
state.setScale(1);
if (nolock && state.ctxmenu.uploadButton.disabled) return; if (nolock && state.ctxmenu.uploadButton.disabled) return;
console.debug( console.debug(
@ -290,32 +348,65 @@ const stampTool = () =>
syncResources(); syncResources();
}; };
state.movecb = (evn) => { state.onwheelcb = (evn) => {
let x = evn.x; _stamp_onwheel(evn, state);
let y = evn.y; };
if (state.snapToGrid) {
x += snap(evn.x, 0, 64); state.dragstartcb = (evn) => {
y += snap(evn.y, 0, 64); const {x, y, sx, sy} = _tool._process_cursor(evn, state.snapToGrid);
rotating = {x: sx, y: sy};
};
state.dragcb = (evn) => {
if (rotating) {
rotation = Math.atan2(rotating.x - evn.x, evn.y - rotating.y);
if (evn.evn.shiftKey)
rotation =
config.rotationSnappingAngles.find(
(v) =>
Math.abs(v - rotation) < config.rotationSnappingDistance
) ?? rotation;
} }
};
const vpc = viewport.canvasToView(x, y); state.dragendcb = (evn) => {
uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height); rotating = null;
state.erasePrevCursor && state.erasePrevCursor(); };
uiCtx.save(); let erasePrevCursor = () => null;
state.movecb = (evn) => {
const {x, y, sx, sy} = _tool._process_cursor(evn, state.snapToGrid);
// Erase Previous Cursors
erasePrevCursor();
state.lastMouseMove = evn; state.lastMouseMove = evn;
ovLayer.clear(); ovLayer.clear();
let px = sx;
let py = sy;
if (rotating) {
px = rotating.x;
py = rotating.y;
}
// Draw selected image // Draw selected image
if (state.selected) { if (state.selected) {
ovCtx.drawImage(state.selected.image, x, y); ovCtx.save();
ovCtx.translate(px, py);
ovCtx.scale(state.scale, state.scale);
ovCtx.rotate(rotation);
ovCtx.drawImage(state.selected.image, 0, 0);
ovCtx.restore();
} }
// Draw current cursor location // Draw current cursor location
state.erasePrevCursor = _tool._cursor_draw(x, y); erasePrevCursor = _tool._cursor_draw(px, py);
uiCtx.restore();
}; };
state.redraw = () => { state.redraw = () => {
@ -323,20 +414,16 @@ const stampTool = () =>
}; };
state.drawcb = (evn) => { state.drawcb = (evn) => {
let x = evn.x; const {x, y, sx, sy} = _tool._process_cursor(evn, state.snapToGrid);
let y = evn.y;
if (state.snapToGrid) {
x += snap(evn.x, 0, 64);
y += snap(evn.y, 0, 64);
}
const resource = state.selected; const resource = state.selected;
if (resource) { if (resource) {
const {canvas, bb} = cropCanvas(ovCanvas, {border: 10});
commands.runCommand("drawImage", "Image Stamp", { commands.runCommand("drawImage", "Image Stamp", {
image: resource.image, image: canvas,
x, x: bb.x,
y, y: bb.y,
}); });
if (resource.temporary) { if (resource.temporary) {
@ -380,6 +467,16 @@ const stampTool = () =>
); );
state.ctxmenu.snapToGridLabel = array; state.ctxmenu.snapToGridLabel = array;
// Scale Slider
const scaleSlider = _toolbar_input.slider(state, "scale", "Scale", {
min: 0.01,
max: 10,
step: 0.1,
textStep: 0.01,
});
state.ctxmenu.scaleSlider = scaleSlider.slider;
state.setScale = scaleSlider.setValue;
// Create resource list // Create resource list
const uploadButtonId = `upload-btn-${guid()}`; const uploadButtonId = `upload-btn-${guid()}`;
@ -528,6 +625,7 @@ const stampTool = () =>
}, },
populateContextMenu: (menu, state) => { populateContextMenu: (menu, state) => {
menu.appendChild(state.ctxmenu.snapToGridLabel); menu.appendChild(state.ctxmenu.snapToGridLabel);
menu.appendChild(state.ctxmenu.scaleSlider);
menu.appendChild(state.ctxmenu.resourceManager); menu.appendChild(state.ctxmenu.resourceManager);
}, },
shortcut: "U", shortcut: "U",