Skip to content

Commit

Permalink
Merge pull request #167 from jbunke/dev-branch
Browse files Browse the repository at this point in the history
1.2.2 development milestone
  • Loading branch information
jbunke authored Dec 31, 2024
2 parents d8eb2f3 + e178bb6 commit 5c5944d
Show file tree
Hide file tree
Showing 52 changed files with 1,410 additions and 120 deletions.
52 changes: 25 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# ![Stipple Effect](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/graphics/logo-anim.gif)

[![Buy on Itch.io](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/buttons/itch.png)](https://flinkerflitzer.itch.io/stipple-effect)
[![Changelog](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/buttons/documentation.png)](https://github.com/jbunke/se-docs)
[![Changelog](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/buttons/api.png)](https://github.com/jbunke/se-api)
[![Website](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/buttons/website.png)](https://jbunke.github.io/se)
[![Changelog](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/buttons/changelog.png)](changelog.md)
[![Roadmap](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/buttons/roadmap.png)](roadmap.md)
[![Buy on Itch.io](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/buttons/itch.png)](https://flinkerflitzer.itch.io/stipple-effect)

## About
*Stipple Effect* is a pixel art editor that supports animation and scripting. It is designed to facilitate a variety of workflows and to encourage rapid, iterative creation of video game art assets and other types of artwork.
Expand All @@ -17,38 +16,37 @@
<div align="center">A preview script in action</div>

## Features
* Symbiotic relationship between layers and frames
* [Linked and unlinked layers](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/graphics/linked-layers.gif)
* [Two-color system: Stipple Effect's brush, pencil, and gradient tool allow for interesting combinations of the primary and secondary colors](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/graphics/combination-modes.gif)
* Dither mode
* Blend mode
* Noise mode
* State management
* [Granular undo and redo](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/graphics/granular-undo-redo.gif)
* Animation playback
* [Onion skinning](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/graphics/onion-skin.gif)
* Symbiotic relationship between [layers](https://jbunke.github.io/se/docs/layer) and [frames](https://jbunke.github.io/se/docs/frame)
* Linked-cel layers (contents persist across frames)
* Two-color system: *Stipple Effect*'s brush, pencil, and gradient tool allow for interesting [combinations](https://jbunke.github.io/se/docs/color#combination-modes) of the [primary and secondary colors](https://jbunke.github.io/se/docs/interface#system-colors)
* Project [state control](https://jbunke.github.io/se/docs/state-control)
* [Granular undo and redo](https://jbunke.github.io/se/docs/state-control#granularity)
* History
* Generate time lapses
* Animation
* [Onion skinning](https://jbunke.github.io/se/docs/layer#onion-skin)
* Edit during playback
* [Split/stitch](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/graphics/split-stitch.gif)
* Split a project into frames
* Stitch frames together into a sprite sheet
* Split/stitch
* [Split a sprite sheet into frames](https://jbunke.github.io/se/docs/sizing#split-a-sprite-sheet-into-frames)
* [Stitch an animation into a sprite sheet](https://jbunke.github.io/se/docs/sizing#stitch-an-animation-into-a-sprite-sheet)
* Palettes
* Import and export palettes
* [Palettization](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/graphics/palettization.gif)
* [Extract colors in a project to a palette](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/graphics/extract-colors.gif)
* Selection
* [Family of selection tools designed for pixel-perfect selection](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/graphics/selection-tools.gif)
* [Intuitive and powerful outlining utilities](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/graphics/outline.gif)
* [Pixel grid](https://raw.githubusercontent.com/jbunke/se-docs/master/assets/graphics/pixel-grid.gif)
* Easily enable/disable and modify the size of the pixel grid cells
* [Palettization](https://jbunke.github.io/se/docs/color-actions#palettization)
* [Extract colors in a project to a palette](https://jbunke.github.io/se/docs/color-actions#extract-canvas-colors-to-palette)
* [Selection](https://jbunke.github.io/se/docs/selection)
* [Family of selection tools](https://jbunke.github.io/se/docs/sel-area-tools) designed for pixel-perfect selection
* Intuitive and powerful [outlining utilities](https://jbunke.github.io/se/docs/outline)
* [Pixel grid](https://jbunke.github.io/se/docs/pixel-grid)
* Easily enable/disable and modify the size of the pixel grid's cells
* The box select tool can snap to the grid
* And much more!

Find out more about the program by reading [the documentation](https://github.com/jbunke/se-docs).
Find out more about the program by reading [the documentation](https://jbunke.github.io/se/docs/).

## Scripting
_Stipple Effect_ supports scripts have three main uses: **automation**, **custom previews** and **color transformation**. It is highly recommended for users that want to get the most out of the program to read the API and familiarize themselves with its potential applications.
* [Scripting overview](https://github.com/jbunke/se-docs/blob/master/scripting.md)
* [API](https://github.com/jbunke/se-api)
*Stipple Effect* scripts have three main uses: [**automation**](https://jbunke.github.io/se/docs/automation-scripts), [**custom previews**](https://jbunke.github.io/se/docs/preview-scripts) and [**color transformations**](https://jbunke.github.io/se/docs/color-scripts). It is highly recommended for users that want to get the most out of the program to read the API specification and familiarize themselves with its potential applications.
* [Scripting overview](https://jbunke.github.io/se/docs/scripting)
* [API specification](https://jbunke.github.io/se/api/)
* [Example scripts](https://github.com/jbunke/se-script-examples)

I have created [a VS Code extension](https://marketplace.visualstudio.com/items?itemName=jordanbunke.deltascript-for-stipple-effect) that provides syntax highlighting for *Stipple Effect* scripts.
Expand Down
18 changes: 18 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Changelog

## **1.2.2** - 2024-12-31

### Added:
* Comprehensive [program documentation](https://jbunke.github.io/se/docs/) and [scripting API specification](https://jbunke.github.io/se/api/)

### Changed:
* Updated *Stipple Effect -> Resources* links with the new website

### Fixed:
* Bug: Line tool produces doubles at oblique angles when line breadth is 1

### API Changes:
* Added:
* `light` type
* New namespaces and associated functions and constants
* `$Graphics`
* `$Math`

## **1.2.1** - 2024-09-06

### Added:
Expand Down
2 changes: 1 addition & 1 deletion res/blurbs/__about.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ following ways.

Thank you!

{Jordan Bunke, 2023-2024}
{Jordan Bunke, 2023-present}
18 changes: 18 additions & 0 deletions res/blurbs/__changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
{1.2.2} - 2024-12-31

Added:
> Comprehensive {program documentation} and {scripting API specification}

Changed:
> Updated {Stipple Effect -> Resources} links with the new website

Fixed:
> Bug: Line tool produces doubles at oblique angles when line breadth is 1

API Changes:
Added:
> {light} type
> New namespaces and associated functions and constants
> {$Graphics}
> {$Math}

{1.2.1} - 2024-09-06

Added:
Expand Down
10 changes: 7 additions & 3 deletions res/blurbs/__roadmap.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
This is a rough outline of planned features and when to expect them. Everything you see here is
subject to change.

{Q3 2024}
> Presets for common scriptable behaviours
{Q1 2025}
> Fix crashing bugs related to:
> Selection
> Out of memory errors

{Q4 2024}
{Q1 - Q2 2025}
> Increase maximum canvas dimensions and frame count
> Lossless video exporting
> Improved dialog menus
> CLI tool
> Test and debug scripts
> Additional API functionality
2 changes: 1 addition & 1 deletion res/blurbs/brush_select.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Shortcut: {sc:SET_TOOL_BRUSH_SELECT}

Behaves like the brush, but for selection.

Simple selection: {Click}
Simple selection: {Click & Drag}

Additive selection: {Ctrl + Click & Drag}
Adds the result of the operation to the existing selection.
Expand Down
2 changes: 1 addition & 1 deletion res/blurbs/hand.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Shortcut: {sc:SET_TOOL_HAND}

Use the hand to move the image canvas around the workspace.
Use the hand to move the canvas around the workspace.

Pan: {Click & Drag}
2 changes: 1 addition & 1 deletion res/blurbs/polygon_select.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Shortcut: {sc:SET_TOOL_POLYGON_SELECT}

Define a polygonal selection area by placing vertices. Adjacent vertices form edges that define
Define a polygonal selection area by placing vertices. Successive vertices form edges that define
the bounds of the selection. To close the polygon, place a vertex down on the same pixel where
the shape began.

Expand Down
2 changes: 1 addition & 1 deletion res/program
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name:{Stipple Effect}
version:{1.2.1}
version:{1.2.2}
devbuild:{false}
native_standard:{1.3}
palette_standard:{1.0}
2 changes: 1 addition & 1 deletion res/tooltips/__scripting_api.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Scripting API
Scripting API specification
2 changes: 1 addition & 1 deletion res/tooltips/import_per_layer.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
New Stipple Effect project from preview with layers preserved
New project from preview with layers preserved
(May not match preview)
2 changes: 1 addition & 1 deletion res/tooltips/import_preview.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
New Stipple Effect project from preview
New project from preview
12 changes: 8 additions & 4 deletions roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

This is a rough outline of planned features and when to expect them. Everything you see here is subject to change.

## Q3 2024
* Presets for common scriptable behaviours
## Q1 2025
* Fix crashing bugs related to:
* Selection
* Out of memory errors

## Q4 2024
## Q1 - Q2 2025
* Increase maximum canvas dimensions and frame count
* Lossless video exporting
* Improved dialog menus
* CLI tool
* CLI tool
* Test and debug scripts
* Additional API functionality
4 changes: 4 additions & 0 deletions src/com/jordanbunke/stipple_effect/preview/Preview.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ protected Preview(

frameIndex = 0;
updateContent();
frameCount = content.length;

initialPos = position;
componentsPositions = new HashMap<>();
Expand Down Expand Up @@ -334,6 +335,9 @@ private void runScript() {
}

private void updateFrameData() {
if (INSTANCE == null)
return;

frameCount = content.length;
frameIndex %= frameCount;
}
Expand Down
55 changes: 33 additions & 22 deletions src/com/jordanbunke/stipple_effect/scripting/SEScriptVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
import com.jordanbunke.stipple_effect.palette.Palette;
import com.jordanbunke.stipple_effect.project.SEContext;
import com.jordanbunke.stipple_effect.project.SaveConfig;
import com.jordanbunke.stipple_effect.scripting.delegators.GraphicsNodeDelegator;
import com.jordanbunke.stipple_effect.scripting.delegators.MathNodeDelegator;
import com.jordanbunke.stipple_effect.scripting.ext_ast_nodes.type.SEExtTypeNode;
import com.jordanbunke.stipple_effect.scripting.util.LayerRep;
import com.jordanbunke.stipple_effect.scripting.util.SENodeDelegator;
import com.jordanbunke.stipple_effect.scripting.delegators.SENodeDelegator;
import com.jordanbunke.stipple_effect.scripting.util.Light;
import com.jordanbunke.stipple_effect.utility.Constants;

import java.util.Set;
Expand All @@ -22,7 +25,7 @@ public final class SEScriptVisitor extends ScriptVisitor {
static {
final Set<Class<?>> extensionTypeObjects = Set.of(
SEContext.class, LayerRep.class,
Palette.class, SaveConfig.class);
Palette.class, SaveConfig.class, Light.class);

extensionTypeObjects.forEach(TypeCompatibility::addBaseType);
}
Expand All @@ -40,16 +43,21 @@ public ExpressionNode visitExtPropertyExpression(
final ScriptParser.ExtPropertyExpressionContext ctx
) {
final String namespace = ctx.namespace().ident().getText(),
propertyID = ctx.namespace().subident().getText()
constID = ctx.namespace().subident().getText()
.substring(SCOPE_SEP.length());

final TextPosition position = TextPosition.fromToken(ctx.start);

if (namespace.equals(Constants.SCRIPT_GLOBAL_NAMESPACE))
return SENodeDelegator.globalProperty(position, propertyID);

return new IllegalExpressionNode(position,
"\"" + namespace + "\" is an illegal namespace");
return switch (namespace) {
case Constants.SCRIPT_GLOBAL_NAMESPACE ->
SENodeDelegator.globalConstant(position, constID);
case Constants.GRAPHICS_NAMESPACE ->
GraphicsNodeDelegator.constant(position, constID);
case Constants.MATH_NAMESPACE ->
MathNodeDelegator.constant(position, constID);
default -> new IllegalExpressionNode(position,
"\"" + namespace + "\" is an illegal namespace");
};
}

@Override
Expand All @@ -62,15 +70,18 @@ public ExpressionNode visitExtFuncCallExpression(

final TextPosition position = TextPosition.fromToken(ctx.start);

final ExpressionNode[] args = ctx.args().expr().stream()
.map(a -> (ExpressionNode) visit(a))
.toArray(ExpressionNode[]::new);

if (namespace.equals(Constants.SCRIPT_GLOBAL_NAMESPACE))
return SENodeDelegator.globalFunctionExpression(position, fID, args);

return new IllegalExpressionNode(position,
"\"" + namespace + "\" is an illegal namespace");
final ExpressionNode[] args = unpackElements(ctx.args().elements());

return switch (namespace) {
case Constants.SCRIPT_GLOBAL_NAMESPACE ->
SENodeDelegator.globalFunctionExpression(position, fID, args);
case Constants.GRAPHICS_NAMESPACE ->
GraphicsNodeDelegator.expression(position, fID, args);
case Constants.MATH_NAMESPACE ->
MathNodeDelegator.expression(position, fID, args);
default -> new IllegalExpressionNode(position, "Namespace \"" +
namespace + "\" does not exist or defines no value-returning functions");
};
}

@Override
Expand All @@ -83,15 +94,15 @@ public StatementNode visitExtFuncCallStatement(

final TextPosition position = TextPosition.fromToken(ctx.start);

final ExpressionNode[] args = ctx.args().expr().stream()
.map(a -> (ExpressionNode) visit(a))
.toArray(ExpressionNode[]::new);
final ExpressionNode[] args = unpackElements(ctx.args().elements());

if (namespace.equals(Constants.SCRIPT_GLOBAL_NAMESPACE))
return SENodeDelegator.globalFunctionStatement(position, fID, args);

return new IllegalStatementNode(position,
"\"" + namespace + "\" is an illegal namespace");
// extend here if other namespaces implement void functions

return new IllegalStatementNode(position, "Namespace \"" +
namespace + "\" does not exist or defines no void functions");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.jordanbunke.stipple_effect.scripting.delegators;

import com.jordanbunke.delta_time.scripting.ast.nodes.expression.ExpressionNode;
import com.jordanbunke.delta_time.scripting.ast.nodes.expression.IllegalExpressionNode;
import com.jordanbunke.delta_time.scripting.util.TextPosition;
import com.jordanbunke.stipple_effect.scripting.ext_ast_nodes.expression.graphics.*;
import com.jordanbunke.stipple_effect.utility.Constants;
import com.jordanbunke.stipple_effect.utility.EnumUtils;

import static com.jordanbunke.stipple_effect.scripting.util.LightingUtils.*;

public final class GraphicsNodeDelegator {
public static ExpressionNode expression(
final TextPosition position, final String fID,
final ExpressionNode[] args
) {
return switch (fID) {
case UVMappingNode.NAME -> new UVMappingNode(position, args);
case GenLookupNode.NAME -> new GenLookupNode(position, args);
case LerpColorNode.NAME -> new LerpColorNode(position, args);
case LightingNode.NAME -> new LightingNode(position, args);
case PointLightNode.NAME -> new PointLightNode(position, args);
case DirLightNode.NAME -> new DirLightNode(position, args);
default -> new IllegalExpressionNode(position, "$" +
Constants.GRAPHICS_NAMESPACE + " does not define a function \"" +
fID + "()\"");
};
}

public static ExpressionNode constant(
final TextPosition position, final String constID
) {
if (EnumUtils.matches(constID, LightDirection.class))
return new DirLightConstantNode(position,
LightDirection.valueOf(constID));

return new IllegalExpressionNode(position,
"No constant \"$" + Constants.GRAPHICS_NAMESPACE +
"." + constID + "\" exists");
}
}
Loading

0 comments on commit 5c5944d

Please sign in to comment.