├── .dockerignore
├── .github
└── FUNDING.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── classes
├── Graph.js
└── nodes
│ ├── Connection.js
│ ├── Input.js
│ ├── InputColor.js
│ ├── InputColorState.js
│ ├── InputImage.js
│ ├── InputImageState.js
│ ├── InputNumber.js
│ ├── InputString.js
│ ├── Node.js
│ ├── NodeColor.js
│ ├── NodeImage.js
│ ├── NodeNumber.js
│ ├── NodeString.js
│ ├── Output.js
│ ├── OutputColor.js
│ ├── OutputImage.js
│ ├── OutputNumber.js
│ ├── OutputString.js
│ ├── Properties.js
│ ├── adjustment
│ ├── Blur.js
│ ├── BlurProperties.jsx
│ ├── BrightnessContrast.js
│ ├── BrightnessContrastProperties.jsx
│ ├── Dither.js
│ ├── DitherProperties.jsx
│ ├── GaussianBlur.js
│ ├── GaussianBlurProperties.jsx
│ ├── Greyscale.js
│ ├── GreyscaleProperties.jsx
│ ├── HSL.js
│ ├── HSLProperties.jsx
│ ├── Invert.js
│ ├── InvertProperties.jsx
│ ├── Levels.js
│ ├── LevelsProperties.jsx
│ ├── Normalize.js
│ ├── NormalizeProperties.jsx
│ ├── OutputLevels.js
│ └── OutputLevelsProperties.jsx
│ ├── alpha
│ ├── Fade.js
│ ├── FadeProperties.jsx
│ ├── Mask.js
│ ├── MaskProperties.jsx
│ ├── Opacity.js
│ ├── OpacityProperties.jsx
│ ├── Opaque.js
│ └── OpaqueProperties.jsx
│ ├── channel
│ ├── ChannelMerge.js
│ ├── ChannelMergeProperties.jsx
│ ├── ChannelSplit.js
│ └── ChannelSplitProperties.jsx
│ ├── color
│ ├── AnalogousColors.js
│ ├── AnalogousColorsProperties.jsx
│ ├── ColorAdjust.js
│ ├── ColorAdjustProperties.jsx
│ ├── ColorInput.js
│ ├── ColorInputProperties.jsx
│ ├── ComplimentColor.js
│ ├── ComplimentColorProperties.jsx
│ ├── GetAlpha.js
│ ├── GetAlphaProperties.jsx
│ ├── GetBrightness.js
│ ├── GetBrightnessProperties.jsx
│ ├── GetLuminance.js
│ ├── GetLuminanceProperties.jsx
│ ├── HSLInput.js
│ ├── HSLInputProperties.jsx
│ ├── HSVInput.js
│ ├── HSVInputProperties.jsx
│ ├── MixColors.js
│ ├── MixColorsProperties.jsx
│ ├── MonochromaticColors.js
│ ├── MonochromaticColorsProperties.jsx
│ ├── RGBInput.js
│ ├── RGBProperties.jsx
│ ├── Sample.js
│ ├── SampleProperties.jsx
│ ├── SplitComplimentColors.js
│ ├── SplitComplimentColorsProperties.jsx
│ ├── TetradColors.js
│ ├── TetradColorsProperties.jsx
│ ├── TriadColors.js
│ └── TriadColorsProperties.jsx
│ ├── composing
│ ├── Blend.js
│ ├── BlendProperties.jsx
│ ├── Blit.js
│ └── BlitProperties.jsx
│ ├── control
│ ├── Counter.js
│ ├── CounterProperties.jsx
│ ├── Else.js
│ ├── ElseColor.js
│ ├── ElseColorProperties.jsx
│ ├── ElseNumber.js
│ ├── ElseNumberProperties.jsx
│ ├── ElseProperties.jsx
│ ├── ElseString.js
│ ├── ElseStringProperties.jsx
│ ├── IfColor.js
│ ├── IfColorProperties.jsx
│ ├── IfImage.js
│ ├── IfImageProperties.jsx
│ ├── IfNumber.js
│ ├── IfNumberProperties.jsx
│ ├── IfString.js
│ ├── IfStringProperties.jsx
│ ├── Loop.js
│ ├── LoopInputImageLoopOutput.js
│ ├── LoopInputNumberNumLoops.js
│ ├── LoopOutputImageLoopInput.js
│ └── LoopProperties.jsx
│ ├── filter
│ ├── AmbientOcclusion.js
│ ├── AmbientOcclusionProperties.jsx
│ ├── NormalMap.js
│ ├── NormalMapProperties.jsx
│ ├── Pixelate.js
│ ├── PixelateProperties.jsx
│ ├── Posterize.js
│ ├── PosterizeProperties.jsx
│ ├── Sepia.js
│ ├── SepiaProperties.jsx
│ ├── Sobel.js
│ ├── SobelProperties.jsx
│ ├── StainedGlass.js
│ └── StainedGlassProperties.jsx
│ ├── image
│ ├── Circle.js
│ ├── CircleProperties.jsx
│ ├── Faultline.js
│ ├── FaultlineProperties.jsx
│ ├── Gradient.js
│ ├── GradientProperties.jsx
│ ├── ImageUpload.js
│ ├── ImageUploadProperties.jsx
│ ├── Line.js
│ ├── LineProperties.jsx
│ ├── PasteImage.js
│ ├── PasteImageProperties.jsx
│ ├── Simplex.js
│ ├── SimplexProperties.jsx
│ ├── Text.js
│ ├── TextProperties.jsx
│ ├── Triangle.js
│ ├── TriangleProperties.jsx
│ ├── UniformColor.js
│ ├── UniformColorProperties.jsx
│ ├── UrlImage.js
│ ├── UrlImageProperties.jsx
│ ├── Worley.js
│ └── WorleyProperties.jsx
│ ├── number
│ ├── AbsoluteValue.js
│ ├── AbsoluteValueProperties.jsx
│ ├── AddNumbers.js
│ ├── AddNumbersProperties.jsx
│ ├── Atan2.js
│ ├── Atan2Properties.jsx
│ ├── Ceil.js
│ ├── CeilProperties.jsx
│ ├── Cos.js
│ ├── CosProperties.jsx
│ ├── DegreesToRadians.js
│ ├── DegreesToRadiansProperties.jsx
│ ├── DivideNumbers.js
│ ├── DivideNumbersProperties.jsx
│ ├── ExponentNumbers.js
│ ├── ExponentNumbersProperties.jsx
│ ├── Floor.js
│ ├── FloorProperties.jsx
│ ├── GetImageSize.js
│ ├── GetImageSizeProperties.jsx
│ ├── Max.js
│ ├── MaxProperties.jsx
│ ├── Min.js
│ ├── MinProperties.jsx
│ ├── ModuloNumbers.js
│ ├── ModuloNumbersProperties.jsx
│ ├── MultiplyNumbers.js
│ ├── MultiplyNumbersProperties.jsx
│ ├── Number.js
│ ├── NumberProperties.jsx
│ ├── Pi.js
│ ├── PiProperties.jsx
│ ├── RadiansToDegrees.js
│ ├── RadiansToDegreesProperties.jsx
│ ├── RandomNumber.js
│ ├── RandomNumberProperties.jsx
│ ├── Round.js
│ ├── RoundProperties.jsx
│ ├── Sin.js
│ ├── SinProperties.jsx
│ ├── Slider.js
│ ├── SliderProperties.jsx
│ ├── SquareRoot.js
│ ├── SquareRootProperties.jsx
│ ├── SubtractNumbers.js
│ └── SubtractNumbersProperties.jsx
│ ├── outputs
│ ├── Output.js
│ └── OutputProperties.jsx
│ ├── strings
│ ├── Length.js
│ ├── LengthProperties.jsx
│ ├── NumberToString.js
│ ├── NumberToStringProperties.jsx
│ ├── StringInput.js
│ └── StringInputProperties.jsx
│ └── transform
│ ├── Crop.js
│ ├── CropProperties.jsx
│ ├── Displace.js
│ ├── DisplaceProperties.jsx
│ ├── FlipHorizontal.js
│ ├── FlipHorizontalProperties.jsx
│ ├── FlipVertical.js
│ ├── FlipVerticalProperties.jsx
│ ├── Resize.js
│ ├── ResizeProperties.jsx
│ ├── Rotate.js
│ └── RotateProperties.jsx
├── components
├── GraphProperties.jsx
├── GraphThumbs.jsx
├── GraphView.jsx
├── JsonView.jsx
├── PropertiesInputNumber.jsx
├── PropertiesInputSlider.jsx
└── TopBar.jsx
├── deploy.bat
├── deploy.sh
├── layouts
└── MainLayout.js
├── lib
├── functions.js
└── settings.js
├── next.config.js
├── package-lock.json
├── package.json
├── pages
├── createaccount.jsx
├── g
│ ├── [graphId].js
│ └── [graphId]
│ │ └── [slug].js
├── graphs.jsx
├── index.js
├── json
│ ├── [graphId].js
│ └── [graphId]
│ │ └── [slug].js
├── login.jsx
├── logout.jsx
└── u
│ └── [userId].js
├── public
└── static
│ ├── discordIcon.png
│ ├── discordIcon_highres.png
│ ├── emailIcon.png
│ ├── emailIcon_highres.png
│ ├── favicon.png
│ ├── fonts
│ └── open-sans
│ │ ├── open-sans-10-black
│ │ ├── open-sans-10-black.fnt
│ │ └── open-sans-10-black.png
│ │ ├── open-sans-12-black
│ │ ├── open-sans-12-black.fnt
│ │ └── open-sans-12-black.png
│ │ ├── open-sans-128-black
│ │ ├── open-sans-128-black.fnt
│ │ └── open-sans-128-black.png
│ │ ├── open-sans-128-white
│ │ ├── open-sans-128-white.fnt
│ │ └── open-sans-128-white.png
│ │ ├── open-sans-14-black
│ │ ├── open-sans-14-black.fnt
│ │ └── open-sans-14-black.png
│ │ ├── open-sans-16-black
│ │ ├── open-sans-16-black.fnt
│ │ └── open-sans-16-black.png
│ │ ├── open-sans-16-white
│ │ ├── open-sans-16-white.fnt
│ │ └── open-sans-16-white.png
│ │ ├── open-sans-32-black
│ │ ├── open-sans-32-black.fnt
│ │ └── open-sans-32-black.png
│ │ ├── open-sans-32-white
│ │ ├── open-sans-32-white.fnt
│ │ └── open-sans-32-white.png
│ │ ├── open-sans-64-black
│ │ ├── open-sans-64-black.fnt
│ │ └── open-sans-64-black.png
│ │ ├── open-sans-64-white
│ │ ├── open-sans-64-white.fnt
│ │ └── open-sans-64-white.png
│ │ ├── open-sans-8-black
│ │ ├── open-sans-8-black.fnt
│ │ └── open-sans-8-black.png
│ │ └── open-sans-8-white
│ │ ├── open-sans-8-white.fnt
│ │ └── open-sans-8-white.png
│ ├── githubLogo.png
│ ├── githubLogo_highres.png
│ ├── og.jpg
│ ├── patreonIcon.png
│ ├── patreonIcon_highres.png
│ ├── screenshots
│ ├── screenshot01.JPG
│ ├── screenshot02.JPG
│ └── screenshot03.JPG
│ ├── trelloIcon.png
│ ├── trelloIcon_highres.png
│ ├── twitterIcon.png
│ ├── twitterIcon_highres.png
│ └── viewportBg.jpg
└── server
├── api
├── createaccount.js
├── deletegraph.js
├── graph.js
├── graphs.js
├── login.js
├── logout.js
└── savegraph.js
├── functions.js
└── index.js
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | .next
4 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: dan335
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .next/
2 | node_modules/
3 | /npm-debug.log
4 | .env
5 | .DS_Store
6 | /.env.production
7 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:18-alpine
2 |
3 | RUN apk add --no-cache make gcc g++ python3 build-base
4 |
5 | ENV PORT=80 TERM=xterm
6 |
7 | RUN mkdir -p /usr/src/app
8 | WORKDIR /usr/src/app
9 |
10 | COPY package.json /usr/src/app/
11 | RUN npm install --production
12 |
13 | COPY . /usr/src/app
14 |
15 | RUN npm run build
16 | EXPOSE 80
17 |
18 | CMD [ "npm", "start" ]
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Daniel Phillips
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NIMP
2 |
3 | https://nimp.app
4 |
5 | Node-Based Image Manipulation Program
6 |
7 | 
8 |
9 | ### Run
10 | ```
11 | start Mongodb
12 | git clone https://github.com/dan335/nimp
13 | cd nimp
14 | npm install
15 | npm run dev
16 | View in browser at http://localhost:3000
17 | ```
18 |
19 | * See the License file for license rights and limitations (MIT).
20 | * Pull requests are welcome.
21 |
--------------------------------------------------------------------------------
/classes/nodes/InputColor.js:
--------------------------------------------------------------------------------
1 | import Input from './Input.js';
2 |
3 |
4 | export default class InputColor extends Input {
5 | constructor(node, index, name) {
6 | super(node, index, name, 'Color');
7 | this.color = null;
8 | }
9 |
10 | connectionMade() {
11 | if (this.node.bg.classList.contains('selected')) {
12 | this.node.propertiesComponentInstance.setState({hasColorInput:true});
13 | }
14 | }
15 |
16 |
17 | connectionRemoved() {
18 | if (this.node.bg.classList.contains('selected')) {
19 | this.node.propertiesComponentInstance.setState({hasColorInput:false});
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/classes/nodes/InputColorState.js:
--------------------------------------------------------------------------------
1 | // need to eventually merge InputNumber with this and update all nodes to use this
2 |
3 |
4 | import InputColor from './InputColor.js';
5 |
6 |
7 | export default class InputColorState extends InputColor {
8 | constructor(node, index, name, stateVariableName) {
9 | super(node, index, name);
10 | this.stateVariableName = stateVariableName;
11 | }
12 |
13 |
14 | connectionMade() {
15 | if (this.node.bg.classList.contains('selected')) {
16 | const t = {};
17 | t[this.stateVariableName] = true;
18 | this.node.propertiesComponentInstance.setState(t);
19 | }
20 | }
21 |
22 |
23 | connectionRemoved() {
24 | if (this.node.bg.classList.contains('selected')) {
25 | const t = {};
26 | t[this.stateVariableName] = false;
27 | this.node.propertiesComponentInstance.setState(t);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/classes/nodes/InputImage.js:
--------------------------------------------------------------------------------
1 | import Input from './Input.js';
2 |
3 |
4 | export default class InputImage extends Input {
5 | constructor(node, index, name) {
6 | super(node, index, name, 'Image');
7 | this.image = null;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/classes/nodes/InputImageState.js:
--------------------------------------------------------------------------------
1 | // need to eventually merge InputNumber with this and update all nodes to use this
2 |
3 |
4 | import InputImage from './InputImage.js';
5 |
6 |
7 | export default class InputImageState extends InputImage {
8 | constructor(node, index, name, stateVariableName) {
9 | super(node, index, name);
10 | this.stateVariableName = stateVariableName;
11 | }
12 |
13 |
14 | connectionMade() {
15 | if (this.node.bg.classList.contains('selected')) {
16 | const t = {};
17 | t[this.stateVariableName] = true;
18 | this.node.propertiesComponentInstance.setState(t);
19 | }
20 | }
21 |
22 |
23 | connectionRemoved() {
24 | if (this.node.bg.classList.contains('selected')) {
25 | const t = {};
26 | t[this.stateVariableName] = false;
27 | this.node.propertiesComponentInstance.setState(t);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/classes/nodes/InputNumber.js:
--------------------------------------------------------------------------------
1 | import Input from './Input.js';
2 |
3 |
4 | export default class InputNumber extends Input {
5 | constructor(node, index, name, stateVariableName) {
6 | super(node, index, name, 'Number');
7 | this.number = null;
8 | this.stateVariableName = stateVariableName;
9 | }
10 |
11 | connectionMade() {
12 | if (this.node.bg.classList.contains('selected')) {
13 | const t = {};
14 | t[this.stateVariableName] = true;
15 | this.node.propertiesComponentInstance.setState(t);
16 | }
17 | }
18 |
19 |
20 | connectionRemoved() {
21 | if (this.node.bg.classList.contains('selected')) {
22 | const t = {};
23 | t[this.stateVariableName] = false;
24 | this.node.propertiesComponentInstance.setState(t);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/classes/nodes/InputString.js:
--------------------------------------------------------------------------------
1 | import Input from './Input.js';
2 |
3 |
4 | export default class InputString extends Input {
5 | constructor(node, index, name, stateVariableName) {
6 | super(node, index, name, 'String');
7 | this.string = null;
8 | this.stateVariableName = stateVariableName;
9 | }
10 |
11 |
12 | connectionMade() {
13 | if (this.node.bg.classList.contains('selected')) {
14 | const t = {};
15 | t[this.stateVariableName] = true;
16 | this.node.propertiesComponentInstance.setState(t);
17 | }
18 | }
19 |
20 |
21 | connectionRemoved() {
22 | if (this.node.bg.classList.contains('selected')) {
23 | const t = {};
24 | t[this.stateVariableName] = false;
25 | this.node.propertiesComponentInstance.setState(t);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/classes/nodes/NodeColor.js:
--------------------------------------------------------------------------------
1 | import Node from './Node.js';
2 | const tinycolor = require("tinycolor2");
3 | var debounce = require('lodash.debounce');
4 |
5 |
6 | export default class NodeColor extends Node {
7 | constructor(className, graph, x, y, name, propertiesComponent, settings) {
8 | super(className, graph, x, y, name, propertiesComponent, settings);
9 |
10 | this.color = tinycolor('#fff');
11 |
12 | this.debouncedRenderPreview = debounce(this.renderPreview, 300);
13 | this.renderName();
14 | }
15 |
16 |
17 | view() {
18 | // do nothing
19 | }
20 |
21 | deView() {
22 | // do nothing
23 | }
24 |
25 |
26 | passToChildren() {
27 | this.outputs.forEach(output => {
28 | output.connections.forEach(conn => {
29 | if (this.color == null) {
30 | conn.color = null;
31 | } else {
32 | conn.color = this.color;
33 | }
34 | conn.runNode();
35 | })
36 | })
37 | }
38 |
39 |
40 | run(inputThatTriggered) {
41 | this.timer.textContent = (Date.now() - this.runTimer) + 'ms';
42 | this.bg.classList.remove('running');
43 | this.passToChildren();
44 |
45 | if (this.color) {
46 | this.debouncedRenderPreview();
47 | } else {
48 | this.preview.setAttributeNS(null, 'href', '');
49 | }
50 | }
51 |
52 |
53 | renderPreview() {
54 | new Jimp(1, 1, this.color.toHex8(), (error, image) => {
55 | if (error) {
56 | console.log(error);
57 | } else {
58 | image.getBufferAsync(Jimp.MIME_PNG).then(i => {
59 | this.preview.setAttributeNS(null, 'href', 'data:'+Jimp.MIME_PNG+';base64,'+i.toString('base64'));
60 | });
61 | }
62 | })
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/classes/nodes/NodeNumber.js:
--------------------------------------------------------------------------------
1 | import Node from './Node.js';
2 |
3 |
4 | export default class NodeNumber extends Node {
5 | constructor(className, graph, x, y, name, propertiesComponent, settings) {
6 | super(className, graph, x, y, name, propertiesComponent, settings);
7 |
8 | this.number = 1;
9 |
10 | this.textPreview.style.display = 'block';
11 | this.renderName();
12 | }
13 |
14 |
15 | view() {
16 | // do nothing
17 | }
18 |
19 | deView() {
20 | // do nothing
21 | }
22 |
23 |
24 | passToChildren() {
25 | this.outputs.forEach(output => {
26 | output.connections.forEach(conn => {
27 | if (this.number == null || isNaN(this.number)) {
28 | conn.number = null;
29 | } else {
30 | conn.number = this.number;
31 | }
32 | conn.runNode();
33 | })
34 | })
35 | }
36 |
37 |
38 | run(inputThatTriggered) {
39 | this.timer.textContent = (Date.now() - this.runTimer) + 'ms';
40 | this.bg.classList.remove('running');
41 | this.passToChildren();
42 | this.renderPreview();
43 | }
44 |
45 |
46 | renderPreview() {
47 | if (this.number != null) {
48 | this.textPreview.textContent = this.number;
49 | } else {
50 | this.textPreview.textContent = '';
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/classes/nodes/NodeString.js:
--------------------------------------------------------------------------------
1 | import Node from './Node.js';
2 |
3 |
4 | export default class NodeString extends Node {
5 | constructor(className, graph, x, y, name, propertiesComponent, settings) {
6 | super(className, graph, x, y, name, propertiesComponent, settings);
7 |
8 | this.string = 'Nimp';
9 |
10 | this.textPreview.style.display = 'block';
11 | this.renderName();
12 | }
13 |
14 |
15 | view() {
16 | // do nothing
17 | }
18 |
19 | deView() {
20 | // do nothing
21 | }
22 |
23 |
24 | passToChildren() {
25 | this.outputs.forEach(output => {
26 | output.connections.forEach(conn => {
27 | if (this.string == null) {
28 | conn.string = null;
29 | } else {
30 | conn.string = this.string;
31 | }
32 | conn.runNode();
33 | })
34 | })
35 | }
36 |
37 |
38 | run(inputThatTriggered) {
39 | this.timer.textContent = (Date.now() - this.runTimer) + 'ms';
40 | this.bg.classList.remove('running');
41 | this.passToChildren();
42 | this.renderPreview();
43 | }
44 |
45 |
46 | renderPreview() {
47 | if (this.string != null) {
48 | this.textPreview.textContent = this.string;
49 | } else {
50 | this.textPreview.textContent = '';
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/classes/nodes/OutputColor.js:
--------------------------------------------------------------------------------
1 | import Output from './Output.js';
2 |
3 |
4 | export default class OutputColor extends Output {
5 | constructor(node, index, name) {
6 | super(node, index, name, 'Color');
7 | }
8 |
9 |
10 | removeConnection(inputConnection, run) {
11 | inputConnection.color = null;
12 | super.removeConnection(inputConnection, run);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/classes/nodes/OutputImage.js:
--------------------------------------------------------------------------------
1 | import Output from './Output.js';
2 |
3 |
4 | export default class OutputImage extends Output {
5 | constructor(node, index, name) {
6 | super(node, index, name, 'Image');
7 | }
8 |
9 |
10 | removeConnection(inputConnection, run) {
11 | inputConnection.image = null;
12 | super.removeConnection(inputConnection, run);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/classes/nodes/OutputNumber.js:
--------------------------------------------------------------------------------
1 | import Output from './Output.js';
2 |
3 |
4 | export default class OutputNumber extends Output {
5 | constructor(node, index, name) {
6 | super(node, index, name, 'Number');
7 | }
8 |
9 |
10 | removeConnection(inputConnection, run) {
11 | inputConnection.number = null;
12 | super.removeConnection(inputConnection, run);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/classes/nodes/OutputString.js:
--------------------------------------------------------------------------------
1 | import Output from './Output.js';
2 |
3 |
4 | export default class OutputString extends Output {
5 | constructor(node, index, name) {
6 | super(node, index, name, 'String');
7 | }
8 |
9 |
10 | removeConnection(inputConnection, run) {
11 | inputConnection.string = null;
12 | super.removeConnection(inputConnection, run);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/classes/nodes/Properties.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class Properties extends React.Component {
4 | constructor(props) {
5 | super(props);
6 |
7 | props.node.propertiesComponentInstance = this;
8 | }
9 |
10 |
11 | colorChange() {
12 | const elm = document.getElementById('colorInput');
13 | this.props.node.hexColor = elm.value;
14 | this.props.node.run(null);
15 | }
16 |
17 |
18 | nameChange() {
19 | const elm = document.getElementById('nameInput');
20 | this.props.node.name = elm.value;
21 | this.props.node.renderName();
22 | }
23 |
24 |
25 | runNode() {
26 | this.props.node.run(null);
27 | }
28 |
29 |
30 | renderRun() {
31 | return (
32 | {this.runNode()}} style={{width:'100%', marginTop:'30px'}}>Run Node
33 | )
34 | }
35 |
36 |
37 | renderName() {
38 | return (
39 |
40 |
41 | Name
42 | {this.nameChange(event);}}/>
43 |
44 | )
45 | }
46 |
47 |
48 | renderColor() {
49 | if (!this.state.hasColorInput) {
50 | return (
51 |
52 | Color
53 | {this.colorChange(event);}} />
54 |
55 | )
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/Blur.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import BlurProperties from './BlurProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 | import InputNumber from '../InputNumber.js';
6 |
7 |
8 | export default class Blur extends NodeImage {
9 | constructor(className, graph, x, y, settings) {
10 | super(className, graph, x, y, 'Blur', BlurProperties, settings);
11 |
12 | this.inputs = [
13 | new InputImage(this, 0, 'Input'),
14 | new InputNumber(this, 1, 'Radius', 'hasRadiusInput')
15 | ];
16 | this.outputs = [
17 | new OutputImage(this, 0, 'Output')
18 | ];
19 |
20 | this.radius = typeof settings.radius !== 'undefined' ? settings.radius : 10;
21 | }
22 |
23 |
24 | run(inputThatTriggered) {
25 | if (this.inputs[0].image) {
26 | this.bg.classList.add('running');
27 | this.runTimer = Date.now();
28 |
29 | let radius = this.radius;
30 |
31 | if (this.inputs[1].number != null) {
32 | radius = this.inputs[1].number;
33 | }
34 |
35 | radius = Math.max(1, radius);
36 |
37 | // blur requires radius to be rounded?
38 | radius = Math.round(radius);
39 |
40 | if (this.isInsideALoop) {
41 | let image = this.inputs[0].image.clone();
42 | image.blur(radius);
43 | this.image = image;
44 | super.run(inputThatTriggered);
45 |
46 | } else {
47 | Jimp.read(this.inputs[0].image).then(image => {
48 | image.blur(radius, (error, image) => {
49 | if (error) {
50 | console.log(error);
51 | } else {
52 | this.image = image;
53 | super.run(inputThatTriggered);
54 | }
55 | });
56 | })
57 | }
58 | } else {
59 | this.runTimer = Date.now();
60 | this.image = null;
61 | super.run(inputThatTriggered);
62 | }
63 | }
64 |
65 |
66 | toJson() {
67 | let json = super.toJson();
68 |
69 | json.settings.radius = this.radius;
70 |
71 | return json;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/BlurProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class BlurProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
Blur
11 |
12 | Fast blur.
13 |
14 |
15 |
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/BrightnessContrastProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputSlider from '../../../components/PropertiesInputSlider.jsx';
3 |
4 | export default class BrightnessContrastProperties extends Properties {
5 |
6 | render() {
7 | return (
8 |
9 |
Brightness/Contrast
10 |
11 |
12 |
13 |
14 | {this.renderRun()}
15 |
16 |
17 | )
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/Dither.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import DitherProperties from './DitherProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 |
6 | export default class Dither extends NodeImage {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Dither', DitherProperties, settings);
9 |
10 | this.inputs = [
11 | new InputImage(this, 0, 'Input')
12 | ];
13 | this.outputs = [
14 | new OutputImage(this, 0, 'Output')
15 | ];
16 | }
17 |
18 |
19 | run(inputThatTriggered) {
20 | if (this.inputs[0].image) {
21 | this.bg.classList.add('running');
22 | this.runTimer = Date.now();
23 |
24 | if (this.isInsideALoop) {
25 | const image = this.inputs[0].image.clone();
26 | image.dither565();
27 | this.image = image;
28 | super.run(inputThatTriggered);
29 | } else {
30 | Jimp.read(this.inputs[0].image).then(image => {
31 | image.dither565((error, image) => {
32 | this.image = image;
33 | super.run(inputThatTriggered);
34 | });
35 | })
36 | }
37 |
38 | } else {
39 | this.runTimer = Date.now();
40 | this.image = null;
41 | super.run(inputThatTriggered);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/DitherProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class DitherProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Dither Image
14 |
15 | Apply a dither effect to an image.
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/GaussianBlurProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class GaussianBlurProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
Gaussian Blur
11 |
12 | Slow but high quality blur.
13 |
14 |
15 |
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/Greyscale.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import GreyscaleProperties from './GreyscaleProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 |
6 | export default class Greyscale extends NodeImage {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Greyscale', GreyscaleProperties, settings);
9 |
10 | this.inputs = [
11 | new InputImage(this, 0, 'Input')
12 | ];
13 | this.outputs = [
14 | new OutputImage(this, 0, 'Output')
15 | ];
16 | }
17 |
18 |
19 | run(inputThatTriggered) {
20 | if (this.inputs[0].image) {
21 | this.bg.classList.add('running');
22 | this.runTimer = Date.now();
23 |
24 | if (this.isInsideALoop) {
25 | const image = this.inputs[0].image.clone();
26 | image.greyscale();
27 | this.image = image;
28 | super.run(inputThatTriggered);
29 | } else {
30 | Jimp.read(this.inputs[0].image).then(image => {
31 | image.greyscale((error, image) => {
32 | this.image = image;
33 | super.run(inputThatTriggered);
34 | });
35 | })
36 | }
37 |
38 | } else {
39 | this.runTimer = Date.now();
40 | this.image = null;
41 | super.run(inputThatTriggered);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/GreyscaleProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class GreyscaleProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Convert to Greyscale
14 |
15 | {this.renderRun()}
16 |
17 |
18 | )
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/HSLProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputSlider from '../../../components/PropertiesInputSlider.jsx';
3 |
4 |
5 | export default class HSLProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
Hue Saturation Lightness
11 |
12 |
13 |
14 |
15 |
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/Invert.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import InvertProperties from './InvertProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 |
6 | export default class Invert extends NodeImage {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Invert', InvertProperties, settings);
9 |
10 | this.inputs = [
11 | new InputImage(this, 0, 'Input')
12 | ];
13 | this.outputs = [
14 | new OutputImage(this, 0, 'Output')
15 | ];
16 | }
17 |
18 |
19 | run(inputThatTriggered) {
20 | if (this.inputs[0].image) {
21 | this.bg.classList.add('running');
22 | this.runTimer = Date.now();
23 |
24 | if (this.isInsideALoop) {
25 | const image = this.inputs[0].image.clone();
26 | image.invert();
27 | this.image = image;
28 | super.run(inputThatTriggered);
29 | } else {
30 | Jimp.read(this.inputs[0].image).then(image => {
31 | image.invert((error, image) => {
32 | this.image = image;
33 | super.run(inputThatTriggered);
34 | });
35 | })
36 | }
37 |
38 | } else {
39 | this.runTimer = Date.now();
40 | this.image = null;
41 | super.run(inputThatTriggered);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/InvertProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class InvertProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Invert Colors
14 |
15 | {this.renderRun()}
16 |
17 |
18 | )
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/LevelsProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputSlider from '../../../components/PropertiesInputSlider.jsx';
3 |
4 | export default class LevelsProperties extends Properties {
5 |
6 | render() {
7 | return (
8 |
9 |
Input Levels
10 |
11 |
12 |
13 |
14 | {this.renderRun()}
15 |
16 |
17 | )
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/Normalize.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import NormalizeProperties from './NormalizeProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 |
6 | export default class Normalize extends NodeImage {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Normalize', NormalizeProperties, settings);
9 |
10 | this.inputs = [
11 | new InputImage(this, 0, 'Input')
12 | ];
13 | this.outputs = [
14 | new OutputImage(this, 0, 'Output')
15 | ];
16 | }
17 |
18 |
19 | run(inputThatTriggered) {
20 | if (this.inputs[0].image) {
21 | this.bg.classList.add('running');
22 | this.runTimer = Date.now();
23 |
24 | if (this.isInsideALoop) {
25 | const image = this.inputs[0].image.clone();
26 | image.normalize();
27 | this.image = image;
28 | super.run(inputThatTriggered);
29 | } else {
30 | Jimp.read(this.inputs[0].image).then(image => {
31 | image.normalize((error, image) => {
32 | this.image = image;
33 | super.run(inputThatTriggered);
34 | });
35 | })
36 | }
37 |
38 | } else {
39 | this.runTimer = Date.now();
40 | this.image = null;
41 | super.run(inputThatTriggered);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/NormalizeProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class NormalizeProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Normalize Image
14 |
15 | Normalizes an images color by computing a histogram.
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/adjustment/OutputLevelsProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputSlider from '../../../components/PropertiesInputSlider.jsx';
3 |
4 | export default class OutputLevelsProperties extends Properties {
5 |
6 | render() {
7 | return (
8 |
9 |
Output Levels
10 |
11 |
12 |
13 | {this.renderRun()}
14 |
15 |
16 | )
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/classes/nodes/alpha/Fade.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import FadeProperties from './FadeProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 | import InputNumber from '../InputNumber.js';
6 |
7 |
8 | export default class Fade extends NodeImage {
9 | constructor(className, graph, x, y, settings) {
10 | super(className, graph, x, y, 'Fade', FadeProperties, settings);
11 |
12 | this.inputs = [
13 | new InputImage(this, 0, 'Input'),
14 | new InputNumber(this, 1, 'Amount', 'hasAmountInput')
15 | ];
16 | this.outputs = [
17 | new OutputImage(this, 0, 'Output')
18 | ];
19 |
20 | this.amount = typeof settings.amount !== 'undefined' ? settings.amount : 0.5;
21 | }
22 |
23 |
24 | run(inputThatTriggered) {
25 | if (this.inputs[0].image) {
26 | this.bg.classList.add('running');
27 | this.runTimer = Date.now();
28 |
29 | let amount = this.amount;
30 |
31 | if (this.inputs[1].number != null) {
32 | amount = this.inputs[1].number;
33 | }
34 |
35 | amount = Math.min(1, Math.max(0, amount));
36 |
37 | if (this.isInsideALoop) {
38 | let image = this.inputs[0].image.clone();
39 | image.fade(amount);
40 | this.image = image;
41 | super.run(inputThatTriggered);
42 |
43 | } else {
44 | Jimp.read(this.inputs[0].image).then(image => {
45 | image.fade(amount, (error, image) => {
46 | if (error) {
47 | console.log(error);
48 | } else {
49 | this.image = image;
50 | super.run(inputThatTriggered);
51 | }
52 | });
53 | })
54 | }
55 | } else {
56 | this.runTimer = Date.now();
57 | this.image = null;
58 | super.run(inputThatTriggered);
59 | }
60 | }
61 |
62 |
63 | toJson() {
64 | let json = super.toJson();
65 |
66 | json.settings.amount = this.amount;
67 |
68 | return json;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/classes/nodes/alpha/FadeProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputSlider from '../../../components/PropertiesInputSlider.jsx';
3 |
4 | export default class FadeProperties extends Properties {
5 |
6 | render() {
7 | return (
8 |
9 |
Fade
10 |
11 |
12 | {this.renderRun()}
13 |
14 |
15 | )
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/classes/nodes/alpha/MaskProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 | export default class MaskProperties extends Properties {
5 |
6 | render() {
7 | return (
8 |
9 |
Mask
10 |
11 | Position of image.
12 |
13 |
14 | {this.renderRun()}
15 |
16 |
17 | )
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/classes/nodes/alpha/Opacity.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import OpacityProperties from './OpacityProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 | import InputNumber from '../InputNumber.js';
6 |
7 |
8 | export default class Opacity extends NodeImage {
9 | constructor(className, graph, x, y, settings) {
10 | super(className, graph, x, y, 'Opacity', OpacityProperties, settings);
11 |
12 | this.inputs = [
13 | new InputImage(this, 0, 'Input'),
14 | new InputNumber(this, 1, 'Amount', 'hasAmountInput')
15 | ];
16 | this.outputs = [
17 | new OutputImage(this, 0, 'Output')
18 | ];
19 |
20 | this.amount = typeof settings.amount !== 'undefined' ? settings.amount : 0.5;
21 | }
22 |
23 |
24 | run(inputThatTriggered) {
25 | if (this.inputs[0].image) {
26 | this.bg.classList.add('running');
27 | this.runTimer = Date.now();
28 |
29 | let amount = this.amount;
30 |
31 | if (this.inputs[1].number != null) {
32 | amount = this.inputs[1].number;
33 | }
34 |
35 | amount = Math.min(1, Math.max(0, amount));
36 |
37 | if (this.isInsideALoop) {
38 | let image = this.inputs[0].image.clone();
39 | image.opacity(amount);
40 | this.image = image;
41 | super.run(inputThatTriggered);
42 |
43 | } else {
44 | Jimp.read(this.inputs[0].image).then(image => {
45 | image.opacity(amount, (error, image) => {
46 | if (error) {
47 | console.log(error);
48 | } else {
49 | this.image = image;
50 | super.run(inputThatTriggered);
51 | }
52 | });
53 | })
54 | }
55 | } else {
56 | this.runTimer = Date.now();
57 | this.image = null;
58 | super.run(inputThatTriggered);
59 | }
60 | }
61 |
62 |
63 | toJson() {
64 | let json = super.toJson();
65 |
66 | json.settings.amount = this.amount;
67 |
68 | return json;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/classes/nodes/alpha/OpacityProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputSlider from '../../../components/PropertiesInputSlider.jsx';
3 |
4 | export default class OpacityProperties extends Properties {
5 |
6 | render() {
7 | return (
8 |
9 |
Opacity
10 |
11 | Multiply the alpha channel by an amount.
12 |
13 |
14 | {this.renderRun()}
15 |
16 |
17 | )
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/classes/nodes/alpha/Opaque.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import OpaqueProperties from './OpaqueProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 |
6 | export default class Opaque extends NodeImage {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Opaque', OpaqueProperties, settings);
9 |
10 | this.inputs = [
11 | new InputImage(this, 0, 'Input')
12 | ];
13 | this.outputs = [
14 | new OutputImage(this, 0, 'Output')
15 | ];
16 | }
17 |
18 |
19 | run(inputThatTriggered) {
20 | if (this.inputs[0].image) {
21 | this.bg.classList.add('running');
22 | this.runTimer = Date.now();
23 |
24 | if (this.isInsideALoop) {
25 | const image = this.inputs[0].image.clone();
26 | image.opaque();
27 | this.image = image;
28 | super.run(inputThatTriggered);
29 | } else {
30 | Jimp.read(this.inputs[0].image).then(image => {
31 | image.opaque((error, image) => {
32 | if (error) {
33 | console.log(error);
34 | } else {
35 | this.image = image;
36 | super.run(inputThatTriggered);
37 | }
38 | });
39 | })
40 | }
41 |
42 | } else {
43 | this.runTimer = Date.now();
44 | this.image = null;
45 | super.run(inputThatTriggered);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/classes/nodes/alpha/OpaqueProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class OpaqueProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Opaque
14 |
15 | Set the alpha channel of every pixel to be opaque.
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/channel/ChannelMergeProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class ChannelMergeProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 |
11 | render() {
12 | return (
13 |
14 |
Channel Merge
15 |
16 |
17 | {this.renderRun()}
18 |
19 |
20 | )
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/classes/nodes/channel/ChannelSplitProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class ChannelSplitProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 |
11 | render() {
12 | return (
13 |
14 |
Channel Split
15 |
16 |
17 | {this.renderRun()}
18 |
19 |
20 | )
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/classes/nodes/color/AnalogousColorsProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class GetAlphaProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | stringChange(event) {
11 | const elm = document.getElementById('stringInput');
12 | this.props.node.string = elm.value;
13 | this.props.node.run(null);
14 | }
15 |
16 |
17 | render() {
18 | return (
19 |
20 |
Analogous Colors
21 |
22 |
23 | {this.renderName()}
24 | {this.renderRun()}
25 |
26 |
27 | )
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/classes/nodes/color/ColorAdjustProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputSlider from '../../../components/PropertiesInputSlider.jsx';
3 |
4 |
5 | export default class ColorAdjustProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
Color Adjust
11 |
12 |
13 |
14 |
15 |
16 |
17 | {this.renderName()}
18 | {this.renderRun()}
19 |
20 |
21 | )
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/classes/nodes/color/ColorInput.js:
--------------------------------------------------------------------------------
1 | import NodeColor from '../NodeColor.js';
2 | import ColorInputProperties from './ColorInputProperties.jsx';
3 | import OutputColor from '../OutputColor.js';
4 | const tinycolor = require("tinycolor2");
5 |
6 |
7 | export default class ColorInput extends NodeColor {
8 | constructor(className, graph, x, y, settings) {
9 | super(className, graph, x, y, 'Color Input', ColorInputProperties, settings);
10 |
11 | this.inputs = [];
12 | this.outputs = [
13 | new OutputColor(this, 0, 'Output')
14 | ];
15 |
16 | this.string = typeof settings.hue !== 'undefined' ? settings.hue : '#fff';
17 | }
18 |
19 |
20 | toJson() {
21 | let json = super.toJson();
22 |
23 | json.settings.string = this.string;
24 |
25 | return json;
26 | }
27 |
28 |
29 | run(inputThatTriggered) {
30 | this.bg.classList.add('running');
31 | this.runTimer = Date.now();
32 |
33 | // hue = Math.min(255, Math.max(0, hue));
34 | // saturation = Math.min(255, Math.max(0, saturation));
35 | // value = Math.min(255, Math.max(0, value));
36 | // alpha = Math.min(255, Math.max(0, alpha));
37 |
38 | this.color = tinycolor(this.string);
39 |
40 | super.run(inputThatTriggered);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/classes/nodes/color/ColorInputProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class ColorInputProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | stringChange(event) {
11 | const elm = document.getElementById('stringInput');
12 | this.props.node.string = elm.value;
13 | this.props.node.run(null);
14 | }
15 |
16 |
17 | render() {
18 | return (
19 |
20 |
HSV Input
21 |
22 |
23 | Color
24 |
{this.stringChange(event)}} />
25 |
26 | Examples of Possible Values
27 |
28 | #fff or #ffffff
29 | rgb (255, 0, 0)
30 | hsl(0, 100%, 50%)
31 | hsv 0 1 1
32 | red
33 |
34 |
35 | See
Tinycolor for all options.
36 | {this.renderName()}
37 | {this.renderRun()}
38 |
39 |
40 | )
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/classes/nodes/color/ComplimentColor.js:
--------------------------------------------------------------------------------
1 | import NodeColor from '../NodeColor.js';
2 | import ComplimentColorProperties from './ComplimentColorProperties.jsx';
3 | import OutputColor from '../OutputColor.js';
4 | const tinycolor = require("tinycolor2");
5 | import InputColor from '../InputColor.js';
6 |
7 |
8 | export default class ComplimentColor extends NodeColor {
9 | constructor(className, graph, x, y, settings) {
10 | super(className, graph, x, y, 'Compliment Color', ComplimentColorProperties, settings);
11 |
12 | this.inputs = [
13 | new InputColor(this, 0, 'Input'),
14 | ];
15 | this.outputs = [
16 | new OutputColor(this, 0, 'Compliment 1'),
17 | ];
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | return json;
25 | }
26 |
27 |
28 | run(inputThatTriggered) {
29 | this.bg.classList.add('running');
30 | this.runTimer = Date.now();
31 |
32 | if (this.inputs[0].color) {
33 | this.color = this.inputs[0].color.clone().complement();
34 |
35 | } else {
36 | this.color = tinycolor('#000');
37 | }
38 |
39 | super.run(inputThatTriggered);
40 | }
41 |
42 |
43 | renderPreview() {
44 | new Jimp(1, 1, this.color.toHex8String(), (error, image) => {
45 | if (error) {
46 | console.log(error);
47 | } else {
48 | image.getBufferAsync(Jimp.MIME_JPEG).then(i => {
49 | this.preview.setAttributeNS(null, 'href', 'data:'+Jimp.MIME_JPEG+';base64,'+i.toString('base64'));
50 | });
51 | }
52 | })
53 | }
54 |
55 |
56 | passToChildren() {
57 | this.outputs[0].connections.forEach(conn => {
58 | conn.color = this.color;
59 | conn.runNode();
60 | })
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/classes/nodes/color/ComplimentColorProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class ComplimentColorProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | stringChange(event) {
11 | const elm = document.getElementById('stringInput');
12 | this.props.node.string = elm.value;
13 | this.props.node.run(null);
14 | }
15 |
16 |
17 | render() {
18 | return (
19 |
20 |
Compliment Color
21 |
22 |
23 | {this.renderName()}
24 | {this.renderRun()}
25 |
26 |
27 | )
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/classes/nodes/color/GetAlpha.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import GetAlphaProperties from './GetAlphaProperties.jsx';
3 | import OutputNumber from '../OutputNumber.js';
4 | const tinycolor = require("tinycolor2");
5 | import InputColor from '../InputColor.js';
6 |
7 |
8 | export default class GetAlpha extends NodeNumber {
9 | constructor(className, graph, x, y, settings) {
10 | super(className, graph, x, y, 'Get Alpha', GetAlphaProperties, settings);
11 |
12 | this.inputs = [
13 | new InputColor(this, 0, 'Input')
14 | ];
15 | this.outputs = [
16 | new OutputNumber(this, 0, 'Alpha')
17 | ];
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | return json;
25 | }
26 |
27 |
28 | run(inputThatTriggered) {
29 | this.bg.classList.add('running');
30 | this.runTimer = Date.now();
31 |
32 | if (this.inputs[0].color) {
33 |
34 | this.number = this.inputs[0].color.clone().getAlpha();
35 |
36 | } else {
37 |
38 | this.color = null
39 | }
40 |
41 | super.run(inputThatTriggered);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/classes/nodes/color/GetAlphaProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class GetAlphaProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | stringChange(event) {
11 | const elm = document.getElementById('stringInput');
12 | this.props.node.string = elm.value;
13 | this.props.node.run(null);
14 | }
15 |
16 |
17 | render() {
18 | return (
19 |
20 |
Alpha Value From Color
21 |
22 |
23 | 0 - 1
24 | {this.renderName()}
25 | {this.renderRun()}
26 |
27 |
28 | )
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/classes/nodes/color/GetBrightness.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import GetBrightnessProperties from './GetBrightnessProperties.jsx';
3 | import OutputNumber from '../OutputNumber.js';
4 | const tinycolor = require("tinycolor2");
5 | import InputColor from '../InputColor.js';
6 |
7 |
8 | export default class GetBrightness extends NodeNumber {
9 | constructor(className, graph, x, y, settings) {
10 | super(className, graph, x, y, 'Get Brightness', GetBrightnessProperties, settings);
11 |
12 | this.inputs = [
13 | new InputColor(this, 0, 'Input')
14 | ];
15 | this.outputs = [
16 | new OutputNumber(this, 0, 'Brightness')
17 | ];
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | return json;
25 | }
26 |
27 |
28 | run(inputThatTriggered) {
29 | this.bg.classList.add('running');
30 | this.runTimer = Date.now();
31 |
32 | if (this.inputs[0].color) {
33 |
34 | this.number = this.inputs[0].color.clone().getBrightness();
35 |
36 | } else {
37 |
38 | this.color = null
39 | }
40 |
41 | super.run(inputThatTriggered);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/classes/nodes/color/GetBrightnessProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class GetBrightnessProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | stringChange(event) {
11 | const elm = document.getElementById('stringInput');
12 | this.props.node.string = elm.value;
13 | this.props.node.run(null);
14 | }
15 |
16 |
17 | render() {
18 | return (
19 |
20 |
Brightness From Color
21 |
22 |
23 | 0 - 255
24 | {this.renderName()}
25 | {this.renderRun()}
26 |
27 |
28 | )
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/classes/nodes/color/GetLuminance.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import GetLuminanceProperties from './GetLuminanceProperties.jsx';
3 | import OutputNumber from '../OutputNumber.js';
4 | const tinycolor = require("tinycolor2");
5 | import InputColor from '../InputColor.js';
6 |
7 |
8 | export default class GetLuminance extends NodeNumber {
9 | constructor(className, graph, x, y, settings) {
10 | super(className, graph, x, y, 'Get Luminance', GetLuminanceProperties, settings);
11 |
12 | this.inputs = [
13 | new InputColor(this, 0, 'Input')
14 | ];
15 | this.outputs = [
16 | new OutputNumber(this, 0, 'Luminance')
17 | ];
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | return json;
25 | }
26 |
27 |
28 | run(inputThatTriggered) {
29 | this.bg.classList.add('running');
30 | this.runTimer = Date.now();
31 |
32 | if (this.inputs[0].color) {
33 |
34 | this.number = this.inputs[0].color.clone().getLuminance();
35 |
36 | } else {
37 |
38 | this.color = null
39 | }
40 |
41 | super.run(inputThatTriggered);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/classes/nodes/color/GetLuminanceProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class GetLuminanceProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | stringChange(event) {
11 | const elm = document.getElementById('stringInput');
12 | this.props.node.string = elm.value;
13 | this.props.node.run(null);
14 | }
15 |
16 |
17 | render() {
18 | return (
19 |
20 |
Luminance From Color
21 |
22 |
23 | 0 - 1
24 | {this.renderName()}
25 | {this.renderRun()}
26 |
27 |
28 | )
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/classes/nodes/color/HSLInputProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputSlider from '../../../components/PropertiesInputSlider.jsx';
3 |
4 |
5 | export default class HSLInputProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
HSL Input
11 |
12 |
13 |
14 |
15 |
16 |
17 | {this.renderName()}
18 | {this.renderRun()}
19 |
20 |
21 | )
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/classes/nodes/color/HSVInputProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputSlider from '../../../components/PropertiesInputSlider.jsx';
3 |
4 |
5 | export default class HSVInputProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
HSV Input
11 |
12 |
13 |
14 |
15 |
16 |
17 | {this.renderName()}
18 | {this.renderRun()}
19 |
20 |
21 | )
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/classes/nodes/color/MixColorsProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputSlider from '../../../components/PropertiesInputSlider.jsx';
3 |
4 | export default class MixColorsProperties extends Properties {
5 |
6 | constructor(props) {
7 | super(props);
8 |
9 | this.state = {
10 | hasColorAInput: props.node.inputs[0].parent ? true : false,
11 | hasColorBInput: props.node.inputs[1].parent ? true : false
12 | }
13 | }
14 |
15 |
16 | colorAChange() {
17 | const elm = document.getElementById('colorAInput');
18 | this.props.node.colorA = elm.value;
19 | this.props.node.run(null);
20 | }
21 |
22 | colorBChange() {
23 | const elm = document.getElementById('colorBInput');
24 | this.props.node.colorB = elm.value;
25 | this.props.node.run(null);
26 | }
27 |
28 |
29 | renderColorA() {
30 | if (!this.state.hasColorAInput) {
31 | return (
32 |
33 | Color A
34 | {this.colorAChange(event);}} />
35 |
36 | )
37 | }
38 | }
39 |
40 | renderColorB() {
41 | if (!this.state.hasColorBInput) {
42 | return (
43 |
44 | Color B
45 | {this.colorBChange(event);}} />
46 |
47 | )
48 | }
49 | }
50 |
51 |
52 | render() {
53 | return (
54 |
55 |
Mix Colors
56 |
57 |
58 | {this.renderColorA()}
59 | {this.renderColorB()}
60 |
61 |
62 | {this.renderName()}
63 | {this.renderRun()}
64 |
65 |
66 | )
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/classes/nodes/color/MonochromaticColorsProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class GetAlphaProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | stringChange(event) {
11 | const elm = document.getElementById('stringInput');
12 | this.props.node.string = elm.value;
13 | this.props.node.run(null);
14 | }
15 |
16 |
17 | render() {
18 | return (
19 |
20 |
Monochromatic Colors
21 |
22 |
23 | {this.renderName()}
24 | {this.renderRun()}
25 |
26 |
27 | )
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/classes/nodes/color/RGBProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputSlider from '../../../components/PropertiesInputSlider.jsx';
3 |
4 | export default class RGBProperties extends Properties {
5 |
6 | render() {
7 | return (
8 |
9 |
RGB Input
10 |
11 |
12 |
13 |
14 |
15 |
16 | {this.renderName()}
17 | {this.renderRun()}
18 |
19 |
20 | )
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/classes/nodes/color/SampleProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 | export default class SampleProperties extends Properties {
5 |
6 | render() {
7 | return (
8 |
9 |
Sample
10 |
11 | Get color of image at pixel x,y.
12 |
13 |
14 |
15 | {this.renderName()}
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/color/SplitComplimentColorsProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class GetAlphaProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | stringChange(event) {
11 | const elm = document.getElementById('stringInput');
12 | this.props.node.string = elm.value;
13 | this.props.node.run(null);
14 | }
15 |
16 |
17 | render() {
18 | return (
19 |
20 |
Split Compliment Colors
21 |
22 |
23 | {this.renderName()}
24 | {this.renderRun()}
25 |
26 |
27 | )
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/classes/nodes/color/TetradColorsProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class GetAlphaProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | stringChange(event) {
11 | const elm = document.getElementById('stringInput');
12 | this.props.node.string = elm.value;
13 | this.props.node.run(null);
14 | }
15 |
16 |
17 | render() {
18 | return (
19 |
20 |
Tetrad Colors
21 |
22 |
23 | {this.renderName()}
24 | {this.renderRun()}
25 |
26 |
27 | )
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/classes/nodes/color/TriadColorsProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class GetAlphaProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | stringChange(event) {
11 | const elm = document.getElementById('stringInput');
12 | this.props.node.string = elm.value;
13 | this.props.node.run(null);
14 | }
15 |
16 |
17 | render() {
18 | return (
19 |
20 |
Triad Colors
21 |
22 |
23 | {this.renderName()}
24 | {this.renderRun()}
25 |
26 |
27 | )
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/classes/nodes/composing/BlitProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class BlitProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
Blit
11 |
12 | Copy an image or part of an image on top of another image.
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | {this.renderRun()}
21 |
22 |
23 | )
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/classes/nodes/control/Counter.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import CounterProperties from './CounterProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import InputColor from '../InputColor.js';
5 | import InputImage from '../InputImage.js';
6 | import InputString from '../InputString.js';
7 | import OutputNumber from '../OutputNumber.js';
8 |
9 | export default class Counter extends NodeNumber {
10 | constructor(className, graph, x, y, settings) {
11 | super(className, graph, x, y, 'Counter', CounterProperties, settings);
12 |
13 | this.inputs = [
14 | new InputNumber(this, 0, 'Increment', 'hasNumber'),
15 | new InputColor(this, 1, 'Increment', 'hasColor'),
16 | new InputImage(this, 2, 'Increment', 'hasImage'),
17 | new InputString(this, 3, 'Increment', 'hasString'),
18 | new InputNumber(this, 4, 'Reset', 'hasNumberReset'),
19 | new InputColor(this, 5, 'Reset', 'hasColorReset'),
20 | new InputImage(this, 6, 'Reset', 'hasImageReset'),
21 | new InputString(this, 7, 'Reset', 'hasStringReset'),
22 | ];
23 | this.outputs = [
24 | new OutputNumber(this, 0, 'Counter')
25 | ];
26 |
27 | this.number = -1;
28 | }
29 |
30 |
31 | toJson() {
32 | let json = super.toJson();
33 |
34 | return json;
35 | }
36 |
37 |
38 | run(inputThatTriggered) {
39 | if (inputThatTriggered && inputThatTriggered.index >= 4) {
40 | this.number = 0
41 | } else {
42 | this.number++;
43 | }
44 | this.runTimer = Date.now();
45 | super.run(inputThatTriggered);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/classes/nodes/control/CounterProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class CounterProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.resetCounter = this.resetCounter.bind(this);
9 | }
10 |
11 |
12 | resetCounter() {
13 | this.props.node.number = -1;
14 | this.props.node.run(null);
15 | }
16 |
17 |
18 | render() {
19 | return (
20 |
21 |
Counter a Number
22 |
23 | Counts how many times this node has been run. Is set to 0 when page is loaded.
24 |
25 | Reset Counter
26 | {this.renderName()}
27 | {this.renderRun()}
28 |
29 |
30 | )
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/classes/nodes/control/ElseColor.js:
--------------------------------------------------------------------------------
1 | import NodeColor from '../NodeColor.js';
2 | import ElseColorProperties from './ElseColorProperties.jsx';
3 | import OutputColor from '../OutputColor.js';
4 | import InputColor from '../InputColor.js';
5 | const tinycolor = require("tinycolor2");
6 | import InputNumber from '../InputNumber.js';
7 |
8 |
9 | export default class ElseColor extends NodeColor {
10 | constructor(className, graph, x, y, settings) {
11 | super(className, graph, x, y, 'Color If Else', ElseColorProperties, settings);
12 |
13 | this.inputs = [
14 | new InputColor(this, 0, 'Input A'),
15 | new InputColor(this, 1, 'Input B'),
16 | new InputNumber(this, 2, 'Test', 'hasAInput')
17 | ];
18 | this.outputs = [
19 | new OutputColor(this, 0, 'Output')
20 | ];
21 |
22 | this.a = typeof settings.a !== 'undefined' ? settings.a : 1;
23 | }
24 |
25 |
26 | toJson() {
27 | let json = super.toJson();
28 |
29 | json.settings.a = this.a;
30 |
31 | return json;
32 | }
33 |
34 |
35 | run(inputThatTriggered) {
36 | let a = this.a;
37 |
38 | if (this.inputs[2].number != null) {
39 | a = this.inputs[2].number;
40 | }
41 |
42 | if (this.inputs[0].color && this.inputs[1].color) {
43 | this.bg.classList.add('running');
44 | this.runTimer = Date.now();
45 |
46 | this.color = tinycolor('#000');
47 | if (a) {
48 | if (this.inputs[0].color) {
49 | this.color = this.inputs[0].color;
50 | }
51 | } else {
52 | if (this.inputs[1].color) {
53 | this.color = this.inputs[1].color;
54 | }
55 | }
56 |
57 | super.run(inputThatTriggered);
58 |
59 | } else {
60 | this.runTimer = Date.now();
61 | this.color = tinycolor('#000');
62 | super.run(inputThatTriggered);
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/classes/nodes/control/ElseColorProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class ElseProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasAInput: props.node.inputs[2].parent ? true : false
10 | }
11 |
12 | this.aChange = this.aChange.bind(this);
13 | }
14 |
15 |
16 | aChange(event) {
17 | const elm = document.getElementById('aInput');
18 | this.props.node.a = Number(elm.value);
19 | this.props.node.run(null);
20 | }
21 |
22 |
23 | renderA() {
24 | if (!this.state.hasAInput) {
25 | return (
26 |
27 | Test Number
28 | {this.aChange(event);}} />
29 |
30 | )
31 | }
32 | }
33 |
34 |
35 | render() {
36 | return (
37 |
38 |
Color If Else
39 |
40 | {this.renderA()}
41 |
42 |
43 | Outputs color A if test number is true. Outputs color B if test number is false. Number is considered false if it is 0 or -0.
44 | {this.renderRun()}
45 |
46 |
47 | )
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/classes/nodes/control/ElseNumber.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import ElseNumberProperties from './ElseNumberProperties.jsx';
3 | import OutputNumber from '../OutputNumber.js';
4 | import InputNumber from '../InputNumber.js';
5 |
6 |
7 | export default class ElseNumber extends NodeNumber {
8 | constructor(className, graph, x, y, settings) {
9 | super(className, graph, x, y, 'Number If Else', ElseNumberProperties, settings);
10 |
11 | this.inputs = [
12 | new InputNumber(this, 0, 'Input A'),
13 | new InputNumber(this, 1, 'Input B'),
14 | new InputNumber(this, 2, 'Test', 'hasAInput')
15 | ];
16 | this.outputs = [
17 | new OutputNumber(this, 0, 'Output')
18 | ];
19 |
20 | this.a = typeof settings.a !== 'undefined' ? settings.a : 1;
21 | }
22 |
23 |
24 | toJson() {
25 | let json = super.toJson();
26 |
27 | json.settings.a = this.a;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | let a = this.a;
35 |
36 | if (this.inputs[2].number != null) {
37 | a = this.inputs[2].number;
38 | }
39 |
40 | if (this.inputs[0].number != null && this.inputs[1].number != null) {
41 | this.bg.classList.add('running');
42 | this.runTimer = Date.now();
43 |
44 | this.number = null;
45 | if (a) {
46 | if (this.inputs[0].number != null) {
47 | this.number = this.inputs[0].number;
48 | }
49 | } else {
50 | if (this.inputs[1].number != null) {
51 | this.number = this.inputs[1].number;
52 | }
53 | }
54 |
55 | super.run(inputThatTriggered);
56 |
57 | } else {
58 | this.runTimer = Date.now();
59 | this.number = null;
60 | super.run(inputThatTriggered);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/classes/nodes/control/ElseNumberProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class ElseNumberProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasAInput: props.node.inputs[2].parent ? true : false
10 | }
11 |
12 | this.aChange = this.aChange.bind(this);
13 | }
14 |
15 |
16 | aChange(event) {
17 | const elm = document.getElementById('aInput');
18 | this.props.node.a = Number(elm.value);
19 | this.props.node.run(null);
20 | }
21 |
22 |
23 | renderA() {
24 | if (!this.state.hasAInput) {
25 | return (
26 |
27 | Test Number
28 | {this.aChange(event);}} />
29 |
30 | )
31 | }
32 | }
33 |
34 |
35 | render() {
36 | return (
37 |
38 |
Number If Else
39 |
40 | {this.renderA()}
41 |
42 |
43 | Outputs number A if test number is true. Outputs number B if test number is false. Number is considered false if it is 0 or -0.
44 | {this.renderRun()}
45 |
46 |
47 | )
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/classes/nodes/control/ElseProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class ElseProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasAInput: props.node.inputs[2].parent ? true : false
10 | }
11 |
12 | this.aChange = this.aChange.bind(this);
13 | }
14 |
15 |
16 | aChange(event) {
17 | const elm = document.getElementById('aInput');
18 | this.props.node.a = Number(elm.value);
19 | this.props.node.run(null);
20 | }
21 |
22 |
23 | renderA() {
24 | if (!this.state.hasAInput) {
25 | return (
26 |
27 | Test Number
28 | {this.aChange(event);}} />
29 |
30 | )
31 | }
32 | }
33 |
34 |
35 | render() {
36 | return (
37 |
38 |
Image If Else
39 |
40 | {this.renderA()}
41 |
42 |
43 | Outputs image A if test number is true. Outputs image B if test number is false. Number is considered false if it is 0 or -0.
44 | {this.renderRun()}
45 |
46 |
47 | )
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/classes/nodes/control/ElseString.js:
--------------------------------------------------------------------------------
1 | import NodeString from '../NodeString.js';
2 | import ElseStringProperties from './ElseStringProperties.jsx';
3 | import OutputString from '../OutputString.js';
4 | import InputNumber from '../InputNumber.js';
5 | import InputString from '../InputString.js';
6 |
7 |
8 | export default class ElseString extends NodeString {
9 | constructor(className, graph, x, y, settings) {
10 | super(className, graph, x, y, 'String If Else', ElseStringProperties, settings);
11 |
12 | this.inputs = [
13 | new InputString(this, 0, 'Input A'),
14 | new InputString(this, 1, 'Input B'),
15 | new InputNumber(this, 2, 'Test', 'hasAInput')
16 | ];
17 | this.outputs = [
18 | new OutputString(this, 0, 'Output')
19 | ];
20 |
21 | this.a = typeof settings.a !== 'undefined' ? settings.a : 1;
22 | }
23 |
24 |
25 | toJson() {
26 | let json = super.toJson();
27 |
28 | json.settings.a = this.a;
29 |
30 | return json;
31 | }
32 |
33 |
34 | run(inputThatTriggered) {
35 | let a = this.a;
36 |
37 | if (this.inputs[2].number != null) {
38 | a = this.inputs[2].number;
39 | }
40 |
41 | if (this.inputs[0].string != null && this.inputs[1].string != null) {
42 | this.bg.classList.add('running');
43 | this.runTimer = Date.now();
44 |
45 | this.string = null;
46 | if (a) {
47 | if (this.inputs[0].string != null) {
48 | this.string = this.inputs[0].string;
49 | }
50 | } else {
51 | if (this.inputs[1].string != null) {
52 | this.string = this.inputs[1].string;
53 | }
54 | }
55 |
56 | super.run(inputThatTriggered);
57 |
58 | } else {
59 | this.runTimer = Date.now();
60 | this.string = null;
61 | super.run(inputThatTriggered);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/classes/nodes/control/ElseStringProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class ElseStringProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasAInput: props.node.inputs[2].parent ? true : false
10 | }
11 |
12 | this.aChange = this.aChange.bind(this);
13 | }
14 |
15 |
16 | aChange(event) {
17 | const elm = document.getElementById('aInput');
18 | this.props.node.a = Number(elm.value);
19 | this.props.node.run(null);
20 | }
21 |
22 |
23 | renderA() {
24 | if (!this.state.hasAInput) {
25 | return (
26 |
27 | Test Number
28 | {this.aChange(event);}} />
29 |
30 | )
31 | }
32 | }
33 |
34 |
35 | render() {
36 | return (
37 |
38 |
String If Else
39 |
40 | {this.renderA()}
41 |
42 |
43 | Outputs string A if test number is true. Outputs string B if test number is false. Number is considered false if it is 0 or -0.
44 | {this.renderRun()}
45 |
46 |
47 | )
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/classes/nodes/control/IfColor.js:
--------------------------------------------------------------------------------
1 | import NodeColor from '../NodeColor.js';
2 | import IfColorProperties from './IfColorProperties.jsx';
3 | import OutputColor from '../OutputColor.js';
4 | import InputColor from '../InputColor.js';
5 | import InputNumber from '../InputNumber.js';
6 |
7 |
8 | export default class IfColor extends NodeColor {
9 | constructor(className, graph, x, y, settings) {
10 | super(className, graph, x, y, 'Color If', IfColorProperties, settings);
11 |
12 | this.inputs = [
13 | new InputColor(this, 0, 'Input'),
14 | new InputNumber(this, 1, 'Test', 'hasAInput')
15 | ];
16 | this.outputs = [
17 | new OutputColor(this, 0, 'Output')
18 | ];
19 |
20 | this.a = typeof settings.a !== 'undefined' ? settings.a : 1;
21 | }
22 |
23 |
24 | toJson() {
25 | let json = super.toJson();
26 |
27 | json.settings.a = this.a;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | let a = this.a;
35 |
36 | if (this.inputs[1].number != null) {
37 | a = this.inputs[1].number;
38 | }
39 |
40 | if (a) {
41 | if (this.inputs[0].color) {
42 | this.bg.classList.add('running');
43 | this.runTimer = Date.now();
44 | this.color = this.inputs[0].color;
45 | super.run(inputThatTriggered);
46 | } else {
47 | this.runTimer = Date.now();
48 | this.color = tinycolor('#000');
49 | super.run(inputThatTriggered);
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/classes/nodes/control/IfColorProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 | export default class IfProperties extends Properties {
5 |
6 |
7 | render() {
8 | return (
9 |
10 |
Color If
11 |
12 |
13 |
14 |
15 | Outputs color if test number is true. Does nothing if number is false. Number is considered false if it is 0 or -0.
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/control/IfImage.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import IfImageProperties from './IfImageProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 | import InputNumber from '../InputNumber.js';
6 |
7 |
8 | export default class IfImage extends NodeImage {
9 | constructor(className, graph, x, y, settings) {
10 | super(className, graph, x, y, 'Image If', IfImageProperties, settings);
11 |
12 | this.inputs = [
13 | new InputImage(this, 0, 'Input'),
14 | new InputNumber(this, 1, 'Test', 'hasAInput')
15 | ];
16 | this.outputs = [
17 | new OutputImage(this, 0, 'Output')
18 | ];
19 |
20 | this.a = typeof settings.a !== 'undefined' ? settings.a : 1;
21 | }
22 |
23 |
24 | toJson() {
25 | let json = super.toJson();
26 |
27 | json.settings.a = this.a;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | let a = this.a;
35 |
36 | if (this.inputs[1].number != null) {
37 | a = this.inputs[1].number;
38 | }
39 |
40 | if (a) {
41 | if (this.inputs[0].image) {
42 | this.bg.classList.add('running');
43 | this.runTimer = Date.now();
44 |
45 | if (this.isInsideALoop) {
46 | let image = this.inputs[0].image.clone();
47 | this.image = image;
48 | super.run(inputThatTriggered);
49 |
50 | } else {
51 | Jimp.read(this.inputs[0].image).then(image => {
52 | this.image = image;
53 | super.run(inputThatTriggered);
54 | })
55 | }
56 | } else {
57 | this.runTimer = Date.now();
58 | this.image = null;
59 | super.run(inputThatTriggered);
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/classes/nodes/control/IfImageProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 | export default class IfProperties extends Properties {
5 |
6 |
7 | render() {
8 | return (
9 |
10 |
Image If
11 |
12 |
13 |
14 |
15 | Outputs image if test number is true. Does nothing if number is false. Number is considered false if it is 0 or -0.
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/control/IfNumber.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import IfNumberProperties from './IfNumberProperties.jsx';
3 | import OutputNumber from '../OutputNumber.js';
4 | import InputNumber from '../InputNumber.js';
5 |
6 |
7 | export default class IfNumber extends NodeNumber {
8 | constructor(className, graph, x, y, settings) {
9 | super(className, graph, x, y, 'Number If', IfNumberProperties, settings);
10 |
11 | this.inputs = [
12 | new InputNumber(this, 0, 'Input'),
13 | new InputNumber(this, 1, 'Test', 'hasAInput')
14 | ];
15 | this.outputs = [
16 | new OutputNumber(this, 0, 'Output')
17 | ];
18 |
19 | this.a = typeof settings.a !== 'undefined' ? settings.a : 1;
20 | }
21 |
22 |
23 | toJson() {
24 | let json = super.toJson();
25 |
26 | json.settings.a = this.a;
27 |
28 | return json;
29 | }
30 |
31 |
32 | run(inputThatTriggered) {
33 | let a = this.a;
34 |
35 | if (this.inputs[1].number != null) {
36 | a = this.inputs[1].number;
37 | }
38 |
39 | if (a) {
40 | if (this.inputs[0].number != null) {
41 | this.bg.classList.add('running');
42 | this.runTimer = Date.now();
43 | this.number = this.inputs[0].number;
44 | super.run(inputThatTriggered);
45 | } else {
46 | this.runTimer = Date.now();
47 | this.number = null;
48 | super.run(inputThatTriggered);
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/classes/nodes/control/IfNumberProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 | export default class IfProperties extends Properties {
5 |
6 |
7 | render() {
8 | return (
9 |
10 |
Number If
11 |
12 |
13 |
14 |
15 | Outputs number if test number is true. Does nothing if number is false. Number is considered false if it is 0 or -0.
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/control/IfString.js:
--------------------------------------------------------------------------------
1 | import NodeString from '../NodeString.js';
2 | import IfStringProperties from './IfStringProperties.jsx';
3 | import OutputString from '../OutputString.js';
4 | import InputString from '../InputString.js';
5 | import InputNumber from '../InputNumber.js';
6 |
7 |
8 | export default class IfString extends NodeString {
9 | constructor(className, graph, x, y, settings) {
10 | super(className, graph, x, y, 'String If', IfStringProperties, settings);
11 |
12 | this.inputs = [
13 | new InputString(this, 0, 'Input'),
14 | new InputNumber(this, 1, 'Test', 'hasAInput')
15 | ];
16 | this.outputs = [
17 | new OutputString(this, 0, 'Output')
18 | ];
19 |
20 | this.a = typeof settings.a !== 'undefined' ? settings.a : 1;
21 | }
22 |
23 |
24 | toJson() {
25 | let json = super.toJson();
26 |
27 | json.settings.a = this.a;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | let a = this.a;
35 |
36 | if (this.inputs[1].number != null) {
37 | a = this.inputs[1].number;
38 | }
39 |
40 | if (a) {
41 | if (this.inputs[0].string != null) {
42 | this.bg.classList.add('running');
43 | this.runTimer = Date.now();
44 | this.string = this.inputs[0].string;
45 | super.run(inputThatTriggered);
46 | } else {
47 | this.runTimer = Date.now();
48 | this.string = null;
49 | super.run(inputThatTriggered);
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/classes/nodes/control/IfStringProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 | export default class IfProperties extends Properties {
5 |
6 |
7 | render() {
8 | return (
9 |
10 |
String If
11 |
12 |
13 |
14 |
15 | Outputs string if test number is true. Does nothing if number is false. Number is considered false if it is 0 or -0.
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/control/LoopInputImageLoopOutput.js:
--------------------------------------------------------------------------------
1 | import InputImage from '../InputImage.js';
2 |
3 |
4 | export default class LoopInputImageLoopOutput extends InputImage {
5 | constructor(node, index, name) {
6 | super(node, index, name);
7 | }
8 |
9 |
10 | connectionMade() {
11 | if (this.node.bg.classList.contains('selected')) {
12 | this.node.propertiesComponentInstance.setState({hasLoopOutput:true});
13 | }
14 | }
15 |
16 |
17 | connectionRemoved() {
18 | if (this.node.bg.classList.contains('selected')) {
19 | this.node.propertiesComponentInstance.setState({hasLoopOutput:false});
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/classes/nodes/control/LoopInputNumberNumLoops.js:
--------------------------------------------------------------------------------
1 | import InputNumber from '../InputNumber.js';
2 |
3 |
4 | export default class LoopInputNumberNumLoops extends InputNumber {
5 | constructor(node, index, name) {
6 | super(node, index, name);
7 | }
8 |
9 |
10 | connectionMade() {
11 | if (this.node.bg.classList.contains('selected')) {
12 | this.node.propertiesComponentInstance.setState({hasNumLoopsInput:true});
13 | }
14 | }
15 |
16 |
17 | connectionRemoved() {
18 | if (this.node.bg.classList.contains('selected')) {
19 | this.node.propertiesComponentInstance.setState({hasNumLoopsInput:false});
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/classes/nodes/control/LoopProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class LoopProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasLoopOutput: props.node.inputs[2].parent ? true : false,
10 | hasLoopInput: props.node.outputs[1].connections.length ? true : false,
11 | hasNumLoopsInput: props.node.inputs[1].parent ? true : false,
12 | }
13 |
14 | this.numLoopsChange = this.numLoopsChange.bind(this);
15 | }
16 |
17 |
18 | numLoopsChange(event) {
19 | const elm = document.getElementById('numLoopsInput');
20 | this.props.node.numLoops = Number(elm.value);
21 | this.props.node.run(null);
22 | }
23 |
24 |
25 | renderNumLoops() {
26 | if (!this.state.hasNumLoopsInput) {
27 | return (
28 |
29 | Number of Loops
30 | {this.numLoopsChange(event);}} />
31 |
32 | )
33 | }
34 | }
35 |
36 |
37 | render() {
38 | return (
39 |
40 |
Loop
41 |
42 | This node creates a loop that runs n times.
43 |
44 | The loop starts with the "loop start" output and ends with the "loop end" input. Loop start and loop end should connect to each other with nodes in between.
45 |
46 | After the loop is finished the output image will be set.
47 |
48 | {this.renderNumLoops()}
49 |
50 | Increment output starts with 0 and adds 1 each loop.
51 | {this.renderRun()}
52 |
53 |
54 | )
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/classes/nodes/filter/AmbientOcclusionProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 | export default class AmbientOcclusionProperties extends Properties {
5 |
6 | constructor(props) {
7 | super(props);
8 | }
9 |
10 |
11 | render() {
12 | return (
13 |
14 |
Ambient Occlusion
15 |
16 |
17 | {this.renderRun()}
18 |
19 |
20 | Uses input as a height map. Black is lowest and white is highest. Calculates how much each pixel is exposed to ambient lighting.
21 |
22 | Increasing radius greatly decreases performance.
23 |
24 |
25 |
26 | )
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/classes/nodes/filter/NormalMapProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class NormalMapProperties extends Properties {
6 |
7 | constructor(props) {
8 | super(props);
9 | }
10 |
11 |
12 | render() {
13 | return (
14 |
15 |
Height to Normal Map
16 |
17 |
18 | {this.renderRun()}
19 |
20 |
21 | )
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/classes/nodes/filter/PixelateProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class BlitProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
Pixelate
11 |
12 | Apply a pixelation effect to the image or a region.
13 |
14 |
15 |
16 |
17 |
18 |
19 | {this.renderRun()}
20 |
21 |
22 | )
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/classes/nodes/filter/Posterize.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import PosterizeProperties from './PosterizeProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 | import InputNumber from '../InputNumber.js';
6 |
7 |
8 | export default class Posterize extends NodeImage {
9 | constructor(className, graph, x, y, settings) {
10 | super(className, graph, x, y, 'Posterize', PosterizeProperties, settings);
11 |
12 | this.inputs = [
13 | new InputImage(this, 0, 'Input'),
14 | new InputNumber(this, 1, 'Amount', 'hasAmountInput')
15 | ];
16 | this.outputs = [
17 | new OutputImage(this, 0, 'Output')
18 | ];
19 |
20 | this.amount = typeof settings.amount !== 'undefined' ? settings.amount : 5;
21 | }
22 |
23 |
24 | run(inputThatTriggered) {
25 | if (this.inputs[0].image) {
26 | this.bg.classList.add('running');
27 | this.runTimer = Date.now();
28 |
29 | let amount = this.amount;
30 |
31 | if (this.inputs[1].number != null) {
32 | amount = this.inputs[1].number;
33 | }
34 |
35 | if (this.isInsideALoop) {
36 | let image = this.inputs[0].image.clone();
37 | image.posterize(amount);
38 | this.image = image;
39 | super.run(inputThatTriggered);
40 |
41 | } else {
42 | Jimp.read(this.inputs[0].image).then(image => {
43 | image.posterize(amount, (error, image) => {
44 | if (error) {
45 | console.log(error);
46 | } else {
47 | this.image = image;
48 | super.run(inputThatTriggered);
49 | }
50 | });
51 | })
52 | }
53 | } else {
54 | this.runTimer = Date.now();
55 | this.image = null;
56 | super.run(inputThatTriggered);
57 | }
58 | }
59 |
60 |
61 | toJson() {
62 | let json = super.toJson();
63 |
64 | json.settings.amount = this.amount;
65 |
66 | return json;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/classes/nodes/filter/PosterizeProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class PosterizeProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
Posterize
11 |
12 |
13 | {this.renderRun()}
14 |
15 |
16 | )
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/classes/nodes/filter/Sepia.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import SepiaProperties from './SepiaProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 |
6 | export default class Sepia extends NodeImage {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Sepia', SepiaProperties, settings);
9 |
10 | this.inputs = [
11 | new InputImage(this, 0, 'Input')
12 | ];
13 | this.outputs = [
14 | new OutputImage(this, 0, 'Output')
15 | ];
16 | }
17 |
18 |
19 | run(inputThatTriggered) {
20 | if (this.inputs[0].image) {
21 | this.bg.classList.add('running');
22 | this.runTimer = Date.now();
23 |
24 | if (this.isInsideALoop) {
25 | const image = this.inputs[0].image.clone();
26 | image.sepia();
27 | this.image = image;
28 | super.run(inputThatTriggered);
29 | } else {
30 | Jimp.read(this.inputs[0].image).then(image => {
31 | image.sepia((error, image) => {
32 | this.image = image;
33 | super.run(inputThatTriggered);
34 | });
35 | })
36 | }
37 |
38 | } else {
39 | this.runTimer = Date.now();
40 | this.image = null;
41 | super.run(inputThatTriggered);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/classes/nodes/filter/SepiaProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class SepiaProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Sepia Filter
14 |
15 | {this.renderRun()}
16 |
17 |
18 | )
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/classes/nodes/filter/SobelProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class SepiaProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Sobel Filter
14 |
15 | {this.renderRun()}
16 |
17 |
18 | )
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/classes/nodes/filter/StainedGlassProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class StainedGlassProperties extends Properties {
6 |
7 | constructor(props) {
8 | super(props);
9 | }
10 |
11 |
12 | render() {
13 | return (
14 |
15 |
Height to Normal Map
16 |
17 |
18 | {this.renderRun()}
19 |
20 |
21 | )
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/classes/nodes/image/CircleProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class CircleProperties extends Properties {
6 |
7 | constructor(props) {
8 | super(props);
9 |
10 | this.state = {
11 | hasColorInput: props.node.inputs[3].parent ? true : false,
12 | }
13 | }
14 |
15 | render() {
16 | return (
17 |
18 |
Circle
19 |
20 |
21 |
22 |
23 |
24 | {this.renderColor()}
25 |
26 | {this.renderRun()}
27 |
28 |
29 | )
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/classes/nodes/image/FaultlineProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class FaultlineProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
Faultline Noise
11 |
12 | Generate noise using fault line formation algorithm.
13 |
14 |
15 |
16 |
17 |
18 | {this.renderRun()}
19 |
20 |
21 | For each iteration pick two random points to create a line. Raise or lower pixel depending on which side of the line it is on.
22 |
23 |
https://github.com/barisusakli/faultline
24 |
25 |
26 | )
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/classes/nodes/image/ImageUpload.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import ImageUploadProperties from './ImageUploadProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class ImageUpload extends NodeImage {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'ImageUpload', ImageUploadProperties, settings);
9 |
10 | this.inputs = [];
11 | this.outputs = [
12 | new OutputImage(this, 0, 'Output'),
13 | new OutputNumber(this, 1, 'Width'),
14 | new OutputNumber(this, 2, 'Height')
15 | ];
16 |
17 | this.base64 = typeof settings.base64 !== 'undefined' ? settings.base64 : null;
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | json.settings.base64 = null;
25 |
26 | return json;
27 | }
28 |
29 |
30 | run(inputThatTriggered) {
31 | if (this.base64) {
32 | this.bg.classList.add('running');
33 | this.runTimer = Date.now();
34 | Jimp.read(this.base64).then(image => {
35 | this.image = image;
36 | super.run(inputThatTriggered);
37 | })
38 | } else {
39 | this.runTimer = Date.now();
40 | this.image = null;
41 | super.run(inputThatTriggered);
42 | }
43 | }
44 |
45 |
46 | passToChildren() {
47 | if (this.image) {
48 | this.outputs[1].connections.forEach(conn => {
49 | conn.number = this.image.bitmap.width;
50 | conn.runNode();
51 | })
52 | this.outputs[2].connections.forEach(conn => {
53 | conn.number = this.image.bitmap.height;
54 | conn.runNode();
55 | })
56 | }
57 |
58 | super.passToChildren();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/classes/nodes/image/ImageUploadProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class GreyscaleProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | progress: null
10 | }
11 |
12 | this.onUploadImage = this.onUploadImage.bind(this);
13 | }
14 |
15 |
16 | onUploadImage(event) {
17 | const elm = document.getElementById('uploadInput');
18 | const reader = new FileReader();
19 |
20 | // reader.addEventListener('load', (e) => {
21 | // this.props.node.base64 = e.target.result;
22 | // this.props.node.run(null);
23 | // })
24 |
25 | reader.onloadstart = (event) => {
26 | this.setState({progress: 0});
27 | }
28 |
29 | reader.onprogress = (event) => {
30 | if (event.lengthComputable) {
31 | this.setState({progress: event.loaded / event.total * 100});
32 | }
33 | }
34 |
35 | reader.onloadend = (event) => {
36 | this.setState({progress: null});
37 | this.props.node.base64 = event.target.result;
38 | this.props.node.run(null);
39 | }
40 |
41 | reader.readAsDataURL(elm.files[0]);
42 | }
43 |
44 |
45 | render() {
46 | return (
47 |
48 |
Image Upload
49 |
50 | {this.onUploadImage(event);}} />
51 |
52 | {this.state.progress != null ?
53 | Math.round(this.state.progress)+'% Uploaded'
54 | : null}
55 |
56 | Uploaded images are not saved with the graph.
57 | {this.renderRun()}
58 |
59 |
60 | )
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/classes/nodes/image/LineProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class LineProperties extends Properties {
6 |
7 | constructor(props) {
8 | super(props);
9 |
10 | this.state = {
11 | hasColorInput: props.node.inputs[6].parent ? true : false,
12 | }
13 | }
14 |
15 | render() {
16 | return (
17 |
18 |
Line
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | {this.renderColor()}
28 |
29 | {this.renderRun()}
30 |
31 |
32 | )
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/classes/nodes/image/PasteImageProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class PasteImageProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Image from Clipboard
14 |
15 | When this node is selected it captures images that are pasted.
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/image/SimplexProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class SimplexProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
Simplex Noise
11 |
12 |
13 |
14 |
15 |
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/image/TriangleProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class TriangleProperties extends Properties {
6 |
7 | constructor(props) {
8 | super(props);
9 |
10 | this.state = {
11 | hasColorInput: props.node.inputs[8].parent ? true : false,
12 | }
13 | }
14 |
15 | render() {
16 | return (
17 |
18 |
Triangle
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | {this.renderColor()}
29 |
30 | {this.renderRun()}
31 |
32 |
33 | )
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/classes/nodes/image/UniformColorProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class UniformColorProperties extends Properties {
6 |
7 | constructor(props) {
8 | super(props);
9 |
10 | this.state = {
11 | hasColorInput: props.node.inputs[2].parent ? true : false,
12 | }
13 | }
14 |
15 |
16 | render() {
17 | return (
18 |
19 |
Uniform Color
20 |
21 |
22 |
23 |
24 |
25 |
26 | {this.renderColor()}
27 |
28 | {this.renderRun()}
29 |
30 |
31 | )
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/classes/nodes/image/UrlImage.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import UrlImageProperties from './UrlImageProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import OutputNumber from '../OutputNumber.js';
5 | import Jimp from "jimp";
6 | import fetch from 'isomorphic-unfetch';
7 |
8 |
9 | export default class UrlImage extends NodeImage {
10 | constructor(className, graph, x, y, settings) {
11 | super(className, graph, x, y, 'Image from Url', UrlImageProperties, settings);
12 |
13 | this.inputs = [];
14 | this.outputs = [
15 | new OutputImage(this, 0, 'Output'),
16 | new OutputNumber(this, 1, 'Width'),
17 | new OutputNumber(this, 2, 'Height')
18 | ];
19 |
20 | //this.url = 'https://i.imgur.com/mdlwVuL.jpg';
21 | this.url = typeof settings.url !== 'undefined' ? settings.url : 'https://i.imgur.com/3aDSTiBl.jpg';
22 | }
23 |
24 |
25 | toJson() {
26 | let json = super.toJson();
27 |
28 | json.settings.url = this.url;
29 |
30 | return json;
31 | }
32 |
33 |
34 | run(inputThatTriggered) {
35 | this.bg.classList.add('running');
36 | this.runTimer = Date.now();
37 | Jimp.read(this.url).then(image => {
38 | this.image = image;
39 | super.run(inputThatTriggered);
40 | }).catch(error => {
41 | console.log(error);
42 | })
43 | }
44 |
45 |
46 | passToChildren() {
47 | if (this.image) {
48 | this.outputs[1].connections.forEach(conn => {
49 | conn.number = this.image.bitmap.width;
50 | conn.runNode();
51 | })
52 | this.outputs[2].connections.forEach(conn => {
53 | conn.number = this.image.bitmap.height;
54 | conn.runNode();
55 | })
56 | }
57 |
58 | super.passToChildren();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/classes/nodes/image/UrlImageProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class UrlImageProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.urlChange = this.urlChange.bind(this);
9 | }
10 |
11 |
12 | urlChange(event) {
13 | const elm = document.getElementById('urlInput');
14 | this.props.node.url = elm.value;
15 | this.props.node.run(null);
16 | }
17 |
18 |
19 | render() {
20 | return (
21 |
22 |
Image from URL
23 |
24 | URL
25 |
{this.urlChange(event);}} />
26 |
27 |
28 | If this fails it's probably because the remote site doesn't allow cross-origin resource sharing. Some sites like
Imgur allow it.
29 | {this.renderRun()}
30 |
31 |
32 | )
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/classes/nodes/image/WorleyProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class WorleyProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
Worley Noise
11 |
12 |
13 |
14 |
15 |
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/number/AbsoluteValue.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import AbsoluteValueProperties from './AbsoluteValueProperties.jsx';
3 | import OutputNumber from '../OutputNumber.js';
4 | import InputNumber from '../InputNumber.js';
5 |
6 | export default class AbsoluteValue extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Absolute Value', AbsoluteValueProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | ];
13 | this.outputs = [
14 | new OutputNumber(this, 0, 'Result')
15 | ];
16 |
17 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | json.settings.a = this.a;
25 |
26 | return json;
27 | }
28 |
29 |
30 | run(inputThatTriggered) {
31 | if (this.inputs[0].number == null) {
32 | this.a = null;
33 | } else {
34 | this.a = this.inputs[0].number;
35 | }
36 |
37 | if (this.a != null && !isNaN(this.a)) {
38 | this.bg.classList.add('running');
39 | this.runTimer = Date.now();
40 | this.number = Math.abs(this.a);
41 | super.run(inputThatTriggered);
42 | } else {
43 | this.runTimer = Date.now();
44 | this.number = null;
45 | super.run(inputThatTriggered);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/classes/nodes/number/AbsoluteValueProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class AbsoluteValueProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | }
11 | }
12 |
13 |
14 | renderResult() {
15 | if (this.state.hasA) {
16 | return (
17 |
18 | |{this.props.node.a}|= {Math.abs(this.props.node.a)}
19 |
20 | )
21 | }
22 | }
23 |
24 |
25 | render() {
26 | return (
27 |
28 |
Add Numbers
29 |
30 | {this.renderResult()}
31 | {this.renderName()}
32 | {this.renderRun()}
33 |
34 |
35 | )
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/classes/nodes/number/AddNumbers.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import AddNumbersProperties from './AddNumbersProperties.jsx';
3 | import OutputNumber from '../OutputNumber.js';
4 | import InputNumber from '../InputNumber.js';
5 |
6 | export default class AddNumbers extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Add', AddNumbersProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | new InputNumber(this, 1, 'b', 'hasB'),
13 | ];
14 | this.outputs = [
15 | new OutputNumber(this, 0, 'Result')
16 | ];
17 |
18 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
19 | this.b = typeof settings.b !== 'undefined' ? settings.b : null;
20 | }
21 |
22 |
23 | toJson() {
24 | let json = super.toJson();
25 |
26 | json.settings.a = this.a;
27 | json.settings.b = this.b;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | if (this.inputs[0].number == null) {
35 | this.a = null;
36 | } else {
37 | this.a = this.inputs[0].number;
38 | }
39 |
40 | if (this.inputs[1].number == null) {
41 | this.b = null;
42 | } else {
43 | this.b = this.inputs[1].number;
44 | }
45 |
46 | if (this.a != null && this.b != null && !isNaN(this.a) && !isNaN(this.b)) {
47 | this.bg.classList.add('running');
48 | this.runTimer = Date.now();
49 | this.number = this.a + this.b;
50 | super.run(inputThatTriggered);
51 | } else {
52 | this.runTimer = Date.now();
53 | this.number = null;
54 | super.run(inputThatTriggered);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/classes/nodes/number/AddNumbersProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class AddNumbersProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | hasB: props.node.inputs[1].parent ? true : false
11 | }
12 | }
13 |
14 |
15 | renderResult() {
16 | if (this.state.hasA && this.state.hasB) {
17 | return (
18 |
19 | {this.props.node.a} + {this.props.node.b} = {this.props.node.a + this.props.node.b}
20 |
21 | )
22 | }
23 | }
24 |
25 |
26 | render() {
27 | return (
28 |
29 |
Add Numbers
30 |
31 | {this.renderResult()}
32 | {this.renderName()}
33 | {this.renderRun()}
34 |
35 |
36 | )
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/classes/nodes/number/Atan2.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import Atan2Properties from './Atan2Properties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class Atan2 extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Atan2', Atan2Properties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'x', 'hasX'),
12 | new InputNumber(this, 1, 'y', 'hasY'),
13 | ];
14 | this.outputs = [
15 | new OutputNumber(this, 0, 'Result')
16 | ];
17 |
18 | this.numX = typeof settings.numX !== 'undefined' ? settings.numX : null;
19 | this.numY = typeof settings.numY !== 'undefined' ? settings.numY : null;
20 | }
21 |
22 |
23 | toJson() {
24 | let json = super.toJson();
25 |
26 | json.settings.numX = this.numX;
27 | json.settings.numY = this.numY;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | if (this.inputs[0].number == null) {
35 | this.numX = null;
36 | } else {
37 | this.numX = this.inputs[0].number;
38 | }
39 |
40 | if (this.inputs[1].number == null) {
41 | this.numY = null;
42 | } else {
43 | this.numY = this.inputs[1].number;
44 | }
45 |
46 | if (this.numX != null && !isNaN(this.numX) && this.numY != null && !isNaN(this.numY)) {
47 | this.bg.classList.add('running');
48 | this.runTimer = Date.now();
49 | this.number = Math.atan2(this.numY, this.numX);
50 | super.run(inputThatTriggered);
51 | } else {
52 | this.runTimer = Date.now();
53 | this.number = null;
54 | super.run(inputThatTriggered);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/classes/nodes/number/Atan2Properties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class AddNumbersProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasX: props.node.inputs[0].parent ? true : false,
10 | hasY: props.node.inputs[1].parent ? true : false
11 | }
12 | }
13 |
14 |
15 | renderResult() {
16 | if (this.state.hasX && this.state.hasY) {
17 | return (
18 |
19 | atan2({this.props.node.numY}, {this.props.node.numX}) = {Math.atan2(this.props.node.numY, this.props.node.numX)}
20 |
21 | )
22 | }
23 | }
24 |
25 |
26 | render() {
27 | return (
28 |
29 |
Atan2
30 |
31 | {this.renderResult()}
32 | {this.renderName()}
33 | {this.renderRun()}
34 |
35 |
36 | )
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/classes/nodes/number/Ceil.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import CeilProperties from './CeilProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class Ceil extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Ceil', CeilProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | ];
13 | this.outputs = [
14 | new OutputNumber(this, 0, 'Result')
15 | ];
16 |
17 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | json.settings.a = this.a;
25 |
26 | return json;
27 | }
28 |
29 |
30 | run(inputThatTriggered) {
31 | if (this.inputs[0].number == null) {
32 | this.a = null;
33 | } else {
34 | this.a = this.inputs[0].number;
35 | }
36 |
37 | if (this.a != null && !isNaN(this.a)) {
38 | this.bg.classList.add('running');
39 | this.runTimer = Date.now();
40 | this.number = Math.ceil(this.a);
41 | super.run(inputThatTriggered);
42 | } else {
43 | this.runTimer = Date.now();
44 | this.number = null;
45 | super.run(inputThatTriggered);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/classes/nodes/number/CeilProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class CeilProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | }
11 | }
12 |
13 |
14 | renderResult() {
15 | if (this.state.hasA) {
16 | return (
17 |
18 | ceil({this.props.node.a}) = {Math.ceil(this.props.node.a)}
19 |
20 | )
21 | }
22 | }
23 |
24 |
25 | render() {
26 | return (
27 |
28 |
Ceil a Number
29 |
30 | {this.renderResult()}
31 | {this.renderName()}
32 | {this.renderRun()}
33 |
34 |
35 | )
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/classes/nodes/number/Cos.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import CosProperties from './CosProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class Cos extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Cosine', CosProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | ];
13 | this.outputs = [
14 | new OutputNumber(this, 0, 'Result')
15 | ];
16 |
17 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | json.settings.a = this.a;
25 |
26 | return json;
27 | }
28 |
29 |
30 | run(inputThatTriggered) {
31 | if (this.inputs[0].number == null) {
32 | this.a = null;
33 | } else {
34 | this.a = this.inputs[0].number;
35 | }
36 |
37 | if (this.a != null && !isNaN(this.a)) {
38 | this.bg.classList.add('running');
39 | this.runTimer = Date.now();
40 | this.number = Math.cos(this.a);
41 | super.run(inputThatTriggered);
42 | } else {
43 | this.runTimer = Date.now();
44 | this.number = null;
45 | super.run(inputThatTriggered);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/classes/nodes/number/CosProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class CosProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | }
11 | }
12 |
13 |
14 | renderResult() {
15 | if (this.state.hasA) {
16 | return (
17 |
18 | cos({this.props.node.a}) = {Math.cos(this.props.node.a)}
19 |
20 | )
21 | }
22 | }
23 |
24 |
25 | render() {
26 | return (
27 |
28 |
Cosine of a Number
29 |
30 | {this.renderResult()}
31 | {this.renderName()}
32 | {this.renderRun()}
33 |
34 |
35 | )
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/classes/nodes/number/DegreesToRadians.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import DegreesToRadiansProperties from './DegreesToRadiansProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class DegreesToRadians extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Degrees to Radians', DegreesToRadiansProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | ];
13 | this.outputs = [
14 | new OutputNumber(this, 0, 'Result')
15 | ];
16 |
17 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | json.settings.a = this.a;
25 |
26 | return json;
27 | }
28 |
29 |
30 | run(inputThatTriggered) {
31 | if (this.inputs[0].number == null) {
32 | this.a = null;
33 | } else {
34 | this.a = this.inputs[0].number;
35 | }
36 |
37 | if (this.a != null && !isNaN(this.a)) {
38 | this.bg.classList.add('running');
39 | this.runTimer = Date.now();
40 | this.number = this.a * (Math.PI / 180);
41 | super.run(inputThatTriggered);
42 | } else {
43 | this.runTimer = Date.now();
44 | this.number = null;
45 | super.run(inputThatTriggered);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/classes/nodes/number/DegreesToRadiansProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class DegreesToRadiansProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | }
11 | }
12 |
13 |
14 | renderResult() {
15 | if (this.state.hasA) {
16 | return (
17 |
18 | sin({this.props.node.a}) = {this.props.node.a*(Math.PI/180)}
19 |
20 | )
21 | }
22 | }
23 |
24 |
25 | render() {
26 | return (
27 |
28 |
Degrees to Radians
29 |
30 | {this.renderResult()}
31 | {this.renderName()}
32 | {this.renderRun()}
33 |
34 |
35 | )
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/classes/nodes/number/DivideNumbers.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import DivideNumbersProperties from './DivideNumbersProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class DivideNumbers extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Divide', DivideNumbersProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | new InputNumber(this, 1, 'b', 'hasB'),
13 | ];
14 | this.outputs = [
15 | new OutputNumber(this, 0, 'Result')
16 | ];
17 |
18 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
19 | this.b = typeof settings.b !== 'undefined' ? settings.b : null;
20 | }
21 |
22 |
23 | toJson() {
24 | let json = super.toJson();
25 |
26 | json.settings.a = this.a;
27 | json.settings.b = this.b;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | if (this.inputs[0].number == null) {
35 | this.a = null;
36 | } else {
37 | this.a = this.inputs[0].number;
38 | }
39 |
40 | if (this.inputs[1].number == null) {
41 | this.b = null;
42 | } else {
43 | this.b = this.inputs[1].number;
44 | }
45 |
46 | if (this.a != null && this.b != null && !isNaN(this.a) && !isNaN(this.b)) {
47 | this.bg.classList.add('running');
48 | this.runTimer = Date.now();
49 | this.number = this.a / this.b;
50 | super.run(inputThatTriggered);
51 | } else {
52 | this.runTimer = Date.now();
53 | this.number = null;
54 | super.run(inputThatTriggered);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/classes/nodes/number/DivideNumbersProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class DivideNumbersProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | hasB: props.node.inputs[1].parent ? true : false
11 | }
12 | }
13 |
14 |
15 | renderResult() {
16 | if (this.state.hasA && this.state.hasB) {
17 | return (
18 |
19 | {this.props.node.a} / {this.props.node.b} = {this.props.node.a / this.props.node.b}
20 |
21 | )
22 | }
23 | }
24 |
25 |
26 | render() {
27 | return (
28 |
29 |
Divide Numbers
30 |
31 | {this.renderResult()}
32 | {this.renderName()}
33 | {this.renderRun()}
34 |
35 |
36 | )
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/classes/nodes/number/ExponentNumbers.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import ExponentNumbersProperties from './ExponentNumbersProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class ExponentNumbers extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Exponent', ExponentNumbersProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | new InputNumber(this, 1, 'b', 'hasB'),
13 | ];
14 | this.outputs = [
15 | new OutputNumber(this, 0, 'Result')
16 | ];
17 |
18 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
19 | this.b = typeof settings.b !== 'undefined' ? settings.b : null;
20 | }
21 |
22 |
23 | toJson() {
24 | let json = super.toJson();
25 |
26 | json.settings.a = this.a;
27 | json.settings.b = this.b;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | if (this.inputs[0].number == null) {
35 | this.a = null;
36 | } else {
37 | this.a = this.inputs[0].number;
38 | }
39 |
40 | if (this.inputs[1].number == null) {
41 | this.b = null;
42 | } else {
43 | this.b = this.inputs[1].number;
44 | }
45 |
46 | if (this.a != null && this.b != null && !isNaN(this.a) && !isNaN(this.b)) {
47 | this.bg.classList.add('running');
48 | this.runTimer = Date.now();
49 | this.number = Math.pow(this.a, this.b);
50 | super.run(inputThatTriggered);
51 | } else {
52 | this.runTimer = Date.now();
53 | this.number = null;
54 | super.run(inputThatTriggered);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/classes/nodes/number/ExponentNumbersProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class ExponentNumbersProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | hasB: props.node.inputs[1].parent ? true : false
11 | }
12 | }
13 |
14 |
15 | renderResult() {
16 | if (this.state.hasA && this.state.hasB) {
17 | return (
18 |
19 | {this.props.node.a} ^ {this.props.node.b} = {Math.pow(this.props.node.a, this.props.node.b)}
20 |
21 | )
22 | }
23 | }
24 |
25 |
26 | render() {
27 | return (
28 |
29 |
Exponent of Numbers
30 |
31 | {this.renderResult()}
32 | {this.renderName()}
33 | {this.renderRun()}
34 |
35 |
36 | )
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/classes/nodes/number/Floor.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import FloorProperties from './FloorProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class Floor extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Floor', FloorProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | ];
13 | this.outputs = [
14 | new OutputNumber(this, 0, 'Result')
15 | ];
16 |
17 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | json.settings.a = this.a;
25 |
26 | return json;
27 | }
28 |
29 |
30 | run(inputThatTriggered) {
31 | if (this.inputs[0].number == null) {
32 | this.a = null;
33 | } else {
34 | this.a = this.inputs[0].number;
35 | }
36 |
37 | if (this.a != null && !isNaN(this.a)) {
38 | this.bg.classList.add('running');
39 | this.runTimer = Date.now();
40 | this.number = Math.floor(this.a);
41 | super.run(inputThatTriggered);
42 | } else {
43 | this.runTimer = Date.now();
44 | this.number = null;
45 | super.run(inputThatTriggered);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/classes/nodes/number/FloorProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class FloorProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | }
11 | }
12 |
13 |
14 | renderResult() {
15 | if (this.state.hasA) {
16 | return (
17 |
18 | floor({this.props.node.a}) = {Math.floor(this.props.node.a)}
19 |
20 | )
21 | }
22 | }
23 |
24 |
25 | render() {
26 | return (
27 |
28 |
Floor a Number
29 |
30 | {this.renderResult()}
31 | {this.renderName()}
32 | {this.renderRun()}
33 |
34 |
35 | )
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/classes/nodes/number/GetImageSize.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import GetImageSizeProperties from './GetImageSizeProperties.jsx';
3 | import InputImage from '../InputImage.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class GetImageSize extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Get Image Size', GetImageSizeProperties, settings);
9 |
10 | this.inputs = [
11 | new InputImage(this, 0, 'Input'),
12 | ];
13 | this.outputs = [
14 | new OutputNumber(this, 0, 'Width'),
15 | new OutputNumber(this, 1, 'Height')
16 | ];
17 | }
18 |
19 |
20 | toJson() {
21 | let json = super.toJson();
22 |
23 | return json;
24 | }
25 |
26 |
27 | run(inputThatTriggered) {
28 | if (this.inputs[0].image != null) {
29 | this.bg.classList.add('running');
30 | this.runTimer = Date.now();
31 | this.number = this.inputs[0].image.bitmap.width+' x '+this.inputs[0].image.bitmap.height;
32 | super.run(inputThatTriggered);
33 | } else {
34 | this.runTimer = Date.now();
35 | this.number = null;
36 | super.run(inputThatTriggered);
37 | }
38 | }
39 |
40 |
41 | passToChildren() {
42 | this.outputs[0].connections.forEach(conn => {
43 | if (this.inputs[0].image == null) {
44 | conn.number = null;
45 | } else {
46 | conn.number = this.inputs[0].image.bitmap.width;
47 | }
48 | conn.runNode();
49 | })
50 |
51 | this.outputs[1].connections.forEach(conn => {
52 | if (this.inputs[0].image == null) {
53 | conn.number = null;
54 | } else {
55 | conn.number = this.inputs[0].image.bitmap.height;
56 | }
57 | conn.runNode();
58 | })
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/classes/nodes/number/GetImageSizeProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class GetImageSizeProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Get Image Size
14 |
15 | {this.renderName()}
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/number/Max.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import MaxProperties from './MaxProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class Max extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Max', MaxProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | new InputNumber(this, 1, 'b', 'hasB'),
13 | ];
14 | this.outputs = [
15 | new OutputNumber(this, 0, 'Result')
16 | ];
17 |
18 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
19 | this.b = typeof settings.b !== 'undefined' ? settings.b : null;
20 | }
21 |
22 |
23 | toJson() {
24 | let json = super.toJson();
25 |
26 | json.settings.a = this.a;
27 | json.settings.b = this.b;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | if (this.inputs[0].number == null) {
35 | this.a = null;
36 | } else {
37 | this.a = this.inputs[0].number;
38 | }
39 |
40 | if (this.inputs[1].number == null) {
41 | this.b = null;
42 | } else {
43 | this.b = this.inputs[1].number;
44 | }
45 |
46 | if (this.a != null && this.b != null && !isNaN(this.a) && !isNaN(this.b)) {
47 | this.bg.classList.add('running');
48 | this.runTimer = Date.now();
49 | this.number = Math.max(this.a, this.b);
50 | super.run(inputThatTriggered);
51 | } else {
52 | this.runTimer = Date.now();
53 | this.number = null;
54 | super.run(inputThatTriggered);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/classes/nodes/number/MaxProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class MaxNumbersProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | hasB: props.node.inputs[1].parent ? true : false
11 | }
12 | }
13 |
14 |
15 | renderResult() {
16 | if (this.state.hasA && this.state.hasB) {
17 | return (
18 |
19 | max({this.props.node.a}, {this.props.node.b}) = {Math.max(this.props.node.a, this.props.node.b)}
20 |
21 | )
22 | }
23 | }
24 |
25 |
26 | render() {
27 | return (
28 |
29 |
Maximum of Two Numbers
30 |
31 | {this.renderResult()}
32 | {this.renderName()}
33 | {this.renderRun()}
34 |
35 |
36 | )
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/classes/nodes/number/Min.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import MinProperties from './MinProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class Min extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Min', MinProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | new InputNumber(this, 1, 'b', 'hasB'),
13 | ];
14 | this.outputs = [
15 | new OutputNumber(this, 0, 'Result')
16 | ];
17 |
18 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
19 | this.b = typeof settings.b !== 'undefined' ? settings.b : null;
20 | }
21 |
22 |
23 | toJson() {
24 | let json = super.toJson();
25 |
26 | json.settings.a = this.a;
27 | json.settings.b = this.b;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | if (this.inputs[0].number == null) {
35 | this.a = null;
36 | } else {
37 | this.a = this.inputs[0].number;
38 | }
39 |
40 | if (this.inputs[1].number == null) {
41 | this.b = null;
42 | } else {
43 | this.b = this.inputs[1].number;
44 | }
45 |
46 | if (this.a != null && this.b != null && !isNaN(this.a) && !isNaN(this.b)) {
47 | this.bg.classList.add('running');
48 | this.runTimer = Date.now();
49 | this.number = Math.min(this.a, this.b);
50 | super.run(inputThatTriggered);
51 | } else {
52 | this.runTimer = Date.now();
53 | this.number = null;
54 | super.run(inputThatTriggered);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/classes/nodes/number/MinProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class MinNumbersProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | hasB: props.node.inputs[1].parent ? true : false
11 | }
12 | }
13 |
14 |
15 | renderResult() {
16 | if (this.state.hasA && this.state.hasB) {
17 | return (
18 |
19 | min({this.props.node.a}, {this.props.node.b}) = {Math.min(this.props.node.a, this.props.node.b)}
20 |
21 | )
22 | }
23 | }
24 |
25 |
26 | render() {
27 | return (
28 |
29 |
Minimum of Two Numbers
30 |
31 | {this.renderResult()}
32 | {this.renderName()}
33 | {this.renderRun()}
34 |
35 |
36 | )
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/classes/nodes/number/ModuloNumbers.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import ModuloNumbersProperties from './ModuloNumbersProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class ModuloNumbers extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Mod', ModuloNumbersProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | new InputNumber(this, 1, 'b', 'hasB'),
13 | ];
14 | this.outputs = [
15 | new OutputNumber(this, 0, 'Result')
16 | ];
17 |
18 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
19 | this.b = typeof settings.b !== 'undefined' ? settings.b : null;
20 | }
21 |
22 |
23 | toJson() {
24 | let json = super.toJson();
25 |
26 | json.settings.a = this.a;
27 | json.settings.b = this.b;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | if (this.inputs[0].number == null) {
35 | this.a = null;
36 | } else {
37 | this.a = this.inputs[0].number;
38 | }
39 |
40 | if (this.inputs[1].number == null) {
41 | this.b = null;
42 | } else {
43 | this.b = this.inputs[1].number;
44 | }
45 |
46 | if (this.a != null && this.b != null && !isNaN(this.a) && !isNaN(this.b)) {
47 | this.bg.classList.add('running');
48 | this.runTimer = Date.now();
49 | this.number = this.a % this.b;
50 | super.run(inputThatTriggered);
51 | } else {
52 | this.runTimer = Date.now();
53 | this.number = null;
54 | super.run(inputThatTriggered);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/classes/nodes/number/ModuloNumbersProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class ModuloNumbersProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | hasB: props.node.inputs[1].parent ? true : false
11 | }
12 | }
13 |
14 |
15 | renderResult() {
16 | if (this.state.hasA && this.state.hasB) {
17 | return (
18 |
19 | {this.props.node.a} % {this.props.node.b} = {this.props.node.a % this.props.node.b}
20 |
21 | )
22 | }
23 | }
24 |
25 |
26 | render() {
27 | return (
28 |
29 |
Modulo Numbers
30 |
31 | {this.renderResult()}
32 | {this.renderName()}
33 | {this.renderRun()}
34 |
35 |
36 | )
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/classes/nodes/number/MultiplyNumbers.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import MultiplyNumbersProperties from './MultiplyNumbersProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class MultiplyNumbers extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Multiply', MultiplyNumbersProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | new InputNumber(this, 1, 'b', 'hasB'),
13 | ];
14 | this.outputs = [
15 | new OutputNumber(this, 0, 'Result')
16 | ];
17 |
18 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
19 | this.b = typeof settings.b !== 'undefined' ? settings.b : null;
20 | }
21 |
22 |
23 | toJson() {
24 | let json = super.toJson();
25 |
26 | json.settings.a = this.a;
27 | json.settings.b = this.b;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | if (this.inputs[0].number == null) {
35 | this.a = null;
36 | } else {
37 | this.a = this.inputs[0].number;
38 | }
39 |
40 | if (this.inputs[1].number == null) {
41 | this.b = null;
42 | } else {
43 | this.b = this.inputs[1].number;
44 | }
45 |
46 | if (this.a != null && this.b != null && !isNaN(this.a) && !isNaN(this.b)) {
47 | this.bg.classList.add('running');
48 | this.runTimer = Date.now();
49 | this.number = this.a * this.b;
50 | super.run(inputThatTriggered);
51 | } else {
52 | this.runTimer = Date.now();
53 | this.number = null;
54 | super.run(inputThatTriggered);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/classes/nodes/number/MultiplyNumbersProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class MultiplyNumbersProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | hasB: props.node.inputs[1].parent ? true : false
11 | }
12 | }
13 |
14 |
15 | renderResult() {
16 | if (this.state.hasA && this.state.hasB) {
17 | return (
18 |
19 | {this.props.node.a} * {this.props.node.b} = {this.props.node.a * this.props.node.b}
20 |
21 | )
22 | }
23 | }
24 |
25 |
26 | render() {
27 | return (
28 |
29 |
Multiply Numbers
30 |
31 | {this.renderResult()}
32 | {this.renderName()}
33 | {this.renderRun()}
34 |
35 |
36 | )
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/classes/nodes/number/Number.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import NumberProperties from './NumberProperties.jsx';
3 | import OutputNumber from '../OutputNumber.js';
4 |
5 | export default class Number extends NodeNumber {
6 | constructor(className, graph, x, y, settings) {
7 | super(className, graph, x, y, 'Number', NumberProperties, settings);
8 |
9 | this.inputs = [];
10 | this.outputs = [
11 | new OutputNumber(this, 0, 'Output')
12 | ];
13 |
14 | this.number = typeof settings.number !== 'undefined' ? settings.number : 1;
15 | }
16 |
17 |
18 | toJson() {
19 | let json = super.toJson();
20 |
21 | json.settings.number = this.number;
22 |
23 | return json;
24 | }
25 |
26 |
27 | run(inputThatTriggered) {
28 | this.bg.classList.add('running');
29 | this.runTimer = Date.now();
30 | super.run(inputThatTriggered);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/classes/nodes/number/NumberProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class NumberProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
Number Input
11 |
12 |
13 |
14 | {this.renderName()}
15 | {this.renderRun()}
16 |
17 |
18 | )
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/classes/nodes/number/Pi.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import PiProperties from './PiProperties.jsx';
3 | import OutputNumber from '../OutputNumber.js';
4 |
5 | export default class Pi extends NodeNumber {
6 | constructor(className, graph, x, y, settings) {
7 | super(className, graph, x, y, 'Pi', PiProperties, settings);
8 |
9 | this.inputs = [];
10 | this.outputs = [
11 | new OutputNumber(this, 0, 'Output')
12 | ];
13 |
14 | this.number = Math.PI;
15 | }
16 |
17 |
18 | toJson() {
19 | let json = super.toJson();
20 |
21 | json.settings.number = this.number;
22 |
23 | return json;
24 | }
25 |
26 |
27 | run(inputThatTriggered) {
28 | this.bg.classList.add('running');
29 | this.runTimer = Date.now();
30 | super.run(inputThatTriggered);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/classes/nodes/number/PiProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class PiProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Pi
14 |
15 |
16 | {this.props.node.number}
17 | {this.renderName()}
18 | {this.renderRun()}
19 |
20 |
21 | )
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/classes/nodes/number/RadiansToDegrees.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import RadiansToDegreesProperties from './RadiansToDegreesProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class RadiansToDegrees extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Radians to Degrees', RadiansToDegreesProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | ];
13 | this.outputs = [
14 | new OutputNumber(this, 0, 'Result')
15 | ];
16 |
17 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | json.settings.a = this.a;
25 |
26 | return json;
27 | }
28 |
29 |
30 | run(inputThatTriggered) {
31 | if (this.inputs[0].number == null) {
32 | this.a = null;
33 | } else {
34 | this.a = this.inputs[0].number;
35 | }
36 |
37 | if (this.a != null && !isNaN(this.a)) {
38 | this.bg.classList.add('running');
39 | this.runTimer = Date.now();
40 | this.number = this.a * (180 / Math.PI);
41 | super.run(inputThatTriggered);
42 | } else {
43 | this.runTimer = Date.now();
44 | this.number = null;
45 | super.run(inputThatTriggered);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/classes/nodes/number/RadiansToDegreesProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class DegreesToRadiansProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | }
11 | }
12 |
13 |
14 | renderResult() {
15 | if (this.state.hasA) {
16 | return (
17 |
18 | sin({this.props.node.a}) = {this.props.node.a * (180 / Math.PI)}
19 |
20 | )
21 | }
22 | }
23 |
24 |
25 | render() {
26 | return (
27 |
28 |
Radians to Degrees
29 |
30 | {this.renderResult()}
31 | {this.renderName()}
32 | {this.renderRun()}
33 |
34 |
35 | )
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/classes/nodes/number/RandomNumber.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import RandomNumberProperties from './RandomNumberProperties.jsx';
3 | import OutputNumber from '../OutputNumber.js';
4 | import InputNumber from '../InputNumber.js';
5 |
6 | export default class RandomNumber extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Random Number', RandomNumberProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'Regenerate')
12 | ];
13 | this.outputs = [
14 | new OutputNumber(this, 0, 'Output')
15 | ];
16 |
17 | this.number = Math.random();
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | json.number = this.number;
25 |
26 | return json;
27 | }
28 |
29 |
30 | run(inputThatTriggered) {
31 | this.bg.classList.add('running');
32 | this.runTimer = Date.now();
33 | this.number = Math.random();
34 | super.run(inputThatTriggered);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/classes/nodes/number/RandomNumberProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class RandomNumberProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.run = this.run.bind(this);
9 | }
10 |
11 |
12 | run(event) {
13 | this.props.node.run(null);
14 | }
15 |
16 |
17 | render() {
18 | return (
19 |
20 |
Random Number
21 |
22 |
23 | Random number between 0 and 1.
24 |
25 | {this.run(event)}}>Regenerate
26 |
27 | When the regenerate input changes this node will generate a new random number.
28 |
29 |
30 | Regenerate input is optional.
31 | {this.renderName()}
32 | {this.renderRun()}
33 |
34 |
35 | )
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/classes/nodes/number/Round.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import RoundProperties from './RoundProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class Round extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Round', RoundProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | ];
13 | this.outputs = [
14 | new OutputNumber(this, 0, 'Result')
15 | ];
16 |
17 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | json.settings.a = this.a;
25 |
26 | return json;
27 | }
28 |
29 |
30 | run(inputThatTriggered) {
31 | if (this.inputs[0].number == null) {
32 | this.a = null;
33 | } else {
34 | this.a = this.inputs[0].number;
35 | }
36 |
37 | if (this.a != null && !isNaN(this.a)) {
38 | this.bg.classList.add('running');
39 | this.runTimer = Date.now();
40 | this.number = Math.round(this.a);
41 | super.run(inputThatTriggered);
42 | } else {
43 | this.runTimer = Date.now();
44 | this.number = null;
45 | super.run(inputThatTriggered);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/classes/nodes/number/RoundProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class RoundProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | }
11 | }
12 |
13 |
14 | renderResult() {
15 | if (this.state.hasA) {
16 | return (
17 |
18 | round({this.props.node.a}) = {Math.round(this.props.node.a)}
19 |
20 | )
21 | }
22 | }
23 |
24 |
25 | render() {
26 | return (
27 |
28 |
Round a Number
29 |
30 | {this.renderResult()}
31 | {this.renderName()}
32 | {this.renderRun()}
33 |
34 |
35 | )
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/classes/nodes/number/Sin.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import SinProperties from './SinProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class Sin extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Sine', SinProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | ];
13 | this.outputs = [
14 | new OutputNumber(this, 0, 'Result')
15 | ];
16 |
17 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | json.settings.a = this.a;
25 |
26 | return json;
27 | }
28 |
29 |
30 | run(inputThatTriggered) {
31 | if (this.inputs[0].number == null) {
32 | this.a = null;
33 | } else {
34 | this.a = this.inputs[0].number;
35 | }
36 |
37 | if (this.a != null && !isNaN(this.a)) {
38 | this.bg.classList.add('running');
39 | this.runTimer = Date.now();
40 | this.number = Math.sin(this.a);
41 | super.run(inputThatTriggered);
42 | } else {
43 | this.runTimer = Date.now();
44 | this.number = null;
45 | super.run(inputThatTriggered);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/classes/nodes/number/SinProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class SinProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | }
11 | }
12 |
13 |
14 | renderResult() {
15 | if (this.state.hasA) {
16 | return (
17 |
18 | sin({this.props.node.a}) = {Math.sin(this.props.node.a)}
19 |
20 | )
21 | }
22 | }
23 |
24 |
25 | render() {
26 | return (
27 |
28 |
Sine of a Number
29 |
30 | {this.renderResult()}
31 | {this.renderName()}
32 | {this.renderRun()}
33 |
34 |
35 | )
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/classes/nodes/number/Slider.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import SliderProperties from './SliderProperties.jsx';
3 | import OutputNumber from '../OutputNumber.js';
4 | import InputNumber from '../InputNumber.js';
5 |
6 | export default class Slider extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Slider', SliderProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'Min', 'hasMinInput'),
12 | new InputNumber(this, 1, 'Max', 'hasMaxInput'),
13 | new InputNumber(this, 2, 'Step', 'hasStepInput'),
14 | ];
15 | this.outputs = [
16 | new OutputNumber(this, 0, 'Output')
17 | ];
18 |
19 | this.number = typeof settings.number !== 'undefined' ? settings.number : 1;
20 | this.min = typeof settings.min !== 'undefined' ? settings.min : 0;
21 | this.max = typeof settings.max !== 'undefined' ? settings.max : 10;
22 | this.step = typeof settings.max !== 'undefined' ? settings.step : 0.01;
23 | }
24 |
25 |
26 | toJson() {
27 | let json = super.toJson();
28 |
29 | json.settings.number = this.number;
30 | json.settings.min = this.min;
31 | json.settings.max = this.max;
32 | json.settings.step = this.step;
33 |
34 | return json;
35 | }
36 |
37 |
38 | run(inputThatTriggered) {
39 | this.bg.classList.add('running');
40 | this.runTimer = Date.now();
41 |
42 | if (this.inputs[0].number != null) {
43 | this.min = this.inputs[0].number;
44 | }
45 |
46 | if (this.inputs[1].number != null) {
47 | this.max = this.inputs[1].number;
48 | }
49 |
50 | if (this.inputs[2].number != null) {
51 | this.step = this.inputs[2].number;
52 | }
53 |
54 | super.run(inputThatTriggered);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/classes/nodes/number/SquareRoot.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import SquareRootProperties from './SquareRootProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class SquareRoot extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'SquareRoot', SquareRootProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | ];
13 | this.outputs = [
14 | new OutputNumber(this, 0, 'Result')
15 | ];
16 |
17 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | json.settings.a = this.a;
25 |
26 | return json;
27 | }
28 |
29 |
30 | run(inputThatTriggered) {
31 | if (this.inputs[0].number == null) {
32 | this.a = null;
33 | } else {
34 | this.a = this.inputs[0].number;
35 | }
36 |
37 | if (this.a != null && !isNaN(this.a)) {
38 | this.bg.classList.add('running');
39 | this.runTimer = Date.now();
40 | this.number = Math.sqrt(this.a);
41 | super.run(inputThatTriggered);
42 | } else {
43 | this.runTimer = Date.now();
44 | this.number = null;
45 | super.run(inputThatTriggered);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/classes/nodes/number/SquareRootProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class SquareRootProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | }
11 | }
12 |
13 |
14 | renderResult() {
15 | if (this.state.hasA) {
16 | return (
17 |
18 | sqrt({this.props.node.a}) = {Math.sqrt(this.props.node.a)}
19 |
20 | )
21 | }
22 | }
23 |
24 |
25 | render() {
26 | return (
27 |
28 |
SquareRoot of a Number
29 |
30 | {this.renderResult()}
31 | {this.renderName()}
32 | {this.renderRun()}
33 |
34 |
35 | )
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/classes/nodes/number/SubtractNumbers.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import SubtractNumbersProperties from './SubtractNumbersProperties.jsx';
3 | import InputNumber from '../InputNumber.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class SubtractNumbers extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Subtract', SubtractNumbersProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'a', 'hasA'),
12 | new InputNumber(this, 1, 'b', 'hasB'),
13 | ];
14 | this.outputs = [
15 | new OutputNumber(this, 0, 'Result')
16 | ];
17 |
18 | this.a = typeof settings.a !== 'undefined' ? settings.a : null;
19 | this.b = typeof settings.b !== 'undefined' ? settings.b : null;
20 | }
21 |
22 |
23 | toJson() {
24 | let json = super.toJson();
25 |
26 | json.settings.a = this.a;
27 | json.settings.b = this.b;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | if (this.inputs[0].number == null) {
35 | this.a = null;
36 | } else {
37 | this.a = this.inputs[0].number;
38 | }
39 |
40 | if (this.inputs[1].number == null) {
41 | this.b = null;
42 | } else {
43 | this.b = this.inputs[1].number;
44 | }
45 |
46 | if (this.a != null && this.b != null && !isNaN(this.a) && !isNaN(this.b)) {
47 | this.bg.classList.add('running');
48 | this.runTimer = Date.now();
49 | this.number = this.a - this.b;
50 | super.run(inputThatTriggered);
51 | } else {
52 | this.runTimer = Date.now();
53 | this.number = null;
54 | super.run(inputThatTriggered);
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/classes/nodes/number/SubtractNumbersProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class SubtractNumbersProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 |
8 | this.state = {
9 | hasA: props.node.inputs[0].parent ? true : false,
10 | hasB: props.node.inputs[1].parent ? true : false
11 | }
12 | }
13 |
14 |
15 | renderResult() {
16 | if (this.state.hasA && this.state.hasB) {
17 | return (
18 |
19 | {this.props.node.a} - {this.props.node.b} = {this.props.node.a - this.props.node.b}
20 |
21 | )
22 | }
23 | }
24 |
25 |
26 | render() {
27 | return (
28 |
29 |
Subtract Numbers
30 |
31 | {this.renderResult()}
32 | {this.renderName()}
33 | {this.renderRun()}
34 |
35 |
36 | )
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/classes/nodes/strings/Length.js:
--------------------------------------------------------------------------------
1 | import NodeNumber from '../NodeNumber.js';
2 | import LengthProperties from './LengthProperties.jsx';
3 | import InputString from '../InputString.js';
4 | import OutputNumber from '../OutputNumber.js';
5 |
6 | export default class Length extends NodeNumber {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'String Length', LengthProperties, settings);
9 |
10 | this.inputs = [
11 | new InputString(this, 0, 'string', 'String'),
12 | ];
13 | this.outputs = [
14 | new OutputNumber(this, 0, 'Result')
15 | ];
16 |
17 | this.string = typeof settings.string !== 'undefined' ? settings.string : null;
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | json.settings.string = this.string;
25 |
26 | return json;
27 | }
28 |
29 |
30 | run(inputThatTriggered) {
31 | let str = this.string;
32 | if (this.inputs[0].string != null) {
33 | str = this.inputs[0].string;
34 | }
35 |
36 | if (str != null) {
37 | this.bg.classList.add('running');
38 | this.runTimer = Date.now();
39 | this.number = str.length;
40 | super.run(inputThatTriggered);
41 | } else {
42 | this.runTimer = Date.now();
43 | this.number = null;
44 | super.run(inputThatTriggered);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/classes/nodes/strings/LengthProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class LengthProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Length a String
14 |
15 | {this.renderName()}
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/strings/NumberToString.js:
--------------------------------------------------------------------------------
1 | import NodeString from '../NodeString.js';
2 | import NumberToStringProperties from './NumberToStringProperties.jsx';
3 | import OutputString from '../OutputString.js';
4 | import InputNumber from '../InputNumber.js';
5 |
6 | export default class NumberToString extends NodeString {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Number to String', NumberToStringProperties, settings);
9 |
10 | this.inputs = [
11 | new InputNumber(this, 0, 'Number', 'hasNumberInput')
12 | ];
13 | this.outputs = [
14 | new OutputString(this, 0, 'Output')
15 | ];
16 |
17 | this.string = typeof settings.string !== 'undefined' ? settings.string : null;
18 | }
19 |
20 |
21 | toJson() {
22 | let json = super.toJson();
23 |
24 | json.settings.string = this.string;
25 |
26 | return json;
27 | }
28 |
29 |
30 | run(inputThatTriggered) {
31 | let num = null;
32 |
33 | if (this.inputs[0].number != null) {
34 | num = this.inputs[0].number;
35 | }
36 |
37 | this.bg.classList.add('running');
38 | this.runTimer = Date.now();
39 |
40 | if (num != null) {
41 | this.string = num.toString();
42 | } else {
43 | this.string = null;
44 | }
45 |
46 | super.run(inputThatTriggered);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/classes/nodes/strings/NumberToStringProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class NumberToStringProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Number to String
14 |
15 | {this.renderName()}
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/strings/StringInput.js:
--------------------------------------------------------------------------------
1 | import NodeString from '../NodeString.js';
2 | import StringInputProperties from './StringInputProperties.jsx';
3 | import OutputString from '../OutputString.js';
4 |
5 | export default class StringInput extends NodeString {
6 | constructor(className, graph, x, y, settings) {
7 | super(className, graph, x, y, 'String Input', StringInputProperties, settings);
8 |
9 | this.inputs = [];
10 | this.outputs = [
11 | new OutputString(this, 0, 'Output')
12 | ];
13 |
14 | this.string = typeof settings.string !== 'undefined' ? settings.string : 'Nimp';
15 | }
16 |
17 |
18 | toJson() {
19 | let json = super.toJson();
20 |
21 | json.settings.string = this.string;
22 |
23 | return json;
24 | }
25 |
26 |
27 | run(inputThatTriggered) {
28 | this.bg.classList.add('running');
29 | this.runTimer = Date.now();
30 | super.run(inputThatTriggered);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/classes/nodes/strings/StringInputProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class StringInputProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | stringChange(event) {
11 | const elm = document.getElementById('stringInput');
12 | this.props.node.string = elm.value;
13 | this.props.node.run(null);
14 | }
15 |
16 |
17 | render() {
18 | return (
19 |
20 |
String Input
21 |
22 |
23 | String Input
24 | {this.stringChange(event);}} />
25 | {this.renderName()}
26 | {this.renderRun()}
27 |
28 |
29 | )
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/classes/nodes/transform/CropProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class CropProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
Crop
11 |
12 |
13 |
14 |
15 |
16 | {this.renderRun()}
17 |
18 |
19 | )
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/classes/nodes/transform/Displace.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import DisplaceProperties from './DisplaceProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 | import InputNumber from '../InputNumber.js';
6 |
7 | export default class Displace extends NodeImage {
8 | constructor(className, graph, x, y, settings) {
9 | super(className, graph, x, y, 'Displace', DisplaceProperties, settings);
10 |
11 | this.inputs = [
12 | new InputImage(this, 0, 'Input'),
13 | new InputImage(this, 1, 'Map'),
14 | new InputNumber(this, 2, 'Offset', 'hasOffsetInput')
15 | ];
16 | this.outputs = [
17 | new OutputImage(this, 0, 'Output')
18 | ];
19 |
20 | this.offset = typeof settings.offset !== 'undefined' ? settings.offset : 20;
21 | }
22 |
23 |
24 | toJson() {
25 | let json = super.toJson();
26 |
27 | json.settings.offset = this.offset;
28 |
29 | return json;
30 | }
31 |
32 |
33 | run(inputThatTriggered) {
34 | if (this.inputs[0].image && this.inputs[1].image) {
35 | this.bg.classList.add('running');
36 | this.runTimer = Date.now();
37 |
38 | let offset = this.offset;
39 |
40 | if (this.inputs[2].number != null) {
41 | offset = this.inputs[2].number;
42 | }
43 |
44 | if (this.isInsideALoop) {
45 | let image = this.inputs[0].image.clone();
46 | image.displace(this.inputs[1].image, offset);
47 | this.image = image;
48 | super.run(inputThatTriggered);
49 | } else {
50 | Jimp.read(this.inputs[0].image).then(image => {
51 | image.displace(this.inputs[1].image, offset, (error, image) => {
52 | if (error) {
53 | console.log(error);
54 | } else {
55 | this.image = image;
56 | super.run(inputThatTriggered);
57 | }
58 | })
59 | })
60 | }
61 |
62 | } else {
63 | this.runTimer = Date.now();
64 | this.image = null;
65 | super.run(inputThatTriggered);
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/classes/nodes/transform/DisplaceProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 | import PropertiesInputNumber from '../../../components/PropertiesInputNumber.jsx';
3 |
4 |
5 | export default class DisplaceProperties extends Properties {
6 |
7 | render() {
8 | return (
9 |
10 |
Displace
11 |
12 | Displace the image pixels based on the provided displacement map.
13 |
14 |
15 | {this.renderRun()}
16 |
17 |
18 | )
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/classes/nodes/transform/FlipHorizontal.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import FlipHorizontalProperties from './FlipHorizontalProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 |
6 | export default class FlipHorizontal extends NodeImage {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Flip Horizontally', FlipHorizontalProperties, settings);
9 |
10 | this.inputs = [
11 | new InputImage(this, 0, 'Input')
12 | ];
13 | this.outputs = [
14 | new OutputImage(this, 0, 'Output')
15 | ];
16 | }
17 |
18 |
19 | run(inputThatTriggered) {
20 | if (this.inputs[0].image) {
21 | this.bg.classList.add('running');
22 | this.runTimer = Date.now();
23 |
24 | if (this.isInsideALoop) {
25 | const image = this.inputs[0].image.clone();
26 | image.flip(true, false);
27 | this.image = image;
28 | super.run(inputThatTriggered);
29 | } else {
30 | Jimp.read(this.inputs[0].image).then(image => {
31 | image.flip(true, false, (error, image) => {
32 | this.image = image;
33 | super.run(inputThatTriggered);
34 | });
35 | })
36 | }
37 |
38 | } else {
39 | this.runTimer = Date.now();
40 | this.image = null;
41 | super.run(inputThatTriggered);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/classes/nodes/transform/FlipHorizontalProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class FlipHorizontalProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Flip Horizontally
14 |
15 | {this.renderRun()}
16 |
17 |
18 | )
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/classes/nodes/transform/FlipVertical.js:
--------------------------------------------------------------------------------
1 | import NodeImage from '../NodeImage.js';
2 | import FlipVerticalProperties from './FlipVerticalProperties.jsx';
3 | import OutputImage from '../OutputImage.js';
4 | import InputImage from '../InputImage.js';
5 |
6 | export default class FlipVertical extends NodeImage {
7 | constructor(className, graph, x, y, settings) {
8 | super(className, graph, x, y, 'Flip Vertically', FlipVerticalProperties, settings);
9 |
10 | this.inputs = [
11 | new InputImage(this, 0, 'Input')
12 | ];
13 | this.outputs = [
14 | new OutputImage(this, 0, 'Output')
15 | ];
16 | }
17 |
18 |
19 | run(inputThatTriggered) {
20 | if (this.inputs[0].image) {
21 | this.bg.classList.add('running');
22 | this.runTimer = Date.now();
23 |
24 | if (this.isInsideALoop) {
25 | const image = this.inputs[0].image.clone();
26 | image.flip(false, true);
27 | this.image = image;
28 | super.run(inputThatTriggered);
29 | } else {
30 | Jimp.read(this.inputs[0].image).then(image => {
31 | image.flip(false, true, (error, image) => {
32 | this.image = image;
33 | super.run(inputThatTriggered);
34 | });
35 | })
36 | }
37 |
38 | } else {
39 | this.runTimer = Date.now();
40 | this.image = null;
41 | super.run(inputThatTriggered);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/classes/nodes/transform/FlipVerticalProperties.jsx:
--------------------------------------------------------------------------------
1 | import Properties from '../Properties.js';
2 |
3 | export default class FlipVerticalProperties extends Properties {
4 |
5 | constructor(props) {
6 | super(props);
7 | }
8 |
9 |
10 | render() {
11 | return (
12 |
13 |
Flip Vertically
14 |
15 | {this.renderRun()}
16 |
17 |
18 | )
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/components/JsonView.jsx:
--------------------------------------------------------------------------------
1 | import TopBar from '../components/TopBar.jsx';
2 | import Head from 'next/head';
3 | import React from 'react';
4 |
5 |
6 | export default class JsonView extends React.Component {
7 | render() {
8 |
9 | return (
10 |
11 |
12 |
13 |
14 |
Back to Graph
15 |
16 |
{JSON.stringify(this.props.graphToLoad.graph, null, 2) }
17 |
18 |
19 |
20 |
25 |
26 | )
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/deploy.bat:
--------------------------------------------------------------------------------
1 | docker login registry.gitlab.com -u danphi
2 | docker build -t registry.gitlab.com/danphi/nimp --platform linux/amd64 .
3 | docker push registry.gitlab.com/danphi/nimp
4 | ssh dan@host.winston.net "cd ~/server; docker compose pull; docker compose up -d"
--------------------------------------------------------------------------------
/deploy.sh:
--------------------------------------------------------------------------------
1 | docker login registry.gitlab.com -u danphi
2 | docker build -t registry.gitlab.com/danphi/nimp --platform linux/amd64 .
3 | docker push registry.gitlab.com/danphi/nimp
4 | ssh dan@host.winston.net "cd ~/server; docker compose pull; docker compose up -d"
5 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | const withCSS = require('@zeit/next-css')
2 |
3 | module.exports = withCSS({
4 | publicRuntimeConfig: {}
5 | })
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Nimp",
3 | "version": "0.1.0",
4 | "description": "Node-based image manipulation program.",
5 | "main": "index.js",
6 | "scripts": {
7 | "next": "next dev",
8 | "dev": "cross-env API_URL=http://localhost:3000 MONGO_URL=mongodb://localhost NODE_ENV=development nodemon server/index.js --watch server",
9 | "build": "next build",
10 | "start": "NODE_ENV=production node server/index.js"
11 | },
12 | "author": "Dan",
13 | "license": "MIT",
14 | "dependencies": {
15 | "@zeit/next-css": "^1.0.1",
16 | "bcryptjs": "^2.4.3",
17 | "body-parser": "^1.19.0",
18 | "bson-objectid": "^1.3.0",
19 | "connect-mongodb-session": "^3.1.1",
20 | "copy-to-clipboard": "^3.2.0",
21 | "express": "^4.17.1",
22 | "express-session": "^1.17.0",
23 | "isomorphic-unfetch": "^3.0.0",
24 | "jimp": "0.8.5",
25 | "lodash.debounce": "^4.0.8",
26 | "mongodb": "^3.3.3",
27 | "next": "^13.3.0",
28 | "normalize.css": "^8.0.1",
29 | "react": "^18.2.0",
30 | "react-dom": "^18.2.0",
31 | "simplex-noise": "^2.4.0",
32 | "tinycolor2": "^1.4.1",
33 | "worley-noise": "^2.0.1"
34 | },
35 | "devDependencies": {
36 | "cross-env": "^6.0.3",
37 | "nodemon": "^2.0.21"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/pages/g/[graphId].js:
--------------------------------------------------------------------------------
1 | import GraphView from '../../components/GraphView.jsx';
2 | import Head from 'next/head';
3 | import MainLayout from '../../layouts/MainLayout.js';
4 | import React from 'react';
5 |
6 | export default class G extends React.Component {
7 | static async getInitialProps({req, res, query}) {
8 | const user = req && req.session && req.session.user ? req.session.user : null;
9 |
10 | let graph = null;
11 | if (query.graphId) {
12 | let body = {graphId: query.graphId, userId: null};
13 | if (user) {
14 | body.userId = user._id;
15 | }
16 |
17 | const result = await fetch(process.env.API_URL + '/api/graph', {
18 | method: 'post',
19 | headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' },
20 | body: JSON.stringify(body)
21 | });
22 |
23 | if (result.status == 200) {
24 | graph = await result.json();
25 | } else {
26 | if (result.status == 404) {
27 | res.statusCode = 404;
28 | res.end('Graph not found with this id.');
29 | return;
30 | } else if (result.status == 401) {
31 | res.statusCode = 401;
32 | res.end('Graph is private.');
33 | return;
34 | } else {
35 | res.statusCode = 500;
36 | res.end('Invalid graph id.');
37 | return;
38 | }
39 | }
40 | }
41 |
42 | return {user:user, graph:graph};
43 | }
44 |
45 | render() {
46 | return (
47 |
48 | {this.props.graph && (
49 |
50 | {this.props.graph.title} - Nimp
51 |
52 |
53 | )}
54 |
55 |
56 | )
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/pages/g/[graphId]/[slug].js:
--------------------------------------------------------------------------------
1 | import GraphView from '../../../components/GraphView.jsx';
2 | import Head from 'next/head';
3 | import MainLayout from '../../../layouts/MainLayout.js';
4 | import React from 'react';
5 |
6 | export default class Slug extends React.Component {
7 | static async getInitialProps({req, res, query}) {
8 | const user = req && req.session && req.session.user ? req.session.user : null;
9 |
10 | let graph = null;
11 | if (query.graphId) {
12 | let body = {graphId: query.graphId, userId: null};
13 | if (user) {
14 | body.userId = user._id;
15 | }
16 |
17 | const result = await fetch(process.env.API_URL + '/api/graph', {
18 | method: 'post',
19 | headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' },
20 | body: JSON.stringify(body)
21 | });
22 |
23 | if (result.status == 200) {
24 | graph = await result.json();
25 | } else {
26 | if (result.status == 404) {
27 | res.statusCode = 404;
28 | res.end('Graph not found with this id.');
29 | return;
30 | } else if (result.status == 401) {
31 | res.statusCode = 401;
32 | res.end('Graph is private.');
33 | return;
34 | } else {
35 | res.statusCode = 500;
36 | res.end('Invalid graph id.');
37 | return;
38 | }
39 | }
40 | }
41 |
42 | return {user:user, graph:graph};
43 | }
44 |
45 | render() {
46 | return (
47 |
48 | {this.props.graph && (
49 |
50 | {this.props.graph.title} - Nimp
51 |
52 |
53 | )}
54 |
55 |
56 | )
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/pages/graphs.jsx:
--------------------------------------------------------------------------------
1 | import MainLayout from '../layouts/MainLayout.js';
2 | import TopBar from '../components/TopBar.jsx';
3 | import fetch from 'isomorphic-unfetch'
4 | import GraphThumbs from '../components/GraphThumbs.jsx';
5 | import React from 'react';
6 |
7 |
8 | export default class Graphs extends React.Component {
9 |
10 | static async getInitialProps({req, query}) {
11 | const user = req && req.session && req.session.user ? req.session.user : null;
12 |
13 | let graphs = [];
14 |
15 | const result = await fetch(process.env.API_URL + '/api/graphs', {
16 | method: 'get',
17 | headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' }
18 | });
19 |
20 | if (result.status == 200) {
21 | graphs = await result.json();
22 | }
23 |
24 | return {user:user, graphs:graphs};
25 | }
26 |
27 |
28 | constructor(props) {
29 | super(props);
30 | }
31 |
32 |
33 | render() {
34 | return (
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
48 |
49 | )
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/pages/index.js:
--------------------------------------------------------------------------------
1 | import GraphView from '../components/GraphView.jsx';
2 | import MainLayout from '../layouts/MainLayout.js';
3 | import React from 'react';
4 |
5 | export default class Index extends React.Component {
6 | static async getInitialProps({req, query}) {
7 | const user = req && req.session && req.session.user ? req.session.user : null;
8 | return {user:user, graph:null};
9 | }
10 |
11 | render() {
12 | return (
13 |
14 |
15 |
16 | )
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/pages/json/[graphId].js:
--------------------------------------------------------------------------------
1 | import JsonView from '../../components/JsonView.jsx';
2 | import Head from 'next/head';
3 | import MainLayout from '../../layouts/MainLayout.js';
4 | import React from 'react';
5 |
6 |
7 | export default class Json extends React.Component {
8 | static async getInitialProps({req, res, query}) {
9 | const user = req && req.session && req.session.user ? req.session.user : null;
10 |
11 | let graph = null;
12 | if (query.graphId) {
13 | let body = {graphId: query.graphId, userId: null};
14 | if (user) {
15 | body.userId = user._id;
16 | }
17 |
18 | const result = await fetch(process.env.API_URL + '/api/graph', {
19 | method: 'post',
20 | headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' },
21 | body: JSON.stringify(body)
22 | });
23 |
24 | if (result.status == 200) {
25 | graph = await result.json();
26 | } else {
27 | if (result.status == 404) {
28 | res.statusCode = 404;
29 | res.end('Graph not found with this id.');
30 | return;
31 | } else if (result.status == 401) {
32 | res.statusCode = 401;
33 | res.end('Graph is private.');
34 | return;
35 | } else {
36 | res.statusCode = 500;
37 | res.end('Invalid graph id.');
38 | return;
39 | }
40 | }
41 | }
42 |
43 | return {user:user, graph:graph};
44 | }
45 |
46 | render() {
47 | return (
48 |
49 | {this.props.graph && (
50 |
51 | {this.props.graph.title} - Nimp
52 |
53 |
54 | )}
55 |
56 |
57 | )
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/pages/json/[graphId]/[slug].js:
--------------------------------------------------------------------------------
1 | import JsonView from '../../../components/JsonView.jsx';
2 | import Head from 'next/head';
3 | import MainLayout from '../../../layouts/MainLayout.js';
4 | import React from 'react';
5 |
6 |
7 | export default class JsonSlug extends React.Component {
8 | static async getInitialProps({req, res, query}) {
9 | const user = req && req.session && req.session.user ? req.session.user : null;
10 |
11 | let graph = null;
12 | if (query.graphId) {
13 | let body = {graphId: query.graphId, userId: null};
14 | if (user) {
15 | body.userId = user._id;
16 | }
17 |
18 | const result = await fetch(process.env.API_URL + '/api/graph', {
19 | method: 'post',
20 | headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' },
21 | body: JSON.stringify(body)
22 | });
23 |
24 | if (result.status == 200) {
25 | graph = await result.json();
26 | } else {
27 | if (result.status == 404) {
28 | res.statusCode = 404;
29 | res.end('Graph not found with this id.');
30 | return;
31 | } else if (result.status == 401) {
32 | res.statusCode = 401;
33 | res.end('Graph is private.');
34 | return;
35 | } else {
36 | res.statusCode = 500;
37 | res.end('Invalid graph id.');
38 | return;
39 | }
40 | }
41 | }
42 |
43 | return {user:user, graph:graph};
44 | }
45 |
46 | render() {
47 | return (
48 |
49 | {this.props.graph && (
50 |
51 | {this.props.graph.title} - Nimp
52 |
53 |
54 | )}
55 |
56 |
57 | )
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/pages/logout.jsx:
--------------------------------------------------------------------------------
1 | import fetch from 'isomorphic-unfetch';
2 | import MainLayout from '../layouts/MainLayout.js';
3 | import React from 'react';
4 |
5 | export default class Logout extends React.Component {
6 |
7 | static async getInitialProps({req, query}) {
8 | const user = req && req.session && req.session.user ? req.session.user : null;
9 | return {user:user};
10 | }
11 |
12 |
13 | componentDidMount() {
14 | fetch('/api/logout', {
15 | method: 'get',
16 | headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json'}
17 | }).then(result => {
18 | window.location.href = '/';
19 | })
20 | }
21 |
22 |
23 | render() {
24 | return (
25 |
26 |
27 | Logging out...
28 |
29 |
30 | )
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/pages/u/[userId].js:
--------------------------------------------------------------------------------
1 | import MainLayout from '../../layouts/MainLayout.js';
2 | import TopBar from '../../components/TopBar.jsx';
3 | import fetch from 'isomorphic-unfetch'
4 | import GraphThumbs from '../../components/GraphThumbs.jsx';
5 | import React from 'react';
6 |
7 |
8 | export default class UserGraphs extends React.Component {
9 |
10 | static async getInitialProps({req, query}) {
11 | const user = req && req.session && req.session.user ? req.session.user : null;
12 |
13 | let graphs = [];
14 |
15 | let isUser = false;
16 | if (user && user._id == query.userId) {
17 | isUser = true;
18 | }
19 |
20 | const result = await fetch(process.env.API_URL + '/api/usergraphs', {
21 | method: 'post',
22 | headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' },
23 | body: JSON.stringify({userId:query.userId, isUser:isUser})
24 | });
25 |
26 | if (result.status == 200) {
27 | graphs = await result.json();
28 | }
29 |
30 | return {user:user, graphs:graphs};
31 | }
32 |
33 |
34 | constructor(props) {
35 | super(props);
36 | }
37 |
38 |
39 | render() {
40 | return (
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
54 |
55 | )
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/public/static/discordIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/discordIcon.png
--------------------------------------------------------------------------------
/public/static/discordIcon_highres.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/discordIcon_highres.png
--------------------------------------------------------------------------------
/public/static/emailIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/emailIcon.png
--------------------------------------------------------------------------------
/public/static/emailIcon_highres.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/emailIcon_highres.png
--------------------------------------------------------------------------------
/public/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/favicon.png
--------------------------------------------------------------------------------
/public/static/fonts/open-sans/open-sans-10-black/open-sans-10-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/fonts/open-sans/open-sans-10-black/open-sans-10-black.png
--------------------------------------------------------------------------------
/public/static/fonts/open-sans/open-sans-12-black/open-sans-12-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/fonts/open-sans/open-sans-12-black/open-sans-12-black.png
--------------------------------------------------------------------------------
/public/static/fonts/open-sans/open-sans-128-black/open-sans-128-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/fonts/open-sans/open-sans-128-black/open-sans-128-black.png
--------------------------------------------------------------------------------
/public/static/fonts/open-sans/open-sans-128-white/open-sans-128-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/fonts/open-sans/open-sans-128-white/open-sans-128-white.png
--------------------------------------------------------------------------------
/public/static/fonts/open-sans/open-sans-14-black/open-sans-14-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/fonts/open-sans/open-sans-14-black/open-sans-14-black.png
--------------------------------------------------------------------------------
/public/static/fonts/open-sans/open-sans-16-black/open-sans-16-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/fonts/open-sans/open-sans-16-black/open-sans-16-black.png
--------------------------------------------------------------------------------
/public/static/fonts/open-sans/open-sans-16-white/open-sans-16-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/fonts/open-sans/open-sans-16-white/open-sans-16-white.png
--------------------------------------------------------------------------------
/public/static/fonts/open-sans/open-sans-32-black/open-sans-32-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/fonts/open-sans/open-sans-32-black/open-sans-32-black.png
--------------------------------------------------------------------------------
/public/static/fonts/open-sans/open-sans-32-white/open-sans-32-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/fonts/open-sans/open-sans-32-white/open-sans-32-white.png
--------------------------------------------------------------------------------
/public/static/fonts/open-sans/open-sans-64-black/open-sans-64-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/fonts/open-sans/open-sans-64-black/open-sans-64-black.png
--------------------------------------------------------------------------------
/public/static/fonts/open-sans/open-sans-64-white/open-sans-64-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/fonts/open-sans/open-sans-64-white/open-sans-64-white.png
--------------------------------------------------------------------------------
/public/static/fonts/open-sans/open-sans-8-black/open-sans-8-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/fonts/open-sans/open-sans-8-black/open-sans-8-black.png
--------------------------------------------------------------------------------
/public/static/fonts/open-sans/open-sans-8-white/open-sans-8-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/fonts/open-sans/open-sans-8-white/open-sans-8-white.png
--------------------------------------------------------------------------------
/public/static/githubLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/githubLogo.png
--------------------------------------------------------------------------------
/public/static/githubLogo_highres.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/githubLogo_highres.png
--------------------------------------------------------------------------------
/public/static/og.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/og.jpg
--------------------------------------------------------------------------------
/public/static/patreonIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/patreonIcon.png
--------------------------------------------------------------------------------
/public/static/patreonIcon_highres.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/patreonIcon_highres.png
--------------------------------------------------------------------------------
/public/static/screenshots/screenshot01.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/screenshots/screenshot01.JPG
--------------------------------------------------------------------------------
/public/static/screenshots/screenshot02.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/screenshots/screenshot02.JPG
--------------------------------------------------------------------------------
/public/static/screenshots/screenshot03.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/screenshots/screenshot03.JPG
--------------------------------------------------------------------------------
/public/static/trelloIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/trelloIcon.png
--------------------------------------------------------------------------------
/public/static/trelloIcon_highres.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/trelloIcon_highres.png
--------------------------------------------------------------------------------
/public/static/twitterIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/twitterIcon.png
--------------------------------------------------------------------------------
/public/static/twitterIcon_highres.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/twitterIcon_highres.png
--------------------------------------------------------------------------------
/public/static/viewportBg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dan335/nimp/5101262701580b60fb73d97ae8aaab8d8eade839/public/static/viewportBg.jpg
--------------------------------------------------------------------------------
/server/api/deletegraph.js:
--------------------------------------------------------------------------------
1 | var ObjectId = require('bson-objectid');
2 |
3 |
4 | module.exports = function(app) {
5 | app.post('/api/deletegraph', (req, res, next) => {
6 | if (!req.session.user) {
7 | return res.status(500).end();
8 | }
9 |
10 | if (req.body.graphId.length != 24) {
11 | return res.status(500).end();
12 | }
13 |
14 | const graphId = new ObjectId(req.body.graphId);
15 |
16 | const collection = req.app.locals.db.collection('graphs');
17 |
18 | collection.deleteOne({userId:req.session.user._id, _id:graphId}, {}, (error, result) => {
19 | if (error) {
20 | res.status(500).end();
21 | } else {
22 | res.status(200).end();
23 | }
24 | })
25 | })
26 | }
27 |
--------------------------------------------------------------------------------
/server/api/graph.js:
--------------------------------------------------------------------------------
1 | var ObjectId = require('mongodb').ObjectID;
2 |
3 |
4 | module.exports = function(app) {
5 | app.post('/api/graph', (req, res, next) => {
6 | if (req.body.graphId.length != 24) {
7 | return res.status(500).end('Invalid graph id.');
8 | }
9 |
10 | const collection = req.app.locals.db.collection('graphs');
11 | const graphId = new ObjectId(req.body.graphId);
12 |
13 | collection.findOne({_id:graphId}, {projection:{thumbnail:0}}, (error, graph) => {
14 | if (error) {
15 | return res.status(500).end('Error finding graph.');
16 | } else {
17 | if (!graph) {
18 | res.status(404).end('No graph found.');
19 | } else {
20 | if (graph.isPublic) {
21 | res.json(graph).end();
22 | } else {
23 | if (graph.userId != req.body.userId) {
24 | return res.status(401).end('Not authorized.');
25 | } else {
26 | return res.json(graph).end();
27 | }
28 | }
29 | }
30 | }
31 | })
32 | })
33 | }
34 |
--------------------------------------------------------------------------------
/server/api/graphs.js:
--------------------------------------------------------------------------------
1 | var ObjectId = require('bson-objectid');
2 |
3 |
4 | module.exports = function(app) {
5 | app.get('/api/graphs', (req, res, next) => {
6 | const collection = req.app.locals.db.collection('graphs');
7 | const cursor = collection.find({isPublic:true}, {sort:{updatedAt:-1}, projection:{userId:1, username:1, views:1, thumbnail:1, title:1, url:1}});
8 | cursor.toArray((error, graphs) => {
9 | if (error) {
10 | console.log(error);
11 | res.status(500).end();
12 | } else {
13 | res.json(graphs).end();
14 | }
15 | })
16 | })
17 |
18 |
19 | app.post('/api/usergraphs', (req, res, next) => {
20 | const collection = req.app.locals.db.collection('graphs');
21 |
22 | if (req.body.userId.length != 24) {
23 | return res.status(500).end();
24 | }
25 |
26 | const userId = new ObjectId(req.body.userId);
27 |
28 | let find = {userId:userId};
29 |
30 | if (!req.body.isUser) {
31 | find.isPublic = true;
32 | }
33 |
34 | const cursor = collection.find(find, {sort:{updatedAt:-1}, projection:{userId:1, username:1, views:1, thumbnail:1, title:1, url:1}});
35 | cursor.toArray((error, graphs) => {
36 | if (error) {
37 | console.log(error);
38 | res.status(500).end();
39 | } else {
40 | res.json(graphs).end();
41 | }
42 | })
43 | })
44 | }
45 |
--------------------------------------------------------------------------------
/server/api/login.js:
--------------------------------------------------------------------------------
1 | const bcrypt = require('bcryptjs');
2 |
3 |
4 | module.exports = function(app) {
5 | app.post('/api/login', (req, res, next) => {
6 | if (!req.body.email || !req.body.email.length) {
7 | return res.status(500).send('Email address required.');
8 | }
9 |
10 | if (!req.body.password || !req.body.password.length) {
11 | return res.status(500).send('Password required.');
12 | }
13 |
14 | const collection = req.app.locals.db.collection('users');
15 |
16 | collection.findOne({email:req.body.email.toLowerCase().trim()}, {}, (error, user) => {
17 | if (error) {
18 | return res.status(500).send('Error finding user.');
19 | } else {
20 | if (user) {
21 |
22 | bcrypt.compare(req.body.password, user.password, (error, result) => {
23 | if (error) {
24 | return res.status(500).send('Error comparing passwords.');
25 | } else {
26 | if (result == true) {
27 | req.session.user = user;
28 | return res.status(200).end();
29 | } else {
30 | return res.status(500).send('Wrong password.');
31 | }
32 | }
33 | })
34 | } else {
35 | return res.status(500).send('Email not found.');
36 | }
37 | }
38 | })
39 | })
40 | }
41 |
--------------------------------------------------------------------------------
/server/api/logout.js:
--------------------------------------------------------------------------------
1 | module.exports = function(app) {
2 | app.get('/api/logout', (req, res, next) => {
3 | delete req.session.user;
4 | res.status(200).end();
5 | })
6 | }
7 |
--------------------------------------------------------------------------------
/server/functions.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | stringToSlug(text) {
3 | const a = 'àáäâèéëêìíïîòóöôùúüûñçßÿœæŕśńṕẃǵǹḿǘẍźḧ·/_,:;'
4 | const b = 'aaaaeeeeiiiioooouuuuncsyoarsnpwgnmuxzh------'
5 | const p = new RegExp(a.split('').join('|'), 'g')
6 |
7 | return text.toString().toLowerCase()
8 | .replace(/\s+/g, '-') // Replace spaces with -
9 | .replace(p, c =>
10 | b.charAt(a.indexOf(c))) // Replace special chars
11 | .replace(/&/g, '-and-') // Replace & with 'and'
12 | .replace(/[^\w\-]+/g, '') // Remove all non-word chars
13 | .replace(/\-\-+/g, '-') // Replace multiple - with single -
14 | .replace(/^-+/, '') // Trim - from start of text
15 | .replace(/-+$/, '') // Trim - from end of text
16 | },
17 | }
18 |
--------------------------------------------------------------------------------