mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-31 09:08:30 +01:00
The Canvas UI now shows a grid while the user is painting. (#75604)
A grid is shown while the user is holding a painting tool on an editable canvas. This is achieved by drawing empty rectangles after the filled ones are placed whenever the canvas is updated and if requirements are met. It's by no mean perfect, especially since the strokeStyle is a mere "#888888" hexcolor, the contrast may get low around colors of similar lightness. But I don't think I've much the strength to seek out a fancier solution to a peeve that's hardly a botherance anyway while the canvas is still mostly white. I've also had a maintainer suggest me to make a toggle to disable/enable. I talked a bit how that'd be a bit more complex to integrate but not much so frankly, although switching hands or putting away the tool already works for that. That said, I'm willing to do it if player feedback suggests such toggle should be integrated.
This commit is contained in:
@@ -50,6 +50,8 @@
|
||||
/// Is it clean canvas or was there something painted on it at some point, used to decide when to show wip splotch overlay
|
||||
var/used = FALSE
|
||||
var/finalized = FALSE //Blocks edits
|
||||
/// Whether a grid should be shown in the UI if the canvas is editable and the viewer is holding a painting tool.
|
||||
var/show_grid = TRUE
|
||||
var/icon_generated = FALSE
|
||||
var/icon/generated_icon
|
||||
///boolean that blocks persistence from saving it. enabled from printing copies, because we do not want to save copies.
|
||||
@@ -128,12 +130,13 @@
|
||||
.["finalized"] = finalized
|
||||
.["editable"] = !finalized //Ideally you should be able to draw moustaches on existing paintings in the gallery but that's not implemented yet
|
||||
.["show_plaque"] = istype(loc,/obj/structure/sign/painting)
|
||||
.["show_grid"] = show_grid
|
||||
.["paint_tool_palette"] = null
|
||||
var/obj/item/painting_implement = user.get_active_held_item()
|
||||
if(!painting_implement)
|
||||
.["paint_tool_color"] = null
|
||||
return
|
||||
.["paint_tool_color"] = get_paint_tool_color(painting_implement)
|
||||
// Clearing additional data so that it doesn't linger around if the painting tool is dropped.
|
||||
.["paint_tool_palette"] = null
|
||||
SEND_SIGNAL(painting_implement, COMSIG_PAINTING_TOOL_GET_ADDITIONAL_DATA, .)
|
||||
|
||||
/obj/item/canvas/examine(mob/user)
|
||||
@@ -190,6 +193,9 @@
|
||||
return FALSE
|
||||
SEND_SIGNAL(painting_implement, COMSIG_PAINTING_TOOL_PALETTE_COLOR_CHANGED, chosen_color, params["color_index"])
|
||||
. = TRUE
|
||||
if("toggle_grid")
|
||||
. = TRUE
|
||||
show_grid = !show_grid
|
||||
if("finalize")
|
||||
. = TRUE
|
||||
finalize(user)
|
||||
|
||||
@@ -18,6 +18,7 @@ type PaintCanvasProps = Partial<{
|
||||
editable: boolean;
|
||||
drawing_color: string | null;
|
||||
has_palette: boolean;
|
||||
show_grid: boolean;
|
||||
}>;
|
||||
|
||||
type PointData = {
|
||||
@@ -37,6 +38,7 @@ const toMassPaintFormat = (data: PointData[]) => {
|
||||
class PaintCanvas extends Component<PaintCanvasProps> {
|
||||
canvasRef: RefObject<HTMLCanvasElement>;
|
||||
baseImageData: Color[][];
|
||||
is_grid_shown: boolean;
|
||||
modifiedElements: PointData[];
|
||||
onCanvasModified: (data: PointData[]) => void;
|
||||
onCanvasDropper: (x: number, y: number) => void;
|
||||
@@ -47,6 +49,7 @@ class PaintCanvas extends Component<PaintCanvasProps> {
|
||||
super(props);
|
||||
this.canvasRef = createRef<HTMLCanvasElement>();
|
||||
this.modifiedElements = [];
|
||||
this.is_grid_shown = false;
|
||||
this.drawing = false;
|
||||
this.onCanvasModified = props.onCanvasModifiedHandler;
|
||||
this.onCanvasDropper = props.onCanvasDropperHandler;
|
||||
@@ -65,9 +68,10 @@ class PaintCanvas extends Component<PaintCanvasProps> {
|
||||
componentDidUpdate() {
|
||||
// eslint-disable-next-line max-len
|
||||
if (
|
||||
this.props.value !== undefined &&
|
||||
JSON.stringify(this.baseImageData) !==
|
||||
JSON.stringify(fromDM(this.props.value))
|
||||
(this.props.value !== undefined &&
|
||||
JSON.stringify(this.baseImageData) !==
|
||||
JSON.stringify(fromDM(this.props.value))) ||
|
||||
this.is_grid_shown !== this.props.show_grid
|
||||
) {
|
||||
this.syncCanvas();
|
||||
}
|
||||
@@ -91,6 +95,7 @@ class PaintCanvas extends Component<PaintCanvasProps> {
|
||||
return;
|
||||
}
|
||||
this.baseImageData = fromDM(this.props.value);
|
||||
this.is_grid_shown = !!this.props.show_grid;
|
||||
this.modifiedElements = [];
|
||||
|
||||
const canvas = this.canvasRef.current!;
|
||||
@@ -101,6 +106,11 @@ class PaintCanvas extends Component<PaintCanvasProps> {
|
||||
const color = element[y];
|
||||
ctx.fillStyle = color.toString();
|
||||
ctx.fillRect(x, y, 1, 1);
|
||||
if (this.is_grid_shown) {
|
||||
ctx.strokeStyle = '#888888';
|
||||
ctx.lineWidth = 0.05;
|
||||
ctx.strokeRect(x, y, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,6 +151,11 @@ class PaintCanvas extends Component<PaintCanvasProps> {
|
||||
const ctx = canvas.getContext('2d')!;
|
||||
ctx.fillStyle = color;
|
||||
ctx.fillRect(x, y, 1, 1);
|
||||
if (this.is_grid_shown) {
|
||||
ctx.strokeStyle = '#888888';
|
||||
ctx.lineWidth = 0.05;
|
||||
ctx.strokeRect(x, y, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
handleDrawing(event: MouseEvent) {
|
||||
@@ -222,6 +237,7 @@ type CanvasData = {
|
||||
patron: string | null;
|
||||
date: string | null;
|
||||
show_plaque: boolean;
|
||||
show_grid: boolean;
|
||||
};
|
||||
|
||||
export const Canvas = (props, context) => {
|
||||
@@ -231,6 +247,7 @@ export const Canvas = (props, context) => {
|
||||
const scaled_height = height * data.px_per_unit;
|
||||
const average_plaque_height = 90;
|
||||
const palette_height = 44;
|
||||
const griddy = !!data.show_grid && !!data.editable && !!data.paint_tool_color;
|
||||
return (
|
||||
<Window
|
||||
width={scaled_width + 72}
|
||||
@@ -241,31 +258,40 @@ export const Canvas = (props, context) => {
|
||||
(data.editable && data.paint_tool_palette ? palette_height : 0)
|
||||
}>
|
||||
<Window.Content>
|
||||
{!!data.paint_tool_palette && (
|
||||
<Tooltip
|
||||
content={
|
||||
multiline`
|
||||
You can Right-Click the canvas to change the color of
|
||||
the painting tool to that of the clicked pixel.
|
||||
` +
|
||||
(data.editable
|
||||
? multiline`
|
||||
\n You can also select a color from the
|
||||
palette at the bottom of the UI,
|
||||
or input a new one with Right-Click.
|
||||
`
|
||||
: '')
|
||||
}>
|
||||
<Icon
|
||||
name="question-circle"
|
||||
position="relative"
|
||||
color="blue"
|
||||
size={1.5}
|
||||
m={0.5}
|
||||
/>
|
||||
<br />
|
||||
</Tooltip>
|
||||
)}
|
||||
<Flex align="start" direction="row">
|
||||
{!!data.paint_tool_palette && (
|
||||
<Flex.Item>
|
||||
<Tooltip
|
||||
content={
|
||||
multiline`
|
||||
You can Right-Click the canvas to change the color of
|
||||
the painting tool to that of the clicked pixel.
|
||||
` +
|
||||
(data.editable
|
||||
? multiline`
|
||||
\n You can also select a color from the
|
||||
palette at the bottom of the UI,
|
||||
or input a new one with Right-Click.
|
||||
`
|
||||
: '')
|
||||
}>
|
||||
<Icon name="question-circle" color="blue" size={1.5} m={0.5} />
|
||||
</Tooltip>
|
||||
</Flex.Item>
|
||||
)}
|
||||
{!!data.editable && !!data.paint_tool_color && (
|
||||
<Flex.Item>
|
||||
<Button
|
||||
title="Grid Toggle"
|
||||
icon="th-large"
|
||||
backgroundColor={data.show_grid ? 'green' : 'red'}
|
||||
onClick={() => act('toggle_grid')}
|
||||
size={1.5}
|
||||
m={0.5}
|
||||
/>
|
||||
</Flex.Item>
|
||||
)}
|
||||
</Flex>
|
||||
<Box textAlign="center">
|
||||
<PaintCanvas
|
||||
value={data.grid}
|
||||
@@ -274,6 +300,7 @@ export const Canvas = (props, context) => {
|
||||
width={scaled_width}
|
||||
height={scaled_height}
|
||||
drawing_color={data.paint_tool_color}
|
||||
show_grid={griddy}
|
||||
onCanvasModifiedHandler={(changed) =>
|
||||
act('paint', { data: toMassPaintFormat(changed) })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user