Skip to content

Commit 029b8ff

Browse files
0HyperCubeKeavon
authored andcommitted
Implement interactive scaling/motion of rulers (#306) (#385)
* Update ruler origin * Fix ruler text * Handle zoom * Remove log * Fix origin
1 parent 5641f5d commit 029b8ff

File tree

5 files changed

+78
-12
lines changed

5 files changed

+78
-12
lines changed

editor/src/document/document_file.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -623,8 +623,9 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
623623
}
624624
.into(),
625625
);
626+
let root_layerdata = self.layerdata(&[]);
626627

627-
let scale = 0.5 + ASYMPTOTIC_EFFECT + self.layerdata(&[]).scale * SCALE_EFFECT;
628+
let scale = 0.5 + ASYMPTOTIC_EFFECT + root_layerdata.scale * SCALE_EFFECT;
628629
let viewport_size = ipp.viewport_bounds.size();
629630
let viewport_mid = ipp.viewport_bounds.center();
630631
let [bounds1, bounds2] = self.graphene_document.visible_layers_bounding_box().unwrap_or([viewport_mid; 2]);
@@ -634,6 +635,13 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
634635
let scrollbar_position = DVec2::splat(0.5) - (bounds1.lerp(bounds2, 0.5) - viewport_mid) / (bounds_length - viewport_size);
635636
let scrollbar_multiplier = bounds_length - viewport_size;
636637
let scrollbar_size = viewport_size / bounds_length;
638+
639+
let log = root_layerdata.scale.log2();
640+
let mut ruler_inverval = if log < 0. { 100. * 2_f64.powf(-log.ceil()) } else { 100. / 2_f64.powf(log.ceil()) };
641+
let ruler_spacing = ruler_inverval * root_layerdata.scale;
642+
643+
let ruler_origin = self.graphene_document.root.transform.transform_point2(DVec2::ZERO);
644+
637645
responses.push_back(
638646
FrontendMessage::UpdateScrollbars {
639647
position: scrollbar_position.into(),
@@ -642,6 +650,15 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
642650
}
643651
.into(),
644652
);
653+
654+
responses.push_back(
655+
FrontendMessage::UpdateRulers {
656+
origin: ruler_origin.into(),
657+
spacing: ruler_spacing,
658+
interval: ruler_inverval,
659+
}
660+
.into(),
661+
);
645662
}
646663

647664
NudgeSelectedLayers(x, y) => {

editor/src/frontend/frontend_message_handler.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub enum FrontendMessage {
1818
UpdateLayer { path: Path, data: LayerPanelEntry },
1919
UpdateCanvas { document: String },
2020
UpdateScrollbars { position: (f64, f64), size: (f64, f64), multiplier: (f64, f64) },
21+
UpdateRulers { origin: (f64, f64), spacing: f64, interval: f64 },
2122
ExportDocument { document: String, name: String },
2223
SaveDocument { document: String, name: String },
2324
OpenDocumentBrowse,

frontend/src/components/panels/Document.vue

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,11 @@
111111
</LayoutCol>
112112
<LayoutCol :class="'viewport'">
113113
<LayoutRow :class="'bar-area'">
114-
<CanvasRuler :origin="0" :majorMarkSpacing="100" :direction="RulerDirection.Horizontal" :class="'top-ruler'" />
114+
<CanvasRuler :origin="rulerOrigin.x" :majorMarkSpacing="rulerSpacing" :numberInterval="rulerInterval" :direction="RulerDirection.Horizontal" :class="'top-ruler'" />
115115
</LayoutRow>
116116
<LayoutRow :class="'canvas-area'">
117117
<LayoutCol :class="'bar-area'">
118-
<CanvasRuler :origin="0" :majorMarkSpacing="100" :direction="RulerDirection.Vertical" />
118+
<CanvasRuler :origin="rulerOrigin.y" :majorMarkSpacing="rulerSpacing" :numberInterval="rulerInterval" :direction="RulerDirection.Vertical" />
119119
</LayoutCol>
120120
<LayoutCol :class="'canvas-area'">
121121
<div class="canvas" ref="canvas">
@@ -224,7 +224,7 @@
224224
<script lang="ts">
225225
import { defineComponent } from "vue";
226226
227-
import { ResponseType, registerResponseHandler, Response, UpdateCanvas, UpdateScrollbars, SetActiveTool, SetCanvasZoom, SetCanvasRotation } from "@/utilities/response-handler";
227+
import { ResponseType, registerResponseHandler, Response, UpdateCanvas, UpdateScrollbars, UpdateRulers, SetActiveTool, SetCanvasZoom, SetCanvasRotation } from "@/utilities/response-handler";
228228
import { SeparatorDirection, SeparatorType } from "@/components/widgets/widgets";
229229
import { comingSoon } from "@/utilities/errors";
230230
import { panicProxy } from "@/utilities/panic-proxy";
@@ -329,6 +329,15 @@ export default defineComponent({
329329
}
330330
});
331331
332+
registerResponseHandler(ResponseType.UpdateRulers, (responseData: Response) => {
333+
const updateData = responseData as UpdateRulers;
334+
if (updateData) {
335+
this.rulerOrigin = updateData.origin;
336+
this.rulerSpacing = updateData.spacing;
337+
this.rulerInterval = updateData.interval;
338+
}
339+
});
340+
332341
registerResponseHandler(ResponseType.SetActiveTool, (responseData: Response) => {
333342
const toolData = responseData as SetActiveTool;
334343
if (toolData) {
@@ -374,6 +383,9 @@ export default defineComponent({
374383
scrollbarPos: { x: 0.5, y: 0.5 },
375384
scrollbarSize: { x: 0.5, y: 0.5 },
376385
scrollbarMultiplier: { x: 0, y: 0 },
386+
rulerOrigin: { x: 0, y: 0 },
387+
rulerSpacing: 100,
388+
rulerInterval: 100,
377389
IncrementBehavior,
378390
IncrementDirection,
379391
MenuDirection,

frontend/src/components/widgets/rulers/CanvasRuler.vue

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,17 @@ export enum RulerDirection {
5555
"Vertical" = "Vertical",
5656
}
5757
58+
// Apparently the modulo operator in js does not work properly.
59+
const mod = (n: number, m: number) => {
60+
const remain = n % m;
61+
return Math.floor(remain >= 0 ? remain : remain + m);
62+
};
63+
5864
export default defineComponent({
5965
props: {
6066
direction: { type: String as PropType<RulerDirection>, default: RulerDirection.Vertical },
6167
origin: { type: Number, required: true },
68+
numberInterval: { type: Number, required: true },
6269
majorMarkSpacing: { type: Number, required: true },
6370
mediumDivisions: { type: Number, default: 5 },
6471
minorDivisions: { type: Number, default: 2 },
@@ -68,9 +75,8 @@ export default defineComponent({
6875
const isVertical = this.direction === RulerDirection.Vertical;
6976
const lineDirection = isVertical ? "H" : "V";
7077
71-
const offsetStart = this.origin % this.majorMarkSpacing;
72-
const phasingShift = offsetStart < this.majorMarkSpacing ? this.majorMarkSpacing : 0;
73-
const shiftedOffsetStart = offsetStart - phasingShift;
78+
const offsetStart = mod(this.origin, this.majorMarkSpacing);
79+
const shiftedOffsetStart = offsetStart - this.majorMarkSpacing;
7480
7581
const divisions = this.majorMarkSpacing / this.mediumDivisions / this.minorDivisions;
7682
const majorMarksFrequency = this.mediumDivisions * this.minorDivisions;
@@ -94,11 +100,13 @@ export default defineComponent({
94100
svgTexts(): {} {
95101
const isVertical = this.direction === RulerDirection.Vertical;
96102
97-
const offsetStart = this.origin % this.majorMarkSpacing;
98-
const phasingShift = offsetStart < this.majorMarkSpacing ? this.majorMarkSpacing : 0;
99-
const shiftedOffsetStart = offsetStart - phasingShift;
103+
const offsetStart = mod(this.origin, this.majorMarkSpacing);
104+
const shiftedOffsetStart = offsetStart - this.majorMarkSpacing;
100105
101106
const svgTextCoordinates = [];
107+
108+
let text = (Math.ceil(-this.origin / this.majorMarkSpacing) - 1) * this.numberInterval;
109+
102110
for (let location = shiftedOffsetStart; location < this.rulerLength; location += this.majorMarkSpacing) {
103111
const destination = Math.round(location);
104112
const x = isVertical ? 9 : destination + 2;
@@ -107,7 +115,9 @@ export default defineComponent({
107115
let transform = `translate(${x} ${y})`;
108116
if (isVertical) transform += " rotate(270)";
109117
110-
svgTextCoordinates.push({ transform, text: location });
118+
svgTextCoordinates.push({ transform, text });
119+
120+
text += this.numberInterval;
111121
}
112122
113123
return svgTextCoordinates;

frontend/src/utilities/response-handler.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const state = reactive({
1515
export enum ResponseType {
1616
UpdateCanvas = "UpdateCanvas",
1717
UpdateScrollbars = "UpdateScrollbars",
18+
UpdateRulers = "UpdateRulers",
1819
ExportDocument = "ExportDocument",
1920
SaveDocument = "SaveDocument",
2021
OpenDocumentBrowse = "OpenDocumentBrowse",
@@ -67,6 +68,8 @@ function parseResponse(responseType: string, data: any): Response {
6768
return newUpdateCanvas(data.UpdateCanvas);
6869
case "UpdateScrollbars":
6970
return newUpdateScrollbars(data.UpdateScrollbars);
71+
case "UpdateRulers":
72+
return newUpdateRulers(data.UpdateRulers);
7073
case "UpdateLayer":
7174
return newUpdateLayer(data.UpdateLayer);
7275
case "SetCanvasZoom":
@@ -94,7 +97,17 @@ function parseResponse(responseType: string, data: any): Response {
9497
}
9598
}
9699

97-
export type Response = SetActiveTool | UpdateCanvas | UpdateScrollbars | UpdateLayer | DocumentChanged | DisplayFolderTreeStructure | UpdateWorkingColors | SetCanvasZoom | SetCanvasRotation;
100+
export type Response =
101+
| SetActiveTool
102+
| UpdateCanvas
103+
| UpdateScrollbars
104+
| UpdateRulers
105+
| UpdateLayer
106+
| DocumentChanged
107+
| DisplayFolderTreeStructure
108+
| UpdateWorkingColors
109+
| SetCanvasZoom
110+
| SetCanvasRotation;
98111

99112
export interface UpdateOpenDocumentsList {
100113
open_documents: Array<string>;
@@ -204,6 +217,19 @@ function newUpdateScrollbars(input: any): UpdateScrollbars {
204217
};
205218
}
206219

220+
export interface UpdateRulers {
221+
origin: { x: number; y: number };
222+
spacing: number;
223+
interval: number;
224+
}
225+
function newUpdateRulers(input: any): UpdateRulers {
226+
return {
227+
origin: { x: input.origin[0], y: input.origin[1] },
228+
spacing: input.spacing,
229+
interval: input.interval,
230+
};
231+
}
232+
207233
export interface ExportDocument {
208234
document: string;
209235
name: string;

0 commit comments

Comments
 (0)