mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-01 02:58:11 +08:00
Make auto-panning speed uniform (#1690)
* Make auto-panning speed uniform * Abstract time-delta calculation to `TimeInfo` * Update docs and add additional check * Apply code review changes
This commit is contained in:
@@ -213,15 +213,12 @@ impl Fsm for ArtboardToolFsmState {
|
||||
let mouse_position = input.mouse.position;
|
||||
tool_data.resize_artboard(responses, document, mouse_position, from_center, constrain_square);
|
||||
|
||||
tool_data.auto_panning.setup_by_mouse_position(
|
||||
mouse_position,
|
||||
input.viewport_bounds.size(),
|
||||
&[
|
||||
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
|
||||
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
|
||||
],
|
||||
responses,
|
||||
);
|
||||
// AutoPanning
|
||||
let messages = [
|
||||
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
|
||||
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
ArtboardToolFsmState::ResizingBounds
|
||||
}
|
||||
@@ -245,15 +242,12 @@ impl Fsm for ArtboardToolFsmState {
|
||||
bounds.bounds[0] = position.round();
|
||||
bounds.bounds[1] = position.round() + size.round();
|
||||
|
||||
tool_data.auto_panning.setup_by_mouse_position(
|
||||
mouse_position,
|
||||
input.viewport_bounds.size(),
|
||||
&[
|
||||
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
|
||||
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
|
||||
],
|
||||
responses,
|
||||
);
|
||||
// AutoPanning
|
||||
let messages = [
|
||||
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
|
||||
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
}
|
||||
ArtboardToolFsmState::Dragging
|
||||
}
|
||||
@@ -303,15 +297,12 @@ impl Fsm for ArtboardToolFsmState {
|
||||
})
|
||||
}
|
||||
|
||||
tool_data.auto_panning.setup_by_mouse_position(
|
||||
mouse_position,
|
||||
input.viewport_bounds.size(),
|
||||
&[
|
||||
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
|
||||
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
|
||||
],
|
||||
responses,
|
||||
);
|
||||
// AutoPanning
|
||||
let messages = [
|
||||
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
|
||||
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
ArtboardToolFsmState::Drawing
|
||||
}
|
||||
@@ -326,12 +317,14 @@ impl Fsm for ArtboardToolFsmState {
|
||||
ArtboardToolFsmState::Ready
|
||||
}
|
||||
(ArtboardToolFsmState::ResizingBounds, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
|
||||
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses);
|
||||
// AutoPanning
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
|
||||
ArtboardToolFsmState::ResizingBounds
|
||||
}
|
||||
(ArtboardToolFsmState::Dragging, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
|
||||
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) {
|
||||
// AutoPanning
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
tool_data.drag_current += shift;
|
||||
tool_data.drag_start += shift;
|
||||
}
|
||||
@@ -339,20 +332,20 @@ impl Fsm for ArtboardToolFsmState {
|
||||
ArtboardToolFsmState::Dragging
|
||||
}
|
||||
(ArtboardToolFsmState::Drawing, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
|
||||
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) {
|
||||
// AutoPanning
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
tool_data.drag_start += shift;
|
||||
}
|
||||
|
||||
ArtboardToolFsmState::Drawing
|
||||
}
|
||||
(state, ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }) => {
|
||||
tool_data.auto_panning.stop(
|
||||
&[
|
||||
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
|
||||
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
|
||||
],
|
||||
responses,
|
||||
);
|
||||
// AutoPanning
|
||||
let messages = [
|
||||
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
|
||||
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
|
||||
];
|
||||
tool_data.auto_panning.stop(&messages, responses);
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ impl Fsm for EllipseToolFsmState {
|
||||
EllipseToolMessage::PointerOutsideViewport { center, lock_ratio }.into(),
|
||||
EllipseToolMessage::PointerMove { center, lock_ratio }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
self
|
||||
}
|
||||
@@ -242,7 +242,7 @@ impl Fsm for EllipseToolFsmState {
|
||||
}
|
||||
(EllipseToolFsmState::Drawing, EllipseToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
|
||||
EllipseToolFsmState::Drawing
|
||||
}
|
||||
|
||||
@@ -440,13 +440,13 @@ impl Fsm for GradientToolFsmState {
|
||||
GradientToolMessage::PointerOutsideViewport { constrain_axis }.into(),
|
||||
GradientToolMessage::PointerMove { constrain_axis }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
GradientToolFsmState::Drawing
|
||||
}
|
||||
(GradientToolFsmState::Drawing, GradientToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) {
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
if let Some(selected_gradient) = &mut tool_data.selected_gradient {
|
||||
selected_gradient.transform.translation += shift;
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ impl Fsm for LineToolFsmState {
|
||||
LineToolMessage::PointerOutsideViewport { center, snap_angle, lock_angle }.into(),
|
||||
LineToolMessage::PointerMove { center, snap_angle, lock_angle }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
LineToolFsmState::Drawing
|
||||
}
|
||||
@@ -215,7 +215,7 @@ impl Fsm for LineToolFsmState {
|
||||
}
|
||||
(LineToolFsmState::Drawing, LineToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
|
||||
LineToolFsmState::Drawing
|
||||
}
|
||||
|
||||
@@ -496,7 +496,7 @@ impl Fsm for PathToolFsmState {
|
||||
|
||||
// Auto-panning
|
||||
let messages = [PathToolMessage::PointerOutsideViewport { alt, shift }.into(), PathToolMessage::PointerMove { alt, shift }.into()];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
PathToolFsmState::DrawingBox
|
||||
}
|
||||
@@ -507,13 +507,13 @@ impl Fsm for PathToolFsmState {
|
||||
|
||||
// Auto-panning
|
||||
let messages = [PathToolMessage::PointerOutsideViewport { alt, shift }.into(), PathToolMessage::PointerMove { alt, shift }.into()];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
PathToolFsmState::Dragging
|
||||
}
|
||||
(PathToolFsmState::DrawingBox, PathToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) {
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
tool_data.drag_start_pos += shift;
|
||||
}
|
||||
|
||||
@@ -521,7 +521,7 @@ impl Fsm for PathToolFsmState {
|
||||
}
|
||||
(PathToolFsmState::Dragging, PathToolMessage::PointerOutsideViewport { shift, .. }) => {
|
||||
// Auto-panning
|
||||
if let Some(delta) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) {
|
||||
if let Some(delta) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
let shift_state = input.keyboard.get(shift as usize);
|
||||
shape_editor.move_selected_points(&document.network, &document.metadata, -delta, shift_state, responses);
|
||||
}
|
||||
|
||||
@@ -685,7 +685,7 @@ impl Fsm for PenToolFsmState {
|
||||
PenToolMessage::PointerOutsideViewport { snap_angle, break_handle, lock_angle }.into(),
|
||||
PenToolMessage::PointerMove { snap_angle, break_handle, lock_angle }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
state
|
||||
}
|
||||
@@ -704,7 +704,7 @@ impl Fsm for PenToolFsmState {
|
||||
PenToolMessage::PointerOutsideViewport { snap_angle, break_handle, lock_angle }.into(),
|
||||
PenToolMessage::PointerMove { snap_angle, break_handle, lock_angle }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
state
|
||||
}
|
||||
@@ -715,13 +715,13 @@ impl Fsm for PenToolFsmState {
|
||||
}
|
||||
(PenToolFsmState::DraggingHandle, PenToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
|
||||
PenToolFsmState::DraggingHandle
|
||||
}
|
||||
(PenToolFsmState::PlacingAnchor, PenToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
|
||||
PenToolFsmState::PlacingAnchor
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ impl Fsm for PolygonToolFsmState {
|
||||
PolygonToolMessage::PointerOutsideViewport { center, lock_ratio }.into(),
|
||||
PolygonToolMessage::PointerMove { center, lock_ratio }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
self
|
||||
}
|
||||
@@ -286,7 +286,7 @@ impl Fsm for PolygonToolFsmState {
|
||||
}
|
||||
(PolygonToolFsmState::Drawing, PolygonToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
|
||||
PolygonToolFsmState::Drawing
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ impl Fsm for RectangleToolFsmState {
|
||||
RectangleToolMessage::PointerOutsideViewport { center, lock_ratio }.into(),
|
||||
RectangleToolMessage::PointerMove { center, lock_ratio }.into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
self
|
||||
}
|
||||
@@ -248,7 +248,7 @@ impl Fsm for RectangleToolFsmState {
|
||||
}
|
||||
(RectangleToolFsmState::Drawing, RectangleToolMessage::PointerOutsideViewport { .. }) => {
|
||||
// Auto-panning
|
||||
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
|
||||
RectangleToolFsmState::Drawing
|
||||
}
|
||||
|
||||
@@ -654,15 +654,12 @@ impl Fsm for SelectToolFsmState {
|
||||
}
|
||||
tool_data.drag_current += mouse_delta;
|
||||
|
||||
tool_data.auto_panning.setup_by_mouse_position(
|
||||
input.mouse.position,
|
||||
input.viewport_bounds.size(),
|
||||
&[
|
||||
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
|
||||
SelectToolMessage::PointerMove(modifier_keys).into(),
|
||||
],
|
||||
responses,
|
||||
);
|
||||
// AutoPanning
|
||||
let messages = [
|
||||
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
|
||||
SelectToolMessage::PointerMove(modifier_keys).into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
SelectToolFsmState::Dragging
|
||||
}
|
||||
@@ -698,15 +695,12 @@ impl Fsm for SelectToolFsmState {
|
||||
|
||||
selected.apply_transformation(bounds.original_bound_transform * transformation * bounds.original_bound_transform.inverse());
|
||||
|
||||
tool_data.auto_panning.setup_by_mouse_position(
|
||||
input.mouse.position,
|
||||
input.viewport_bounds.size(),
|
||||
&[
|
||||
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
|
||||
SelectToolMessage::PointerMove(modifier_keys).into(),
|
||||
],
|
||||
responses,
|
||||
);
|
||||
// AutoPanning
|
||||
let messages = [
|
||||
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
|
||||
SelectToolMessage::PointerMove(modifier_keys).into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
}
|
||||
}
|
||||
SelectToolFsmState::ResizingBounds
|
||||
@@ -751,15 +745,12 @@ impl Fsm for SelectToolFsmState {
|
||||
let snapped_mouse_position = mouse_position; //tool_data.snap_manager.snap_position(responses, document, mouse_position);
|
||||
tool_data.pivot.set_viewport_position(snapped_mouse_position, document, responses);
|
||||
|
||||
tool_data.auto_panning.setup_by_mouse_position(
|
||||
input.mouse.position,
|
||||
input.viewport_bounds.size(),
|
||||
&[
|
||||
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
|
||||
SelectToolMessage::PointerMove(modifier_keys).into(),
|
||||
],
|
||||
responses,
|
||||
);
|
||||
// AutoPanning
|
||||
let messages = [
|
||||
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
|
||||
SelectToolMessage::PointerMove(modifier_keys).into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
SelectToolFsmState::DraggingPivot
|
||||
}
|
||||
@@ -767,15 +758,12 @@ impl Fsm for SelectToolFsmState {
|
||||
tool_data.drag_current = input.mouse.position;
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
|
||||
tool_data.auto_panning.setup_by_mouse_position(
|
||||
input.mouse.position,
|
||||
input.viewport_bounds.size(),
|
||||
&[
|
||||
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
|
||||
SelectToolMessage::PointerMove(modifier_keys).into(),
|
||||
],
|
||||
responses,
|
||||
);
|
||||
// AutoPanning
|
||||
let messages = [
|
||||
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
|
||||
SelectToolMessage::PointerMove(modifier_keys).into(),
|
||||
];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
let selection = tool_data.nested_selection_behavior;
|
||||
SelectToolFsmState::DrawingBox { selection }
|
||||
@@ -800,7 +788,8 @@ impl Fsm for SelectToolFsmState {
|
||||
SelectToolFsmState::Ready { selection }
|
||||
}
|
||||
(SelectToolFsmState::Dragging, SelectToolMessage::PointerOutsideViewport(_)) => {
|
||||
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) {
|
||||
// AutoPanning
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
tool_data.drag_current += shift;
|
||||
tool_data.drag_start += shift;
|
||||
}
|
||||
@@ -808,7 +797,8 @@ impl Fsm for SelectToolFsmState {
|
||||
SelectToolFsmState::Dragging
|
||||
}
|
||||
(SelectToolFsmState::ResizingBounds, SelectToolMessage::PointerOutsideViewport(_)) => {
|
||||
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) {
|
||||
// AutoPanning
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
if let Some(ref mut bounds) = &mut tool_data.bounding_box_manager {
|
||||
bounds.center_of_transformation += shift;
|
||||
bounds.original_bound_transform.translation += shift;
|
||||
@@ -818,25 +808,26 @@ impl Fsm for SelectToolFsmState {
|
||||
self
|
||||
}
|
||||
(SelectToolFsmState::DraggingPivot, SelectToolMessage::PointerOutsideViewport(_)) => {
|
||||
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses);
|
||||
// AutoPanning
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
|
||||
self
|
||||
}
|
||||
(SelectToolFsmState::DrawingBox { .. }, SelectToolMessage::PointerOutsideViewport(_)) => {
|
||||
if let Some(shift) = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses) {
|
||||
// AutoPanning
|
||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
|
||||
tool_data.drag_start += shift;
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
(state, SelectToolMessage::PointerOutsideViewport(modifier_keys)) => {
|
||||
tool_data.auto_panning.stop(
|
||||
&[
|
||||
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
|
||||
SelectToolMessage::PointerMove(modifier_keys).into(),
|
||||
],
|
||||
responses,
|
||||
);
|
||||
// AutoPanning
|
||||
let messages = [
|
||||
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
|
||||
SelectToolMessage::PointerMove(modifier_keys).into(),
|
||||
];
|
||||
tool_data.auto_panning.stop(&messages, responses);
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
@@ -271,13 +271,13 @@ impl Fsm for SplineToolFsmState {
|
||||
|
||||
// Auto-panning
|
||||
let messages = [SplineToolMessage::PointerOutsideViewport.into(), SplineToolMessage::PointerMove.into()];
|
||||
tool_data.auto_panning.setup_by_mouse_position(input.mouse.position, input.viewport_bounds.size(), &messages, responses);
|
||||
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
|
||||
|
||||
SplineToolFsmState::Drawing
|
||||
}
|
||||
(SplineToolFsmState::Drawing, SplineToolMessage::PointerOutsideViewport) => {
|
||||
// Auto-panning
|
||||
let _ = AutoPanning::shift_viewport(input.mouse.position, input.viewport_bounds.size(), responses);
|
||||
let _ = tool_data.auto_panning.shift_viewport(input, responses);
|
||||
|
||||
SplineToolFsmState::Drawing
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user