mirror of
https://github.com/scratchfoundation/scratch-paint.git
synced 2025-01-08 13:42:00 -05:00
Add the background guide layer
This commit is contained in:
parent
dacc17d6c4
commit
29a3d74143
7 changed files with 103 additions and 10 deletions
|
@ -6,7 +6,7 @@ import {changeMode} from '../reducers/modes';
|
|||
import {undo, redo, undoSnapshot} from '../reducers/undo';
|
||||
import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
|
||||
|
||||
import {getGuideLayer} from '../helper/layer';
|
||||
import {getGuideLayer, getBackgroundGuideLayer} from '../helper/layer';
|
||||
import {performUndo, performRedo, performSnapshot} from '../helper/undo';
|
||||
import {bringToFront, sendBackward, sendToBack, bringForward} from '../helper/order';
|
||||
import {groupSelection, ungroupSelection} from '../helper/group';
|
||||
|
@ -41,7 +41,9 @@ class PaintEditor extends React.Component {
|
|||
handleUpdateSvg (skipSnapshot) {
|
||||
// Hide guide layer
|
||||
const guideLayer = getGuideLayer();
|
||||
const backgroundGuideLayer = getBackgroundGuideLayer();
|
||||
guideLayer.remove();
|
||||
backgroundGuideLayer.remove();
|
||||
const bounds = paper.project.activeLayer.bounds;
|
||||
this.props.onUpdateSvg(
|
||||
paper.project.exportSVG({
|
||||
|
@ -53,6 +55,8 @@ class PaintEditor extends React.Component {
|
|||
if (!skipSnapshot) {
|
||||
performSnapshot(this.props.undoSnapshot);
|
||||
}
|
||||
paper.project.addLayer(backgroundGuideLayer);
|
||||
backgroundGuideLayer.sendToBack();
|
||||
paper.project.addLayer(guideLayer);
|
||||
}
|
||||
handleUndo () {
|
||||
|
|
|
@ -7,6 +7,7 @@ import paper from '@scratch/paper';
|
|||
import {performSnapshot} from '../helper/undo';
|
||||
import {undoSnapshot, clearUndoState} from '../reducers/undo';
|
||||
import {isGroup, ungroupItems} from '../helper/group';
|
||||
import {setupLayers} from '../helper/layer';
|
||||
|
||||
import styles from './paper-canvas.css';
|
||||
|
||||
|
@ -22,6 +23,8 @@ class PaperCanvas extends React.Component {
|
|||
paper.setup(this.canvas);
|
||||
// Don't show handles by default
|
||||
paper.settings.handleSize = 0;
|
||||
// Make layers.
|
||||
setupLayers();
|
||||
if (this.props.svg) {
|
||||
this.importSvg(this.props.svg, this.props.rotationCenterX, this.props.rotationCenterY);
|
||||
} else {
|
||||
|
@ -31,7 +34,9 @@ class PaperCanvas extends React.Component {
|
|||
componentWillReceiveProps (newProps) {
|
||||
if (this.props.svgId === newProps.svgId) return;
|
||||
for (const layer of paper.project.layers) {
|
||||
layer.removeChildren();
|
||||
if (!layer.data.isBackgroundGuideLayer) {
|
||||
layer.removeChildren();
|
||||
}
|
||||
}
|
||||
this.props.clearUndo();
|
||||
if (newProps.svg) {
|
||||
|
|
|
@ -3,7 +3,7 @@ import log from '../../log/log';
|
|||
import BroadBrushHelper from './broad-brush-helper';
|
||||
import SegmentBrushHelper from './segment-brush-helper';
|
||||
import {MIXED, styleCursorPreview} from '../../helper/style-path';
|
||||
import {clearSelection} from '../../helper/selection';
|
||||
import {clearSelection, getItems} from '../../helper/selection';
|
||||
import {getGuideLayer} from '../../helper/layer';
|
||||
|
||||
/**
|
||||
|
@ -193,7 +193,7 @@ class Blobbiness {
|
|||
const blob = this;
|
||||
|
||||
// Get all path items to merge with
|
||||
const paths = paper.project.getItems({
|
||||
const paths = getItems({
|
||||
match: function (item) {
|
||||
return blob.isMergeable(lastPath, item) &&
|
||||
item.parent instanceof paper.Layer; // don't merge with nested in group
|
||||
|
@ -245,7 +245,7 @@ class Blobbiness {
|
|||
|
||||
// Get all path items to merge with
|
||||
// If there are selected items, try to erase from amongst those.
|
||||
let items = paper.project.getItems({
|
||||
let items = getItems({
|
||||
match: function (item) {
|
||||
return item.selected && blob.isMergeable(lastPath, item) && blob.touches(lastPath, item);
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ class Blobbiness {
|
|||
// and deselect the selection
|
||||
if (items.length === 0) {
|
||||
clearSelection(this.clearSelectedItems);
|
||||
items = paper.project.getItems({
|
||||
items = getItems({
|
||||
match: function (item) {
|
||||
return blob.isMergeable(lastPath, item) && blob.touches(lastPath, item);
|
||||
}
|
||||
|
|
|
@ -15,4 +15,70 @@ const getGuideLayer = function () {
|
|||
return guideLayer;
|
||||
};
|
||||
|
||||
export {getGuideLayer};
|
||||
const getBackgroundGuideLayer = function () {
|
||||
for (let i = 0; i < paper.project.layers.length; i++) {
|
||||
const layer = paper.project.layers[i];
|
||||
if (layer.data && layer.data.isBackgroundGuideLayer) {
|
||||
return layer;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const _makePaintingLayer = function () {
|
||||
const paintingLayer = new paper.Layer();
|
||||
paintingLayer.data.isPaintingLayer = true;
|
||||
return paintingLayer;
|
||||
};
|
||||
|
||||
const _makeBackgroundGuideLayer = function () {
|
||||
const BLOCK_WIDTH = 4;
|
||||
const guideLayer = new paper.Layer();
|
||||
guideLayer.locked = true;
|
||||
for (let i = 0; i < 500 / BLOCK_WIDTH; i += 2) {
|
||||
for (let j = 0; j < 400 / BLOCK_WIDTH; j++) {
|
||||
const rect = new paper.Shape.Rectangle(
|
||||
new paper.Point((i + (j % 2)) * BLOCK_WIDTH, j * BLOCK_WIDTH),
|
||||
new paper.Point((i + (j % 2) + 1) * BLOCK_WIDTH, (j + 1) * BLOCK_WIDTH)
|
||||
);
|
||||
rect.fillColor = '#E5E5E5';
|
||||
rect.guide = true;
|
||||
rect.locked = true;
|
||||
}
|
||||
}
|
||||
|
||||
const vLine = new paper.Path.Line(new paper.Point(0, -7), new paper.Point(0, 7));
|
||||
vLine.strokeWidth = 2;
|
||||
vLine.strokeColor = '#ccc';
|
||||
vLine.position = paper.view.center;
|
||||
vLine.guide = true;
|
||||
vLine.locked = true;
|
||||
|
||||
const hLine = new paper.Path.Line(new paper.Point(-7, 0), new paper.Point(7, 0));
|
||||
hLine.strokeWidth = 2;
|
||||
hLine.strokeColor = '#ccc';
|
||||
hLine.position = paper.view.center;
|
||||
hLine.guide = true;
|
||||
hLine.locked = true;
|
||||
|
||||
const circle = new paper.Shape.Circle(new paper.Point(0, 0), 5);
|
||||
circle.strokeWidth = 2;
|
||||
circle.strokeColor = '#ccc';
|
||||
circle.position = paper.view.center;
|
||||
circle.guide = true;
|
||||
circle.locked = true;
|
||||
|
||||
guideLayer.data.isBackgroundGuideLayer = true;
|
||||
guideLayer.sendToBack();
|
||||
return guideLayer;
|
||||
};
|
||||
|
||||
const setupLayers = function () {
|
||||
_makeBackgroundGuideLayer();
|
||||
_makePaintingLayer().activate();
|
||||
};
|
||||
|
||||
export {
|
||||
getGuideLayer,
|
||||
getBackgroundGuideLayer,
|
||||
setupLayers
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import paper from '@scratch/paper';
|
||||
import {getItems} from '../selection';
|
||||
|
||||
/**
|
||||
* Tool to handle scaling items by pulling on the handles around the edges of the bounding
|
||||
|
@ -55,9 +56,9 @@ class ScaleTool {
|
|||
const modOrigSize = this.origSize;
|
||||
|
||||
// get item to insert below so that scaled items stay in same z position
|
||||
const items = paper.project.getItems({
|
||||
const items = getItems({
|
||||
match: function (item) {
|
||||
if (item instanceof paper.Layer || item.data.isHelperItem) {
|
||||
if (item instanceof paper.Layer) {
|
||||
return false;
|
||||
}
|
||||
for (const scaleItem of scaleTool.scaleItems) {
|
||||
|
|
|
@ -5,6 +5,21 @@ import {getItemsGroup, isGroup} from './group';
|
|||
import {getRootItem, isCompoundPathItem, isBoundsItem, isPathItem, isPGTextItem} from './item';
|
||||
import {getItemsCompoundPath, isCompoundPath, isCompoundPathChild} from './compound-path';
|
||||
|
||||
/**
|
||||
* Wrapper for paper.project.getItems that excludes our helper items
|
||||
* @param {?object} options See paper.js docs for paper.Item.getItems
|
||||
* @return {Array<paper.Item>} items that match options
|
||||
*/
|
||||
const getItems = function (options) {
|
||||
const newMatcher = function (item) {
|
||||
return !item.locked &&
|
||||
!(item.data && item.data.isHelperItem) &&
|
||||
(!options.match || options.match(item));
|
||||
};
|
||||
const newOptions = {...options, match: newMatcher};
|
||||
return paper.project.getItems(newOptions);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {boolean} includeGuides True if guide layer items like the bounding box should
|
||||
* be included in the returned items.
|
||||
|
@ -389,6 +404,7 @@ const shouldShowSelectAll = function () {
|
|||
};
|
||||
|
||||
export {
|
||||
getItems,
|
||||
getAllRootItems,
|
||||
selectAllItems,
|
||||
selectAllSegments,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import paper from '@scratch/paper';
|
||||
import {getItems} from './selection';
|
||||
|
||||
/**
|
||||
* @param {paper.Point} point1 point 1
|
||||
|
@ -19,7 +20,7 @@ const touching = function (point1, point2, tolerance) {
|
|||
* tolerance distance of the given point, or null if none exists.
|
||||
*/
|
||||
const endPointHit = function (point, tolerance, excludePath) {
|
||||
const lines = paper.project.getItems({
|
||||
const lines = getItems({
|
||||
class: paper.Path
|
||||
});
|
||||
// Prefer more recent lines
|
||||
|
|
Loading…
Reference in a new issue