From 155fa15b6eca5445891080e782309edbd5e063bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20de=20Courville?= Date: Sun, 16 Mar 2025 11:06:08 +0100 Subject: [PATCH 01/29] Update README.md for 4.4 release --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 313e4596c0..ae46f06fcb 100644 --- a/README.md +++ b/README.md @@ -7,14 +7,14 @@ Processing is a flexible software sketchbook and a programming language designed This repository contains the source code for the [Processing](https://processing.org/) project for people who want to help improve the code. -## Announcing Processing 4.3.1 +## Welcome to Processing 4.4! -We’re excited to announce the release of Processing 4.3.1! This update brings tooling improvements and a friendlier experience for contributors. To learn more, read the [Processing 4.3.1 announcement](https://github.com/processing/processing4-carbon-aug-19/wiki/Announcing-Processing-4.3.1). +We’re excited to announce the release of Processing 4.4! While our last big release focused on tooling and developer experience, this update modernizes Processing under the hood to make future development easier. Key changes include switching the build system from Ant to Gradle, starting the transition to Jetpack Compose Multiplatform for the UI, and adding Kotlin support to the codebase. To learn more, check out [Changes in 4.4.0](https://github.com/processing/processing4/wiki/Changes-in-4.4.0). -Processing was initiated in 2001 by Ben Fry and Casey Reas, who lead the development and maintenance of the project until 2023. We are grateful for their vision and dedication to the project. Processing is also indebted to over two decades of contributions from the broader Processing community. +We hope these updates will make it easier for more people to contribute to Processing. If you'd like to get involved, have a look at our [Contributor Guide](CONTRIBUTING.md). -> [!NOTE] -> Due to platform limitations, the GitHub Contributors page for this repository does not show the complete list of contributors. However, the [git commit history](https://github.com/processing/processing4/commits/main/) provides a full record of the project's contributions. For contributor graphs before November 13th, refer to [this page](https://github.com/benfry/processing4/graphs/contributors). A comprehensive [list of all contributors](#contributors) is also included below. To see all commits by a contributor, click on the [💻](https://github.com/processing/processing4/commits?author=benfry) emoji below their name. +## Acknowledgement +Processing was initiated in 2001 by Ben Fry and Casey Reas, who lead the development and maintenance of the project until 2023. We are grateful for their vision and dedication to the project. Processing is also indebted to over two decades of contributions from the broader Processing community. ## Using Processing @@ -66,8 +66,9 @@ For licensing information about the Processing website see the [processing-websi Copyright (c) 2015-now The Processing Foundation ## Contributors +The Processing project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification, recognizing all forms of contributions (not just code!). A list of all contributors is included below. You can add yourself to the contributors list [here](https://github.com/processing/processing4-carbon-aug-19/issues/839)! -Add yourself to the contributors list [here](https://github.com/processing/processing4-carbon-aug-19/issues/839)! +_Note: due to GitHub's limitations, this repository's [Contributors](https://github.com/processing/processing4/graphs/contributors) page only shows accurate contribution data starting from late 2024. Contributor graphs from before November 13th 2024 can be found on [this page](https://github.com/benfry/processing4/graphs/contributors). The [git commit history](https://github.com/processing/processing4/commits/main/) provides a full record of the project's contributions. To see all commits by a contributor, click on the [💻](https://github.com/processing/processing4/commits?author=benfry) emoji below their name._ From df8b732c3f4491c95a62864140d00eea72893b81 Mon Sep 17 00:00:00 2001 From: rishab Date: Thu, 20 Mar 2025 11:40:22 +0530 Subject: [PATCH 02/29] added unit tests for PVector --- core/test/processing/core/PVectorTest.java | 294 +++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 core/test/processing/core/PVectorTest.java diff --git a/core/test/processing/core/PVectorTest.java b/core/test/processing/core/PVectorTest.java new file mode 100644 index 0000000000..9d97dc470a --- /dev/null +++ b/core/test/processing/core/PVectorTest.java @@ -0,0 +1,294 @@ +package processing.core; + +import org.junit.Assert; +import org.junit.Test; + +public class PVectorTest { + + @Test + public void testConstructors() { + PVector v0 = new PVector(); + Assert.assertEquals(0, v0.x, 0.0001f); + Assert.assertEquals(0, v0.y, 0.0001f); + Assert.assertEquals(0, v0.z, 0.0001f); + + PVector v2 = new PVector(3, 4); + Assert.assertEquals(3, v2.x, 0.0001f); + Assert.assertEquals(4, v2.y, 0.0001f); + Assert.assertEquals(0, v2.z, 0.0001f); + + PVector v3 = new PVector(1, 2, 3); + Assert.assertEquals(1, v3.x, 0.0001f); + Assert.assertEquals(2, v3.y, 0.0001f); + Assert.assertEquals(3, v3.z, 0.0001f); + } + + @Test + public void testSetAndCopy() { + PVector v = new PVector(1, 2, 3); + PVector copy = v.copy(); + Assert.assertEquals(v.x, copy.x, 0.0001f); + Assert.assertEquals(v.y, copy.y, 0.0001f); + Assert.assertEquals(v.z, copy.z, 0.0001f); + + v.set(4, 5, 6); + Assert.assertEquals(4, v.x, 0.0001f); + Assert.assertEquals(5, v.y, 0.0001f); + Assert.assertEquals(6, v.z, 0.0001f); + } + + @Test + public void testAdd() { + PVector v1 = new PVector(1, 1, 1); + PVector v2 = new PVector(2, 3, 4); + v1.add(v2); + Assert.assertEquals(3, v1.x, 0.0001f); + Assert.assertEquals(4, v1.y, 0.0001f); + Assert.assertEquals(5, v1.z, 0.0001f); + + PVector v3 = new PVector(1, 2, 3); + PVector result = PVector.add(v3, new PVector(4, 5, 6)); + Assert.assertEquals(5, result.x, 0.0001f); + Assert.assertEquals(7, result.y, 0.0001f); + Assert.assertEquals(9, result.z, 0.0001f); + } + + @Test + public void testSub() { + PVector v1 = new PVector(5, 7, 9); + PVector v2 = new PVector(1, 2, 3); + v1.sub(v2); + Assert.assertEquals(4, v1.x, 0.0001f); + Assert.assertEquals(5, v1.y, 0.0001f); + Assert.assertEquals(6, v1.z, 0.0001f); + + PVector v3 = new PVector(10, 10, 10); + PVector result = PVector.sub(v3, new PVector(3, 3, 3)); + Assert.assertEquals(7, result.x, 0.0001f); + Assert.assertEquals(7, result.y, 0.0001f); + Assert.assertEquals(7, result.z, 0.0001f); + } + + @Test + public void testMult() { + PVector v = new PVector(1, 2, 3); + v.mult(2); + Assert.assertEquals(2, v.x, 0.0001f); + Assert.assertEquals(4, v.y, 0.0001f); + Assert.assertEquals(6, v.z, 0.0001f); + + PVector result = PVector.mult(new PVector(1, 1, 1), 5); + Assert.assertEquals(5, result.x, 0.0001f); + Assert.assertEquals(5, result.y, 0.0001f); + Assert.assertEquals(5, result.z, 0.0001f); + } + + @Test + public void testDiv() { + PVector v1 = new PVector(10, 20, 30); + v1.div(2); + Assert.assertEquals(5, v1.x, 0.0001f); + Assert.assertEquals(10, v1.y, 0.0001f); + Assert.assertEquals(15, v1.z, 0.0001f); + + PVector result = PVector.div(new PVector(10, 20, 30), 2); + Assert.assertEquals(5, result.x, 0.0001f); + Assert.assertEquals(10, result.y, 0.0001f); + Assert.assertEquals(15, result.z, 0.0001f); + + // Division by zero + PVector v2 = new PVector(1, 2, 3); + v2.div(0); + Assert.assertTrue(Float.isInfinite(v2.x)); + Assert.assertTrue(Float.isInfinite(v2.y)); + Assert.assertTrue(Float.isInfinite(v2.z)); + } + + @Test + public void testMagnitude() { + PVector v = new PVector(3, 4, 0); + Assert.assertEquals(5, v.mag(), 0.0001f); + Assert.assertEquals(25, v.magSq(), 0.0001f); + } + + @Test + public void testDot() { + PVector v1 = new PVector(1, 2, 3); + PVector v2 = new PVector(4, -5, 6); + float dot = v1.dot(v2); + Assert.assertEquals(12, dot, 0.0001f); + + float dotStatic = PVector.dot(v1, v2); + Assert.assertEquals(12, dotStatic, 0.0001f); + } + + @Test + public void testCross() { + PVector v1 = new PVector(1, 0, 0); + PVector v2 = new PVector(0, 1, 0); + PVector cross = v1.cross(v2); + Assert.assertEquals(0, cross.x, 0.0001f); + Assert.assertEquals(0, cross.y, 0.0001f); + Assert.assertEquals(1, cross.z, 0.0001f); + } + + @Test + public void testNormalize() { + PVector v1 = new PVector(3, 4, 0); + v1.normalize(); + Assert.assertEquals(1, v1.mag(), 0.0001f); + + //with target + PVector v2 = new PVector(3, 4, 0); + PVector target = new PVector(); + PVector result = v2.normalize(target); + Assert.assertSame(target, result); + Assert.assertEquals(0.6f, result.x, 0.0001f); + Assert.assertEquals(0.8f, result.y, 0.0001f); + Assert.assertEquals(0, result.z, 0.0001f); + + // Normalize zero vector + PVector zero = new PVector(0, 0, 0); + zero.normalize(); + Assert.assertEquals(0, zero.x, 0.0001f); + Assert.assertEquals(0, zero.y, 0.0001f); + Assert.assertEquals(0, zero.z, 0.0001f); + + } + + @Test + public void testLimit() { + PVector v = new PVector(10, 0, 0); + v.limit(5); + Assert.assertEquals(5, v.mag(), 0.0001f); + } + + @Test + public void testSetMag() { + PVector v = new PVector(3, 4, 0); + v.setMag(10); + Assert.assertEquals(10, v.mag(), 0.0001f); + } + + @Test + public void testHeading() { + PVector v = new PVector(0, 1); + float heading = v.heading(); + Assert.assertEquals(PConstants.HALF_PI, heading, 0.0001f); + } + + @Test + public void testRotate() { + PVector v = new PVector(1, 0); + v.rotate(PConstants.HALF_PI); + Assert.assertEquals(0, v.x, 0.0001f); + Assert.assertEquals(1, v.y, 0.0001f); + } + + @Test + public void testLerp() { + PVector v1 = new PVector(0, 0, 0); + PVector v2 = new PVector(10, 10, 10); + v1.lerp(v2, 0.5f); + Assert.assertEquals(5, v1.x, 0.0001f); + Assert.assertEquals(5, v1.y, 0.0001f); + Assert.assertEquals(5, v1.z, 0.0001f); + + PVector result = PVector.lerp(new PVector(0, 0, 0), new PVector(10, 10, 10), 0.5f); + Assert.assertEquals(5, result.x, 0.0001f); + Assert.assertEquals(5, result.y, 0.0001f); + Assert.assertEquals(5, result.z, 0.0001f); + } + + @Test + public void testAngleBetween() { + PVector v1 = new PVector(1, 0, 0); + PVector v2 = new PVector(0, 1, 0); + float a1 = PVector.angleBetween(v1, v2); + Assert.assertEquals(PConstants.HALF_PI, a1, 0.0001f); + + // angleBetween with zero vectors + float a2 = PVector.angleBetween(new PVector(0, 0, 0), new PVector(1, 0, 0)); + Assert.assertEquals(0, a2, 0.0001f); + + // angleBetween with parallel vectors + float a3 = PVector.angleBetween(new PVector(1, 0, 0), new PVector(2, 0, 0)); + Assert.assertEquals(0, a3, 0.0001f); + + // angleBetween with opposite vectors + float a4 = PVector.angleBetween(new PVector(1, 0, 0), new PVector(-1, 0, 0)); + Assert.assertEquals(PConstants.PI, a4, 0.0001f); + } + + @Test + public void testFromAngle() { + PVector v = PVector.fromAngle(0); + Assert.assertEquals(1, v.x, 0.0001f); + Assert.assertEquals(0, v.y, 0.0001f); + Assert.assertEquals(0, v.z, 0.0001f); + + v = PVector.fromAngle(PConstants.HALF_PI); + Assert.assertEquals(0, v.x, 0.0001f); + Assert.assertEquals(1, v.y, 0.0001f); + Assert.assertEquals(0, v.z, 0.0001f); + + PVector target = new PVector(); + PVector result = PVector.fromAngle(PConstants.PI, target); + Assert.assertSame(target, result); + Assert.assertEquals(-1, result.x, 0.0001f); + Assert.assertEquals(0, result.y, 0.0001f); + } + + + @Test + public void testArray() { + PVector v = new PVector(3, 4, 5); + float[] arr = v.array(); + Assert.assertEquals(3, arr[0], 0.0001f); + Assert.assertEquals(4, arr[1], 0.0001f); + Assert.assertEquals(5, arr[2], 0.0001f); + } + + @Test + public void testRandom2D() { + PVector v = PVector.random2D(); + Assert.assertEquals(1, v.mag(), 0.0001f); + Assert.assertEquals(0, v.z, 0.0001f); + + PVector target = new PVector(); + PVector result = PVector.random2D(target); + Assert.assertSame(target, result); + Assert.assertEquals(1, result.mag(), 0.0001f); + } + + @Test + public void testRandom3D() { + PVector v = PVector.random3D(); + Assert.assertEquals(1, v.mag(), 0.0001f); + + PVector target = new PVector(); + PVector result = PVector.random3D(target); + Assert.assertSame(target, result); + Assert.assertEquals(1, result.mag(), 0.0001f); + } + + + @Test + public void testEqualsAndHashCode() { + PVector v1 = new PVector(1, 2, 3); + PVector v2 = new PVector(1, 2, 3); + PVector v3 = new PVector(3, 2, 1); + + Assert.assertTrue(v1.equals(v2)); + Assert.assertFalse(v1.equals(v3)); + Assert.assertEquals(v1.hashCode(), v2.hashCode()); + } + + @Test + public void testToString() { + PVector v = new PVector(1, 2, 3); + String expected = "[ 1.0, 2.0, 3.0 ]"; + Assert.assertEquals(expected, v.toString()); + } + +} From 1a0e52a8d8dd16c15718a3a92f8c7ce9b0fb5e0c Mon Sep 17 00:00:00 2001 From: rishab Date: Tue, 25 Mar 2025 19:53:52 +0530 Subject: [PATCH 03/29] added unit tests for PMatrix2D --- core/test/processing/core/PMatrix2DTest.java | 186 +++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 core/test/processing/core/PMatrix2DTest.java diff --git a/core/test/processing/core/PMatrix2DTest.java b/core/test/processing/core/PMatrix2DTest.java new file mode 100644 index 0000000000..3f1f82f247 --- /dev/null +++ b/core/test/processing/core/PMatrix2DTest.java @@ -0,0 +1,186 @@ +package processing.core; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; + +public class PMatrix2DTest { + + private PMatrix2D m; + + @Before + public void setUp() { + m = new PMatrix2D(); + } + + @Test + public void testIdentity() { + assertTrue("New matrix should be identity", m.isIdentity()); + float[] arr = m.get(null); + assertEquals(1, arr[0], 0.0001f); // m00 + assertEquals(0, arr[1], 0.0001f); // m01 + assertEquals(0, arr[2], 0.0001f); // m02 + assertEquals(0, arr[3], 0.0001f); // m10 + assertEquals(1, arr[4], 0.0001f); // m11 + assertEquals(0, arr[5], 0.0001f); // m12 + } + + @Test + public void testTranslate() { + m.translate(10, 20); + assertEquals(10, m.m02, 0.0001f); + assertEquals(20, m.m12, 0.0001f); + } + + @Test + public void testRotate() { + m.rotate(PConstants.HALF_PI); + assertEquals(0, m.m00, 0.0001f); + assertEquals(-1, m.m01, 0.0001f); + assertEquals(1, m.m10, 0.0001f); + assertEquals(0, m.m11, 0.0001f); + } + + + @Test + public void testScale() { + m.scale(2, 3); + assertEquals(2, m.m00, 0.0001f); + assertEquals(3, m.m11, 0.0001f); + assertEquals(0, m.m02, 0.0001f); + assertEquals(0, m.m12, 0.0001f); + } + + @Test + public void testShear() { + float shearAngle = 0.2f; + m.shearX(shearAngle); + assertEquals(0, m.m01, 0.0001f); + assertEquals((float)Math.tan(shearAngle), m.m10, 0.0001f); + assertEquals(1, m.m02, 0.0001f); + + m.reset(); + + m.shearY(shearAngle); + assertEquals(0, m.m01, 0.0001f); + assertEquals(0, m.m10, 0.0001f); + assertEquals((float)Math.tan(shearAngle), m.m11, 0.0001f); + assertEquals(1, m.m02, 0.0001f); + } + + @Test + public void testApply() { + PMatrix2D m2 = new PMatrix2D(1, 2, 3, 4, 5, 6); + m.apply(m2); + assertEquals(m2.m00, m.m00, 0.0001f); + assertEquals(m2.m01, m.m01, 0.0001f); + assertEquals(m2.m02, m.m02, 0.0001f); + assertEquals(m2.m10, m.m10, 0.0001f); + assertEquals(m2.m11, m.m11, 0.0001f); + assertEquals(m2.m12, m.m12, 0.0001f); + } + + @Test + public void testPreApply() { + PMatrix2D m1 = new PMatrix2D(1, 2, 3, 4, 5, 6); + m.reset(); // identity matrix + m.preApply(m1); + assertEquals(m1.m00, m.m00, 0.0001f); + assertEquals(m1.m01, m.m01, 0.0001f); + assertEquals(m1.m02, m.m02, 0.0001f); + assertEquals(m1.m10, m.m10, 0.0001f); + assertEquals(m1.m11, m.m11, 0.0001f); + assertEquals(m1.m12, m.m12, 0.0001f); + } + + @Test + public void testMultPVector() { + PVector src = new PVector(1, 2, 0); + PVector result = m.mult(src, null); + assertEquals(src.x, result.x, 0.0001f); + assertEquals(src.y, result.y, 0.0001f); + } + + @Test + public void testMultArray() { + float[] vec = { 1, 2 }; + float[] out = m.mult(vec, null); + assertEquals(1, out[0], 0.0001f); + assertEquals(2, out[1], 0.0001f); + } + + @Test + public void testMultXandY() { + float x = 10, y = 20; + float xOut = m.multX(x, y); + float yOut = m.multY(x, y); + assertEquals(x, xOut, 0.0001f); + assertEquals(y, yOut, 0.0001f); + } + + @Test + public void testInvertAndDeterminant() { + m.set(2, 0, 5, 1, 3, 7); + float det = m.determinant(); + assertEquals(6, det, 0.0001f); + + boolean invertible = m.invert(); + assertTrue("Matrix should be invertible", invertible); + + PMatrix2D identity = new PMatrix2D(2, 0, 5, 1, 3, 7); + identity.apply(m); + + assertEquals(1, identity.m00, 0.001f); + assertEquals(0, identity.m01, 0.001f); + assertEquals(0, identity.m10, 0.001f); + assertEquals(1, identity.m11, 0.001f); + } + + @Test + public void testIdentityWarped() { + assertTrue(m.isIdentity()); + assertFalse(m.isWarped()); + + m.translate(10, 20); + assertFalse(m.isIdentity()); + } + + @Test(expected = IllegalArgumentException.class) + public void testTranslate3DThrows() { + m.translate(1, 2, 3); + } + + @Test(expected = IllegalArgumentException.class) + public void testRotateXThrows() { + m.rotateX(1); + } + + @Test(expected = IllegalArgumentException.class) + public void testRotateYThrows() { + m.rotateY(1); + } + + @Test(expected = IllegalArgumentException.class) + public void testScale3DThrows() { + m.scale(1, 2, 3); + } + + @Test(expected = IllegalArgumentException.class) + public void testApplyPMatrix3DThrows() { + PMatrix3D m3d = new PMatrix3D(1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1); + m.apply(m3d); + } + + @Test + public void testGetArray() { + m.set(new float[]{1, 2, 0, 0, 1, 0}); + float[] arr = m.get(null); + assertEquals(1, arr[0], 0.0001f); + assertEquals(2, arr[1], 0.0001f); + assertEquals(0, arr[2], 0.0001f); + } +} From 88459e7a3a1db6d0fd55e623e15a1ef9d11742fb Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Fri, 28 Mar 2025 19:37:35 +0100 Subject: [PATCH 04/29] Store where Processing is installed --- app/src/processing/app/Base.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 07e23d36b4..ec51da59de 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -166,6 +166,20 @@ static public void main(final String[] args) { static private void createAndShowGUI(String[] args) { // these times are fairly negligible relative to Base. // long t1 = System.currentTimeMillis(); + var preferences = java.util.prefs.Preferences.userRoot().node("org/processing/app"); + var installLocations = new ArrayList<>(List.of(preferences.get("installLocations", "").split(","))); + var installLocation = System.getProperty("user.dir") + "^" + Base.getVersionName(); + + // Check if the installLocation is already in the list + if (!installLocations.contains(installLocation)) { + // Add the installLocation to the list + installLocations.add(installLocation); + + // Save the updated list back to preferences + preferences.put("installLocations", String.join(",", installLocations)); + } + // TODO: Cleanup old locations if no longer installed + // TODO: Cleanup old locations if current version is installed in the same location File versionFile = Platform.getContentFile("lib/version.txt"); if (versionFile != null && versionFile.exists()) { From 19c6f65ef18e525c39dadea93651d126cfcb8275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20de=20Courville?= Date: Sat, 5 Apr 2025 15:52:28 +0200 Subject: [PATCH 05/29] Adding steps about IntelliJ project safety and Gradle imports --- BUILD.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/BUILD.md b/BUILD.md index b73147e8bf..8172a5313d 100644 --- a/BUILD.md +++ b/BUILD.md @@ -8,6 +8,8 @@ First, [download the IntelliJ IDEA Community Edition](https://www.jetbrains.com/ 1. Clone the Processing4 repository to your machine locally 1. Open the cloned repository in IntelliJ IDEA CE +1. When prompted, select **Trust Project**. You can preview the project in Safe Mode but you won't be able to build Processing. +1. IntelliJ may start loading Gradle dependencies automatically. Wait for this process to complete. 1. In the main menu, go to File > Project Structure > Project Settings > Project. 1. In the SDK Dropdown option, select a JDK version 17 or Download the jdk 1. Click the green Run Icon in the top right of the window. This is also where you can find the option to debug Processing. From 36945e71e3c687b24e46e6735776a6987e1257d2 Mon Sep 17 00:00:00 2001 From: Konsl <82901383+Konsl@users.noreply.github.com> Date: Mon, 14 Apr 2025 18:09:15 +0200 Subject: [PATCH 06/29] Update PGraphics.java: fix typos in documentation --- core/src/processing/core/PGraphics.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/processing/core/PGraphics.java b/core/src/processing/core/PGraphics.java index 9e3205c69a..a997861a7c 100644 --- a/core/src/processing/core/PGraphics.java +++ b/core/src/processing/core/PGraphics.java @@ -2496,7 +2496,7 @@ protected void curveVertexSegment(float x1, float y1, float z1, *
* Using point() with strokeWeight(1) or smaller may draw nothing to the screen, * depending on the graphics settings of the computer. Workarounds include - * setting the pixel using set() or drawing the point using either + * setting the pixel using set() or drawing the point using either * circle() or square(). * * @webref shape:2d primitives @@ -6439,7 +6439,7 @@ public PStyle getStyle(PStyle s) { // ignore *
* Using point() with strokeWeight(1) or smaller may draw nothing to the screen, * depending on the graphics settings of the computer. Workarounds include - * setting the pixel using set() or drawing the point using either + * setting the pixel using set() or drawing the point using either * circle() or square(). * * @webref shape:attributes From 4924605c8d09da1663feadf48aee0bb0a4b1f39b Mon Sep 17 00:00:00 2001 From: Konsl <82901383+Konsl@users.noreply.github.com> Date: Mon, 14 Apr 2025 18:18:54 +0200 Subject: [PATCH 07/29] Update PGraphics.java: fix more typos --- core/src/processing/core/PGraphics.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/processing/core/PGraphics.java b/core/src/processing/core/PGraphics.java index a997861a7c..22e3e9b6c5 100644 --- a/core/src/processing/core/PGraphics.java +++ b/core/src/processing/core/PGraphics.java @@ -6252,7 +6252,7 @@ public float modelZ(float x, float y, float z) { *

* The style information controlled by the following functions are included * in the style: - * fill(), stroke(), tint(), strokeWeight(), strokeCap(),strokeJoin(), + * fill(), stroke(), tint(), strokeWeight(), strokeCap(),strokeJoin(), * imageMode(), rectMode(), ellipseMode(), shapeMode(), colorMode(), * textAlign(), textFont(), textMode(), textSize(), textLeading(), * emissive(), specular(), shininess(), ambient() From b342feba9ac84482f7cb50786d457dbda97f136a Mon Sep 17 00:00:00 2001 From: Konsl <82901383+Konsl@users.noreply.github.com> Date: Mon, 14 Apr 2025 18:26:44 +0200 Subject: [PATCH 08/29] Update PApplet.java: remove unmatched closing tag --- core/src/processing/core/PApplet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/processing/core/PApplet.java b/core/src/processing/core/PApplet.java index 9f3486a10d..4cb01184b3 100644 --- a/core/src/processing/core/PApplet.java +++ b/core/src/processing/core/PApplet.java @@ -913,7 +913,7 @@ void handleSettings() { * Processing Development Environment (PDE). For example, when * using the Eclipse code editor, it's necessary to use * settings() to define the size() and - * smooth() values for a sketch.. + * smooth() values for a sketch. *

* The settings() method runs before the sketch has been * set up, so other Processing functions cannot be used at that From 056b88b671484742cf7c8eae0f20b5b6731b81fc Mon Sep 17 00:00:00 2001 From: Konsl <82901383+Konsl@users.noreply.github.com> Date: Mon, 14 Apr 2025 18:31:37 +0200 Subject: [PATCH 09/29] Update PGraphics.java: fix swapped html tags --- core/src/processing/core/PGraphics.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/processing/core/PGraphics.java b/core/src/processing/core/PGraphics.java index 22e3e9b6c5..0b9f0d2ed4 100644 --- a/core/src/processing/core/PGraphics.java +++ b/core/src/processing/core/PGraphics.java @@ -3559,8 +3559,8 @@ public float curvePoint(float a, float b, float c, float d, float t) { /** * Calculates the tangent of a point on a curve. There's a good definition - * of tangent on Wikipedia. + * of tangent on Wikipedia. * *

Advanced

* Code thanks to Dave Bollinger (Bug #715) From c86a162f69a173988a45271710320d22f855db41 Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Tue, 15 Apr 2025 16:08:23 +0200 Subject: [PATCH 10/29] Move populateSketchbookMenu to a separate thread --- app/src/processing/app/Base.java | 38 ++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 07e23d36b4..4578336ed5 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -1942,18 +1942,20 @@ public void rebuildSketchbook() { public void populateSketchbookMenu(JMenu menu) { - boolean found = false; - try { - found = addSketches(menu, sketchbookFolder); - } catch (Exception e) { - Messages.showWarning("Sketchbook Menu Error", - "An error occurred while trying to list the sketchbook.", e); - } - if (!found) { - JMenuItem empty = new JMenuItem(Language.text("menu.file.sketchbook.empty")); - empty.setEnabled(false); - menu.add(empty); - } + new Thread(() -> { + boolean found = false; + try { + found = addSketches(menu, sketchbookFolder); + } catch (Exception e) { + Messages.showWarning("Sketchbook Menu Error", + "An error occurred while trying to list the sketchbook.", e); + } + if (!found) { + JMenuItem empty = new JMenuItem(Language.text("menu.file.sketchbook.empty")); + empty.setEnabled(false); + menu.add(empty); + } + }).start(); } @@ -1964,11 +1966,17 @@ public void populateSketchbookMenu(JMenu menu) { * sketch should open in a new window. */ protected boolean addSketches(JMenu menu, File folder) { + Messages.log("scanning " + folder.getAbsolutePath()); // skip .DS_Store files, etc. (this shouldn't actually be necessary) if (!folder.isDirectory()) { return false; } + // Don't look inside the 'android' folders in the sketchbook + if (folder.getName().equals("android")) { + return false; + } + if (folder.getName().equals("libraries")) { return false; // let's not go there } @@ -2054,6 +2062,7 @@ protected boolean addSketches(JMenu menu, File folder) { */ public boolean addSketches(DefaultMutableTreeNode node, File folder, boolean examples) throws IOException { + Messages.log("scanning " + folder.getAbsolutePath()); // skip .DS_Store files, etc. (this shouldn't actually be necessary) if (!folder.isDirectory()) { return false; @@ -2061,6 +2070,11 @@ public boolean addSketches(DefaultMutableTreeNode node, File folder, final String folderName = folder.getName(); + // Don't look inside the 'android' folders in the sketchbook + if (folderName.equals("android")) { + return false; + } + // Don't look inside the 'libraries' folders in the sketchbook if (folderName.equals("libraries")) { return false; From 73d3aeb05041265410828987e30bb12448dd938f Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Tue, 15 Apr 2025 18:05:52 +0200 Subject: [PATCH 11/29] Change the default display density --- core/src/processing/core/PApplet.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/processing/core/PApplet.java b/core/src/processing/core/PApplet.java index 9f3486a10d..cbb70aa2e1 100644 --- a/core/src/processing/core/PApplet.java +++ b/core/src/processing/core/PApplet.java @@ -10105,6 +10105,8 @@ static public void runSketch(final String[] args, sketch.present = present; sketch.fullScreen = fullScreen; + sketch.pixelDensity = sketch.displayDensity(); + // For 3.0.1, moved this above handleSettings() so that loadImage() can be // used inside settings(). Sets a terrible precedent, but the alternative // of not being able to size a sketch to an image is driving people loopy. From b320165d432bb75de1285a9a15574fffbf94fc10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20de=20Courville?= Date: Tue, 15 Apr 2025 18:25:27 +0200 Subject: [PATCH 12/29] Fixed the link to changelog --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ae46f06fcb..469f6913a5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This repository contains the source code for the [Processing](https://processing ## Welcome to Processing 4.4! -We’re excited to announce the release of Processing 4.4! While our last big release focused on tooling and developer experience, this update modernizes Processing under the hood to make future development easier. Key changes include switching the build system from Ant to Gradle, starting the transition to Jetpack Compose Multiplatform for the UI, and adding Kotlin support to the codebase. To learn more, check out [Changes in 4.4.0](https://github.com/processing/processing4/wiki/Changes-in-4.4.0). +We’re excited to announce the release of Processing 4.4! While our last big release focused on tooling and developer experience, this update modernizes Processing under the hood to make future development easier. Key changes include switching the build system from Ant to Gradle, starting the transition to Jetpack Compose Multiplatform for the UI, and adding Kotlin support to the codebase. To learn more, check out [Changes in 4.4.0](https://github.com/processing/processing4/wiki/Changes-in-4.4). We hope these updates will make it easier for more people to contribute to Processing. If you'd like to get involved, have a look at our [Contributor Guide](CONTRIBUTING.md). From 86bee0387a737c798ebcca7a1b7e6f0cd16cd5b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20de=20Courville?= Date: Tue, 15 Apr 2025 18:27:24 +0200 Subject: [PATCH 13/29] Tightened update paragraph --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 469f6913a5..c7169e4f79 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This repository contains the source code for the [Processing](https://processing ## Welcome to Processing 4.4! -We’re excited to announce the release of Processing 4.4! While our last big release focused on tooling and developer experience, this update modernizes Processing under the hood to make future development easier. Key changes include switching the build system from Ant to Gradle, starting the transition to Jetpack Compose Multiplatform for the UI, and adding Kotlin support to the codebase. To learn more, check out [Changes in 4.4.0](https://github.com/processing/processing4/wiki/Changes-in-4.4). +We’re excited to announce the release of Processing 4.4! This update modernizes Processing under the hood to make future development easier. Key changes include switching the build system from Ant to Gradle, starting the transition from Swing to Jetpack Compose Multiplatform for the UI, and adding Kotlin support to the codebase. To learn more, check out [Changes in 4.4.0](https://github.com/processing/processing4/wiki/Changes-in-4.4). We hope these updates will make it easier for more people to contribute to Processing. If you'd like to get involved, have a look at our [Contributor Guide](CONTRIBUTING.md). From f469a78b36131028955f6ea4525c8bb046bf435c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20de=20Courville?= Date: Tue, 15 Apr 2025 18:32:01 +0200 Subject: [PATCH 14/29] Update README.md fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f93d186ae6..a69c9a4e71 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ We’re excited to announce the release of Processing 4.4! This update modernize We hope these updates will make it easier for more people to contribute to Processing. If you'd like to get involved, have a look at our [Contributor Guide](CONTRIBUTING.md). ## Acknowledgement -Processing was initiated in 2001 by Ben Fry and Casey Reas, who lead the development and maintenance of the project until 2023. We are grateful for their vision and dedication to the project. Processing is also indebted to over two decades of contributions from the broader Processing community. +Processing was initiated in 2001 by Ben Fry and Casey Reas, who led the development and maintenance of the project until 2023. We are grateful for their vision and dedication to the project. Processing is also indebted to over two decades of contributions from the broader Processing community. ## Using Processing From 2a2750d190d6897cf22e57a574490d96159f151c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20de=20Courville?= Date: Tue, 15 Apr 2025 18:46:53 +0200 Subject: [PATCH 15/29] Update CONTRIBUTING.md Clearer explanations on new features, libraries, and decision making --- CONTRIBUTING.md | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d90e5fa58a..f542aeef4b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,22 +69,37 @@ If there hasn’t been any activity after two weeks, feel free to gently follow Before opening a pull request, please make sure to discuss the related issue and get assigned to it first. This helps us stay aligned and avoid unnecessary work. Thank you! -## New Features +## Adding New Features to Processing -In most cases, the best way to contribute a new feature is to create a library. The [Processing Library Template](https://github.com/processing/processing-library-template) is a great way to get started. For more instructions, see the [library template documentation](https://processing.github.io/processing-library-template/). +If you have an idea for something Processing doesn’t yet support, **creating a library** is often the best way to contribute. The [Processing Library Template](https://github.com/processing/processing-library-template) provides a starting point for developing, packaging, and distributing Processing libraries. For more instructions, see the [library template documentation](https://processing.github.io/processing-library-template/). +Once your library is complete, you can submit it to the official [Processing Contributions](https://github.com/processing/processing-contributions) repository. This makes it discoverable through the PDE’s Contribution Manager. Follow the guidelines in the [Processing Library Guidelines](https://github.com/processing/processing4/wiki/Library-Guidelines). + +### Libraries as the Starting Point for Features Nearly all new features are first introduced as a Library or a Mode, or even as an example. The current [OpenGL renderer](http://glgraphics.sourceforge.net/) and Video library began as separate projects by Andrés Colubri, who needed a more performant, more sophisticated version of what we had in Processing for work that he was creating. The original `loadShape()` implementation came from the “Candy” library by Michael Chang (“mflux“). Similarly, Tweak Mode began as a [separate project](http://galsasson.com/tweakmode/) by Gal Sasson before being incorporated. PDE X was a Google Summer of code [project](https://github.com/processing/processing-experimental) by Manindra Moharana that updated the PDE to include basic refactoring and better error checking. -Developing features separately from the main software has several benefits: +### Why Develop Outside the Core? +Working outside the main Processing codebase has several advantages: * It’s easier for the contributor to develop the software without it needing to work for tens or hundreds of thousands of Processing users. * It provides a way to get feedback on that code independently of everything else, and the ability to iterate on it rapidly. * This feedback process also helps gauge the level of interest for the community, and how it should be prioritized for the software. * We can delay the process of “normalizing” the features so that they’re consistent with the rest of Processing (function naming, structure, etc). -A major consideration for any new feature is the level of maintenance that it might require in the future. If the original maintainer loses interest over time (which is normal) and the feature breaks (which happens more often than we'd like), it sits on the issues list unfixed, which isn’t good for anyone. +### What Guides the Inclusion of New Features? +We take maintenance seriously. A feature added to the core becomes a long-term responsibility. If it breaks, it needs fixing. Sometimes the original developer is no longer active (which is normal), and the burden falls on others. + +Processing is a massive project that has existed for more than 20 years. Part of its longevity comes from the effort that’s gone into keeping things as simple as we can, and in particular, making a lot of difficult decisions about *what to leave out*. + +Adding a new feature always has to be weighed against the potential confusion of one more thing—whether it’s a menu item, a dialog box, a function that needs to be added to the reference, etc. Adding a new graphics function means making it work across all the renderers that we ship (Java2D, OpenGL, JavaFX, PDF, etc) and across platforms (macOS, Windows, Linux). + +It may also mean new interface elements, updates to the reference, and more documentation. + +So when we consider a new feature, we ask ourselves: + +> Does this solve a problem for many users? Is it worth the added complexity and extra maintenance work? -Processing is a massive project that has existed for more than 20 years. Part of its longevity comes from the effort that’s gone into keeping things as simple as we can, and in particular, making a lot of difficult decisions about *what to leave out*. Adding a new feature always has to be weighed against the potential confusion of one more thing—whether it’s a menu item, a dialog box, a function that needs to be added to the reference, etc. Adding a new graphics function means making it work across all the renderers that we ship (Java2D, OpenGL, JavaFX, PDF, etc) and across platforms (macOS, Windows, Linux). Does the feature help enough people that it's worth making the reference longer? Or the additional burden of maintaining that feature? It's no fun to say “no,” especially to people volunteering their time, but we often have to. +These are not easy decisions, especially when volunteers are offering their time and ideas. But we have to make them carefully to keep Processing sustainable. ## Editor From fd571d13d5e12de0ca196a13c5890cdd787ba8b5 Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Fri, 18 Apr 2025 17:42:31 +0200 Subject: [PATCH 16/29] Initial Command Line structure --- app/build.gradle.kts | 5 +- app/src/processing/app/Processing.kt | 70 +++++++++++++++++++ core/examples/src/main/java/Basic.java | 15 +++- .../mode/java/lsp/PdeLanguageServer.java | 2 +- 4 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 app/src/processing/app/Processing.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 865296d135..f02a511ccd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -47,7 +47,7 @@ sourceSets{ compose.desktop { application { - mainClass = "processing.app.ui.Start" + mainClass = "processing.app.ProcessingKt" jvmArgs(*listOf( Pair("processing.version", rootProject.version), @@ -97,6 +97,7 @@ compose.desktop { dependencies { implementation(project(":core")) + runtimeOnly(project(":java")) implementation(libs.flatlaf) @@ -121,6 +122,8 @@ dependencies { testImplementation(libs.mockitoKotlin) testImplementation(libs.junitJupiter) testImplementation(libs.junitJupiterParams) + + implementation("com.github.ajalt.clikt:clikt:5.0.2") } tasks.test { diff --git a/app/src/processing/app/Processing.kt b/app/src/processing/app/Processing.kt new file mode 100644 index 0000000000..82f89572dd --- /dev/null +++ b/app/src/processing/app/Processing.kt @@ -0,0 +1,70 @@ +package processing.app + +import com.github.ajalt.clikt.command.SuspendingCliktCommand +import com.github.ajalt.clikt.command.main +import com.github.ajalt.clikt.core.Context +import com.github.ajalt.clikt.core.subcommands +import com.github.ajalt.clikt.parameters.options.flag +import com.github.ajalt.clikt.parameters.options.option +import processing.app.ui.Start + +// TODO: Allow Start to run on no args +// TODO: Modify InstallCommander to use the new structure +// TODO: Move dependency to gradle toml +// TODO: Add the options/arguments for Base arguments +class Processing(val args: Array): SuspendingCliktCommand(name = "Processing"){ + override suspend fun run() { + if(currentContext.invokedSubcommand == null){ + Start.main(args) + } + } +} + +suspend fun main(args: Array) = Processing(args) + .subcommands( + LSP(args), + LegacyCLI(args) + ) + .main(args) + + +class LSP(val args: Array): SuspendingCliktCommand("lsp"){ + override fun help(context: Context) = "Start the Processing Language Server" + override suspend fun run(){ + try { + // Indirect invocation since app does not depend on java mode + Class.forName("processing.mode.java.lsp.PdeLanguageServer") + .getMethod("main", Array::class.java) + .invoke(null, *arrayOf(args)) + } catch (e: Exception) { + throw InternalError("Failed to invoke main method", e) + } + } +} + +class LegacyCLI(val args: Array): SuspendingCliktCommand(name = "cli"){ + override fun help(context: Context) = "Legacy processing-java command line interface" + + val help by option("--help").flag() + val build by option("--build").flag() + val run by option("--run").flag() + val present by option("--present").flag() + val sketch: String? by option("--sketch") + val force by option("--force").flag() + val output: String? by option("--output") + val export by option("--export").flag() + val noJava by option("--no-java").flag() + val variant: String? by option("--variant") + + override suspend fun run(){ + val cliArgs = args.filter { it != "cli" }.toTypedArray() + try { + // Indirect invocation since app does not depend on java mode + Class.forName("processing.mode.java.Commander") + .getMethod("main", Array::class.java) + .invoke(null, *arrayOf(cliArgs)) + } catch (e: Exception) { + throw InternalError("Failed to invoke main method", e) + } + } +} \ No newline at end of file diff --git a/core/examples/src/main/java/Basic.java b/core/examples/src/main/java/Basic.java index 379bb4b306..7c5a72cba2 100644 --- a/core/examples/src/main/java/Basic.java +++ b/core/examples/src/main/java/Basic.java @@ -1,12 +1,25 @@ import processing.core.PApplet; +import java.io.IOException; + public class Basic extends PApplet { public void settings(){ size(500, 500); + + try { + Runtime.getRuntime().exec("echo Hello World"); + } catch (IOException e) { + throw new RuntimeException(e); + } } public void draw(){ - ellipse(width / 2f, height / 2f, 125f, 125f); + background(255); + fill(0); + ellipse(mouseX, mouseY, 125f, 125f); + println(frameRate); + + } diff --git a/java/src/processing/mode/java/lsp/PdeLanguageServer.java b/java/src/processing/mode/java/lsp/PdeLanguageServer.java index 3d865fcc7b..0673b48231 100644 --- a/java/src/processing/mode/java/lsp/PdeLanguageServer.java +++ b/java/src/processing/mode/java/lsp/PdeLanguageServer.java @@ -21,7 +21,7 @@ import org.eclipse.lsp4j.services.LanguageClient; -class PdeLanguageServer implements LanguageServer, LanguageClientAware { +public class PdeLanguageServer implements LanguageServer, LanguageClientAware { Map adapters = new HashMap<>(); LanguageClient client = null; PdeTextDocumentService textDocumentService = new PdeTextDocumentService(this); From 0121c75ef9de9fe8c4d8dd25ec53b4cdbea9329e Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Fri, 18 Apr 2025 23:24:39 +0200 Subject: [PATCH 17/29] Add `removable-media` as a Snap Plug Fixes #1051 I referenced the Firefox snap configuration and they also defined the `removable-media` plug so it makes sense to me that we should also support it. --- app/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 865296d135..715be42d5c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -240,6 +240,7 @@ tasks.register("generateSnapConfiguration"){ - network - opengl - home + - removable-media parts: processing: From 51c9734d2ae28fa4f86f4638db39ba701d079cea Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Sat, 19 Apr 2025 09:34:06 +0200 Subject: [PATCH 18/29] Refined Command Line Structure --- app/build.gradle.kts | 2 +- app/src/processing/app/Processing.kt | 45 ++++++++------ .../app/tools/InstallCommander.java | 59 +++++++++++-------- gradle/libs.versions.toml | 1 + 4 files changed, 63 insertions(+), 44 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f02a511ccd..f3da7263f1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -123,7 +123,7 @@ dependencies { testImplementation(libs.junitJupiter) testImplementation(libs.junitJupiterParams) - implementation("com.github.ajalt.clikt:clikt:5.0.2") + implementation(libs.clikt) } tasks.test { diff --git a/app/src/processing/app/Processing.kt b/app/src/processing/app/Processing.kt index 82f89572dd..498d63b210 100644 --- a/app/src/processing/app/Processing.kt +++ b/app/src/processing/app/Processing.kt @@ -4,45 +4,49 @@ import com.github.ajalt.clikt.command.SuspendingCliktCommand import com.github.ajalt.clikt.command.main import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.subcommands +import com.github.ajalt.clikt.parameters.arguments.argument +import com.github.ajalt.clikt.parameters.arguments.multiple import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import processing.app.ui.Start -// TODO: Allow Start to run on no args -// TODO: Modify InstallCommander to use the new structure -// TODO: Move dependency to gradle toml -// TODO: Add the options/arguments for Base arguments -class Processing(val args: Array): SuspendingCliktCommand(name = "Processing"){ +class Processing: SuspendingCliktCommand("processing"){ + val sketches by argument().multiple(default = emptyList()) + + override fun help(context: Context) = "Start the Processing IDE" + override val invokeWithoutSubcommand = true override suspend fun run() { - if(currentContext.invokedSubcommand == null){ - Start.main(args) + val subcommand = currentContext.invokedSubcommand + if (subcommand == null) { + Start.main(sketches.toTypedArray()) } } } -suspend fun main(args: Array) = Processing(args) - .subcommands( - LSP(args), - LegacyCLI(args) - ) - .main(args) - +suspend fun main(args: Array){ + Processing() + .subcommands( + LSP(), + LegacyCLI(args) + ) + .main(args) +} -class LSP(val args: Array): SuspendingCliktCommand("lsp"){ +class LSP: SuspendingCliktCommand("lsp"){ override fun help(context: Context) = "Start the Processing Language Server" override suspend fun run(){ try { // Indirect invocation since app does not depend on java mode Class.forName("processing.mode.java.lsp.PdeLanguageServer") .getMethod("main", Array::class.java) - .invoke(null, *arrayOf(args)) + .invoke(null, *arrayOf(emptyList())) } catch (e: Exception) { throw InternalError("Failed to invoke main method", e) } } } -class LegacyCLI(val args: Array): SuspendingCliktCommand(name = "cli"){ +class LegacyCLI(val args: Array): SuspendingCliktCommand( "cli"){ override fun help(context: Context) = "Legacy processing-java command line interface" val help by option("--help").flag() @@ -57,12 +61,15 @@ class LegacyCLI(val args: Array): SuspendingCliktCommand(name = "cli"){ val variant: String? by option("--variant") override suspend fun run(){ - val cliArgs = args.filter { it != "cli" }.toTypedArray() + val cliArgs = args.filter { it != "cli" } try { + if(build){ + System.setProperty("java.awt.headless", "true") + } // Indirect invocation since app does not depend on java mode Class.forName("processing.mode.java.Commander") .getMethod("main", Array::class.java) - .invoke(null, *arrayOf(cliArgs)) + .invoke(null, *arrayOf(cliArgs.toTypedArray())) } catch (e: Exception) { throw InternalError("Failed to invoke main method", e) } diff --git a/app/src/processing/app/tools/InstallCommander.java b/app/src/processing/app/tools/InstallCommander.java index cd136c3621..33eabc6f68 100644 --- a/app/src/processing/app/tools/InstallCommander.java +++ b/app/src/processing/app/tools/InstallCommander.java @@ -86,30 +86,41 @@ public void run() { PrintWriter writer = PApplet.createWriter(file); writer.print("#!/bin/sh\n\n"); - writer.print("# Prevents processing-java from stealing focus, see:\n" + - "# https://github.com/processing/processing/issues/3996.\n" + - "OPTION_FOR_HEADLESS_RUN=\"\"\n" + - "for ARG in \"$@\"\n" + - "do\n" + - " if [ \"$ARG\" = \"--build\" ]; then\n" + - " OPTION_FOR_HEADLESS_RUN=\"-Djava.awt.headless=true\"\n" + - " fi\n" + - "done\n\n"); - - String javaRoot = Platform.getContentFile(".").getCanonicalPath(); - - StringList jarList = new StringList(); - addJarList(jarList, new File(javaRoot)); - addJarList(jarList, new File(javaRoot, "core/library")); - addJarList(jarList, new File(javaRoot, "modes/java/mode")); - String classPath = jarList.join(":").replaceAll(javaRoot + "\\/?", ""); - - writer.println("cd \"" + javaRoot + "\" && " + - Platform.getJavaPath().replaceAll(" ", "\\\\ ") + - " -Djna.nosys=true" + - " $OPTION_FOR_HEADLESS_RUN" + - " -cp \"" + classPath + "\"" + - " processing.mode.java.Commander \"$@\""); + var resourcesDir = System.getProperty("compose.application.resources.dir"); + if(resourcesDir != null) { + // Gradle based distributable + var appBinary = (resourcesDir + .split("\\.app")[0] + ".app/Contents/MacOS/Processing") + .replaceAll(" ", "\\\\ "); + writer.print(appBinary + " cli $@"); + + } else { + // Ant based distributable + writer.print("# Prevents processing-java from stealing focus, see:\n" + + "# https://github.com/processing/processing/issues/3996.\n" + + "OPTION_FOR_HEADLESS_RUN=\"\"\n" + + "for ARG in \"$@\"\n" + + "do\n" + + " if [ \"$ARG\" = \"--build\" ]; then\n" + + " OPTION_FOR_HEADLESS_RUN=\"-Djava.awt.headless=true\"\n" + + " fi\n" + + "done\n\n"); + + String javaRoot = Platform.getContentFile(".").getCanonicalPath(); + + StringList jarList = new StringList(); + addJarList(jarList, new File(javaRoot)); + addJarList(jarList, new File(javaRoot, "core/library")); + addJarList(jarList, new File(javaRoot, "modes/java/mode")); + String classPath = jarList.join(":").replaceAll(javaRoot + "\\/?", ""); + + writer.println("cd \"" + javaRoot + "\" && " + + Platform.getJavaPath().replaceAll(" ", "\\\\ ") + + " -Djna.nosys=true" + + " $OPTION_FOR_HEADLESS_RUN" + + " -cp \"" + classPath + "\"" + + " processing.mode.java.Commander \"$@\""); + } writer.flush(); writer.close(); file.setExecutable(true); diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a9fe0b6e52..70f93aaff5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -27,6 +27,7 @@ lsp4j = { module = "org.eclipse.lsp4j:org.eclipse.lsp4j", version = "0.22.0" } jsoup = { module = "org.jsoup:jsoup", version = "1.17.2" } markdown = { module = "com.mikepenz:multiplatform-markdown-renderer-m2", version = "0.31.0" } markdownJVM = { module = "com.mikepenz:multiplatform-markdown-renderer-jvm", version = "0.31.0" } +clikt = { module = "com.github.ajalt.clikt:clikt", version = "5.0.2" } [plugins] jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" } From 30fd531a446c661809345fe1d487a0fbf701528b Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Sat, 19 Apr 2025 09:54:15 +0200 Subject: [PATCH 19/29] Improving documentation --- app/src/processing/app/Processing.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/processing/app/Processing.kt b/app/src/processing/app/Processing.kt index 498d63b210..9e7324dd3c 100644 --- a/app/src/processing/app/Processing.kt +++ b/app/src/processing/app/Processing.kt @@ -5,13 +5,16 @@ import com.github.ajalt.clikt.command.main import com.github.ajalt.clikt.core.Context import com.github.ajalt.clikt.core.subcommands import com.github.ajalt.clikt.parameters.arguments.argument +import com.github.ajalt.clikt.parameters.arguments.help import com.github.ajalt.clikt.parameters.arguments.multiple import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import processing.app.ui.Start class Processing: SuspendingCliktCommand("processing"){ - val sketches by argument().multiple(default = emptyList()) + val sketches by argument() + .multiple(default = emptyList()) + .help("Sketches to open") override fun help(context: Context) = "Start the Processing IDE" override val invokeWithoutSubcommand = true From 036d01e90dae7711523715a45a2195c7b6043ad6 Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Sat, 19 Apr 2025 12:28:24 +0200 Subject: [PATCH 20/29] Added version option --- app/src/processing/app/Processing.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/processing/app/Processing.kt b/app/src/processing/app/Processing.kt index 9e7324dd3c..11555edf53 100644 --- a/app/src/processing/app/Processing.kt +++ b/app/src/processing/app/Processing.kt @@ -8,10 +8,15 @@ import com.github.ajalt.clikt.parameters.arguments.argument import com.github.ajalt.clikt.parameters.arguments.help import com.github.ajalt.clikt.parameters.arguments.multiple import com.github.ajalt.clikt.parameters.options.flag +import com.github.ajalt.clikt.parameters.options.help import com.github.ajalt.clikt.parameters.options.option import processing.app.ui.Start class Processing: SuspendingCliktCommand("processing"){ + val version by option("-v","--version") + .flag() + .help("Print version information") + val sketches by argument() .multiple(default = emptyList()) .help("Sketches to open") @@ -19,6 +24,11 @@ class Processing: SuspendingCliktCommand("processing"){ override fun help(context: Context) = "Start the Processing IDE" override val invokeWithoutSubcommand = true override suspend fun run() { + if(version){ + println("processing-${Base.getVersionName()}-${Base.getRevision()}") + return + } + val subcommand = currentContext.invokedSubcommand if (subcommand == null) { Start.main(sketches.toTypedArray()) From 7551eca7c278c7c47d52eee7d6d9161574558b94 Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Sat, 19 Apr 2025 12:36:42 +0200 Subject: [PATCH 21/29] Change for `includeJDK` to grab the running JDK --- app/build.gradle.kts | 57 ++++++++++------------------ app/src/processing/app/Platform.java | 11 ++---- build/shared/include.jdk | 0 3 files changed, 25 insertions(+), 43 deletions(-) create mode 100644 build/shared/include.jdk diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 865296d135..215f43e5c5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,3 +1,4 @@ +import org.gradle.internal.jvm.Jvm import org.gradle.kotlin.dsl.support.zipTo import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform import org.jetbrains.compose.desktop.application.dsl.TargetFormat @@ -250,7 +251,6 @@ tasks.register("generateSnapConfiguration"){ - openjdk-17-jre override-prime: | snapcraftctl prime - chmod -R +x opt/processing/lib/app/resources/jdk-* rm -vf usr/lib/jvm/java-17-openjdk-*/lib/security/cacerts """.trimIndent() dir.file("../snapcraft.yaml").asFile.writeText(content) @@ -322,40 +322,26 @@ tasks.register("includeJavaMode") { into(composeResources("modes/java/mode")) duplicatesStrategy = DuplicatesStrategy.EXCLUDE } -tasks.register("includeJdk") { - val os = DefaultNativePlatform.getCurrentOperatingSystem() - val arch = when (System.getProperty("os.arch")) { - "amd64", "x86_64" -> "x64" - else -> System.getProperty("os.arch") - } - val platform = when { - os.isWindows -> "windows" - os.isMacOsX -> "mac" - else -> "linux" - } - - val javaVersion = System.getProperty("java.version").split(".")[0] - val imageType = "jdk" - - src("https://api.adoptium.net/v3/binary/latest/" + - "$javaVersion/ga/" + - "$platform/" + - "$arch/" + - "$imageType/" + - "hotspot/normal/eclipse?project=jdk") - - val extension = if (os.isWindows) "zip" else "tar.gz" - val jdk = layout.buildDirectory.file("tmp/jdk-$platform-$arch.$extension") - dest(jdk) - overwrite(false) - doLast { - copy { - val archive = if (os.isWindows) { zipTree(jdk) } else { tarTree(jdk) } - from(archive){ eachFile{ permissions{ unix("755") } } } - into(composeResources("")) +tasks.register("includeJdk") { + dependsOn("createDistributable") + doFirst { + val jdk = Jvm.current().javaHome.absolutePath + val target = layout.buildDirectory.dir("compose/binaries").get().asFileTree.matching { include("**/include.jdk") } + .files + .firstOrNull() + ?.parentFile + ?.resolve("jdk") + ?.absolutePath + ?: error("Could not find include.jdk") + + val isWindows = System.getProperty("os.name").lowercase().contains("win") + val command = if (isWindows) { + listOf("xcopy", "/E", "/I", "/Q", jdk, target) + } else { + listOf("cp", "-a", jdk, target) } + ProcessBuilder(command).inheritIO().start().waitFor() } - finalizedBy("prepareAppResources") } tasks.register("includeSharedAssets"){ from("../build/shared/") @@ -427,7 +413,6 @@ tasks.register("signResources"){ dependsOn( "includeCore", "includeJavaMode", - "includeJdk", "includeSharedAssets", "includeProcessingExamples", "includeProcessingWebsiteExamples", @@ -540,7 +525,7 @@ afterEvaluate { } } tasks.named("createDistributable").configure { - dependsOn("signResources", "includeJdk") - finalizedBy("setExecutablePermissions") + dependsOn("signResources") + finalizedBy( "includeJdk","setExecutablePermissions") } } diff --git a/app/src/processing/app/Platform.java b/app/src/processing/app/Platform.java index 2af96bfd12..b911d7e0ae 100644 --- a/app/src/processing/app/Platform.java +++ b/app/src/processing/app/Platform.java @@ -391,17 +391,14 @@ static public File getContentFile(String name) { static public File getJavaHome() { var resourcesDir = System.getProperty("compose.application.resources.dir"); if(resourcesDir != null) { - var jdkFolder = Arrays.stream(new File(resourcesDir).listFiles((dir, name) -> dir.isDirectory() && name.startsWith("jdk-"))) - .findFirst() - .orElse(null); - if(Platform.isMacOS()){ - return new File(jdkFolder, "Contents/Home"); - } + var jdkFolder = new File(resourcesDir,"jdk"); + if(jdkFolder.exists()){ return jdkFolder; + } } var home = System.getProperty("java.home"); - if(home != null && new File(home, "bin/java").exists()){ + if(home != null){ return new File(home); } if (Platform.isMacOS()) { diff --git a/build/shared/include.jdk b/build/shared/include.jdk new file mode 100644 index 0000000000..e69de29bb2 From 03723be0159bf5ae77eedaaa5fe5e307052bc1c2 Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Sun, 20 Apr 2025 16:05:36 +0200 Subject: [PATCH 22/29] Added missing module --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 865296d135..ff551706f9 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -59,7 +59,7 @@ compose.desktop { ).map { "-D${it.first}=${it.second}" }.toTypedArray()) nativeDistributions{ - modules("jdk.jdi", "java.compiler", "jdk.accessibility", "java.management.rmi") + modules("jdk.jdi", "java.compiler", "jdk.accessibility", "java.management.rmi", "java.scripting") targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) packageName = "Processing" From 858c6b6b149ddfcad18c77b41a69b045c731d6fb Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Tue, 22 Apr 2025 13:51:00 +0200 Subject: [PATCH 23/29] Fix error with macOS builds not being completely signed --- app/build.gradle.kts | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 215f43e5c5..aadb1715fd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,10 +1,8 @@ import org.gradle.internal.jvm.Jvm -import org.gradle.kotlin.dsl.support.zipTo import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform import org.jetbrains.compose.desktop.application.dsl.TargetFormat import org.jetbrains.compose.desktop.application.tasks.AbstractJPackageTask import org.jetbrains.compose.internal.de.undercouch.gradle.tasks.download.Download -import org.jetbrains.kotlin.fir.scopes.impl.overrides import java.io.FileOutputStream import java.util.zip.ZipEntry import java.util.zip.ZipOutputStream @@ -279,12 +277,13 @@ tasks.register("zipDistributable"){ } afterEvaluate{ + // Override the default DMG task to use our custom one tasks.named("packageDmg").configure{ dependsOn("packageCustomDmg") group = "compose desktop" actions = emptyList() } - + // Override the default MSI task to use our custom one tasks.named("packageMsi").configure{ dependsOn("packageCustomMsi") group = "compose desktop" @@ -335,12 +334,26 @@ tasks.register("includeJdk") { ?: error("Could not find include.jdk") val isWindows = System.getProperty("os.name").lowercase().contains("win") + val isMacOS = System.getProperty("os.name").lowercase().contains("mac") val command = if (isWindows) { listOf("xcopy", "/E", "/I", "/Q", jdk, target) } else { listOf("cp", "-a", jdk, target) } ProcessBuilder(command).inheritIO().start().waitFor() + + if(org.gradle.internal.os.OperatingSystem.current().isMacOsX + && compose.desktop.application.nativeDistributions.macOS.notarization.appleID.isPresent + ) { + // Sign the main binary again since changed it. + val app = layout.buildDirectory.dir("compose/binaries").get().asFileTree.matching { include("**/*.app") } + .files + .firstOrNull() + ?.parentFile ?: error("Could not find Info.plist") + val signCommand = listOf("codesign", "--timestamp", "--force", "--deep","--options=runtime", "--sign", "Developer ID Application", app.absolutePath) + ProcessBuilder(signCommand).inheritIO().start().waitFor() + } + } } tasks.register("includeSharedAssets"){ @@ -526,6 +539,6 @@ afterEvaluate { } tasks.named("createDistributable").configure { dependsOn("signResources") - finalizedBy( "includeJdk","setExecutablePermissions") + finalizedBy( "includeJdk", "setExecutablePermissions") } } From 527bdedeafc5ae2cd1ddc77c3822c85a67b861a6 Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Tue, 22 Apr 2025 15:04:51 +0200 Subject: [PATCH 24/29] Switched to a normal copy operation and updated permissions --- app/build.gradle.kts | 145 +++++++++++++++------------------------ build/shared/include.jdk | 0 2 files changed, 55 insertions(+), 90 deletions(-) delete mode 100644 build/shared/include.jdk diff --git a/app/build.gradle.kts b/app/build.gradle.kts index aadb1715fd..63554140b0 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,4 +1,5 @@ import org.gradle.internal.jvm.Jvm +import org.gradle.internal.os.OperatingSystem import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform import org.jetbrains.compose.desktop.application.dsl.TargetFormat import org.jetbrains.compose.desktop.application.tasks.AbstractJPackageTask @@ -135,11 +136,11 @@ tasks.compileJava{ val version = if(project.version == "unspecified") "1.0.0" else project.version tasks.register("installCreateDmg") { - onlyIf { org.gradle.internal.os.OperatingSystem.current().isMacOsX } + onlyIf { OperatingSystem.current().isMacOsX } commandLine("arch", "-arm64", "brew", "install", "--quiet", "create-dmg") } tasks.register("packageCustomDmg"){ - onlyIf { org.gradle.internal.os.OperatingSystem.current().isMacOsX } + onlyIf { OperatingSystem.current().isMacOsX } group = "compose desktop" val distributable = tasks.named("createDistributable").get() @@ -169,8 +170,6 @@ tasks.register("packageCustomDmg"){ extra.add("25") } - commandLine("brew", "install", "--quiet", "create-dmg") - commandLine("create-dmg", "--volname", packageName, "--volicon", file("macos/volume.icns"), @@ -187,7 +186,7 @@ tasks.register("packageCustomDmg"){ } tasks.register("packageCustomMsi"){ - onlyIf { org.gradle.internal.os.OperatingSystem.current().isWindows } + onlyIf { OperatingSystem.current().isWindows } dependsOn("createDistributable") workingDir = file("windows") group = "compose desktop" @@ -203,20 +202,22 @@ tasks.register("packageCustomMsi"){ ) } -val snapname = findProperty("snapname") ?: rootProject.name -val snaparch = when (System.getProperty("os.arch")) { - "amd64", "x86_64" -> "amd64" - "aarch64" -> "arm64" - else -> System.getProperty("os.arch") -} + tasks.register("generateSnapConfiguration"){ - onlyIf { org.gradle.internal.os.OperatingSystem.current().isLinux } + val name = findProperty("snapname") ?: rootProject.name + val arch = when (System.getProperty("os.arch")) { + "amd64", "x86_64" -> "amd64" + "aarch64" -> "arm64" + else -> System.getProperty("os.arch") + } + + onlyIf { OperatingSystem.current().isLinux } val distributable = tasks.named("createDistributable").get() dependsOn(distributable) val dir = distributable.destinationDir.get() val content = """ - name: $snapname + name: $name version: $version base: core22 summary: A creative coding editor @@ -243,7 +244,7 @@ tasks.register("generateSnapConfiguration"){ parts: processing: plugin: dump - source: deb/processing_$version-1_$snaparch.deb + source: deb/processing_$version-1_$arch.deb source-type: deb stage-packages: - openjdk-17-jre @@ -255,7 +256,7 @@ tasks.register("generateSnapConfiguration"){ } tasks.register("packageSnap"){ - onlyIf { org.gradle.internal.os.OperatingSystem.current().isLinux } + onlyIf { OperatingSystem.current().isLinux } dependsOn("packageDeb", "generateSnapConfiguration") group = "compose desktop" @@ -290,7 +291,7 @@ afterEvaluate{ actions = emptyList() } tasks.named("packageDistributionForCurrentOS").configure { - if(org.gradle.internal.os.OperatingSystem.current().isMacOsX + if(OperatingSystem.current().isMacOsX && compose.desktop.application.nativeDistributions.macOS.notarization.appleID.isPresent ){ dependsOn("notarizeDmg") @@ -321,40 +322,9 @@ tasks.register("includeJavaMode") { into(composeResources("modes/java/mode")) duplicatesStrategy = DuplicatesStrategy.EXCLUDE } -tasks.register("includeJdk") { - dependsOn("createDistributable") - doFirst { - val jdk = Jvm.current().javaHome.absolutePath - val target = layout.buildDirectory.dir("compose/binaries").get().asFileTree.matching { include("**/include.jdk") } - .files - .firstOrNull() - ?.parentFile - ?.resolve("jdk") - ?.absolutePath - ?: error("Could not find include.jdk") - - val isWindows = System.getProperty("os.name").lowercase().contains("win") - val isMacOS = System.getProperty("os.name").lowercase().contains("mac") - val command = if (isWindows) { - listOf("xcopy", "/E", "/I", "/Q", jdk, target) - } else { - listOf("cp", "-a", jdk, target) - } - ProcessBuilder(command).inheritIO().start().waitFor() - - if(org.gradle.internal.os.OperatingSystem.current().isMacOsX - && compose.desktop.application.nativeDistributions.macOS.notarization.appleID.isPresent - ) { - // Sign the main binary again since changed it. - val app = layout.buildDirectory.dir("compose/binaries").get().asFileTree.matching { include("**/*.app") } - .files - .firstOrNull() - ?.parentFile ?: error("Could not find Info.plist") - val signCommand = listOf("codesign", "--timestamp", "--force", "--deep","--options=runtime", "--sign", "Developer ID Application", app.absolutePath) - ProcessBuilder(signCommand).inheritIO().start().waitFor() - } - - } +tasks.register("includeJdk") { + from(Jvm.current().javaHome.absolutePath) + destinationDir = composeResources("jdk").get().asFile } tasks.register("includeSharedAssets"){ from("../build/shared/") @@ -400,6 +370,7 @@ tasks.register("includeJavaModeResources") { from(java.layout.buildDirectory.dir("resources-bundled")) into(composeResources("../")) } +// TODO: Move to java mode tasks.register("renameWindres") { dependsOn("includeSharedAssets","includeJavaModeResources") val dir = composeResources("modes/java/application/launch4j/bin/") @@ -416,14 +387,9 @@ tasks.register("renameWindres") { duplicatesStrategy = DuplicatesStrategy.INCLUDE into(dir) } -tasks.register("signResources"){ - onlyIf { - org.gradle.internal.os.OperatingSystem.current().isMacOsX - && - compose.desktop.application.nativeDistributions.macOS.signing.sign.get() - } - group = "compose desktop" +tasks.register("includeProcessingResources"){ dependsOn( + "includeJdk", "includeCore", "includeJavaMode", "includeSharedAssets", @@ -432,12 +398,18 @@ tasks.register("signResources"){ "includeJavaModeResources", "renameWindres" ) - finalizedBy("prepareAppResources") + finalizedBy("signResources") +} +tasks.register("signResources"){ + onlyIf { + OperatingSystem.current().isMacOsX + && + compose.desktop.application.nativeDistributions.macOS.signing.sign.get() + } + group = "compose desktop" val resourcesPath = composeResources("") - - // find jars in the resources directory val jars = mutableListOf() doFirst{ @@ -470,7 +442,7 @@ tasks.register("signResources"){ include("**/*x86_64*") include("**/*ffmpeg*") include("**/ffmpeg*/**") - exclude("jdk-*/**") + exclude("jdk/**") exclude("*.jar") exclude("*.so") exclude("*.dll") @@ -506,39 +478,32 @@ tasks.register("signResources"){ } -afterEvaluate { - tasks.named("prepareAppResources").configure { - dependsOn( - "includeCore", - "includeJavaMode", - "includeSharedAssets", - "includeProcessingExamples", - "includeProcessingWebsiteExamples", - "includeJavaModeResources", - "renameWindres" - ) - } - tasks.register("setExecutablePermissions") { - description = "Sets executable permissions on binaries in Processing.app resources" - group = "compose desktop" +tasks.register("setExecutablePermissions") { + description = "Sets executable permissions on binaries in Processing.app resources" + group = "compose desktop" - doLast { - val resourcesPath = layout.buildDirectory.dir("compose/binaries") - fileTree(resourcesPath) { - include("**/resources/**/bin/**") - include("**/resources/**/*.sh") - include("**/resources/**/*.dylib") - include("**/resources/**/*.so") - include("**/resources/**/*.exe") - }.forEach { file -> - if (file.isFile) { - file.setExecutable(true, false) - } + doLast { + val resourcesPath = layout.buildDirectory.dir("compose/binaries") + fileTree(resourcesPath) { + include("**/resources/**/bin/**") + include("**/resources/**/lib/**") + include("**/resources/**/*.sh") + include("**/resources/**/*.dylib") + include("**/resources/**/*.so") + include("**/resources/**/*.exe") + }.forEach { file -> + if (file.isFile) { + file.setExecutable(true, false) } } } +} + +afterEvaluate { + tasks.named("prepareAppResources").configure { + dependsOn("includeProcessingResources") + } tasks.named("createDistributable").configure { - dependsOn("signResources") - finalizedBy( "includeJdk", "setExecutablePermissions") + finalizedBy("setExecutablePermissions") } } diff --git a/build/shared/include.jdk b/build/shared/include.jdk deleted file mode 100644 index e69de29bb2..0000000000 From 6a6c5c0ddf7b0545af0767e1f3d2d85729fb239d Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Thu, 24 Apr 2025 14:37:24 +0200 Subject: [PATCH 25/29] Added LSP Develop gradle task --- app/build.gradle.kts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 865296d135..decdc5b300 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -133,6 +133,27 @@ tasks.compileJava{ options.encoding = "UTF-8" } +tasks.register("lsp-develop"){ + group = "processing" + // This task is used to run the LSP server when developing the LSP server itself + // to run the LSP server for end-users use `processing lsp` instead + dependencies.add("runtimeOnly", project(":java")) + + // Usage: ./gradlew lsp-develop + // Make sure the cwd is set the project directory + // or use -p to set the project directory + + // Modify run configuration to start the LSP server rather than the Processing IDE + val run = tasks.named("run").get() + run.standardInput = System.`in` + run.standardOutput = System.out + dependsOn(run) + + // TODO: Remove after command line is integrated, then add the `lsp` argument instead, `lsp-develop` can't be removed because we still need to pipe the input and output + run.jvmArgs("-Djava.awt.headless=true") + compose.desktop.application.mainClass = "processing.mode.java.lsp.PdeLanguageServer" +} + val version = if(project.version == "unspecified") "1.0.0" else project.version tasks.register("installCreateDmg") { From 1444f2ffaa3c06fb713077f9802e59885437a5f5 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 25 Apr 2025 09:07:18 +0000 Subject: [PATCH 26/29] docs: update README.md [skip ci] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a69c9a4e71..4ce76574e4 100644 --- a/README.md +++ b/README.md @@ -294,6 +294,7 @@ _Note: due to GitHub's limitations, this repository's [Contributors](https://git Subhraman Sarkar
Subhraman Sarkar

💻 ️️️️♿️ SushantBansal-tech
SushantBansal-tech

🤔 💻 + Konsl
Konsl

📖 From 2976d4a7efb95f0ebc40249486dbdc44cbf014ee Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 25 Apr 2025 09:07:19 +0000 Subject: [PATCH 27/29] docs: update .all-contributorsrc [skip ci] --- .all-contributorsrc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 38341006fa..eea6f9e5e3 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1503,6 +1503,15 @@ "ideas", "code" ] + }, + { + "login": "Konsl", + "name": "Konsl", + "avatar_url": "https://avatars.githubusercontent.com/u/82901383?v=4", + "profile": "https://github.com/Konsl", + "contributions": [ + "doc" + ] } ], "repoType": "github", From 1a2ba32bd3650542df02965c70baf805f30dcf6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20de=20Courville?= Date: Fri, 25 Apr 2025 12:08:32 +0200 Subject: [PATCH 28/29] Update build.gradle.kts typo --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index decdc5b300..f3a34a297a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -140,7 +140,7 @@ tasks.register("lsp-develop"){ dependencies.add("runtimeOnly", project(":java")) // Usage: ./gradlew lsp-develop - // Make sure the cwd is set the project directory + // Make sure the cwd is set to the project directory // or use -p to set the project directory // Modify run configuration to start the LSP server rather than the Processing IDE From c83f44c9d82b29b285775f97de5a8737bd991818 Mon Sep 17 00:00:00 2001 From: Stef Tervelde Date: Fri, 25 Apr 2025 13:57:18 +0200 Subject: [PATCH 29/29] Update PGraphicsOpenGL.java --- core/src/processing/opengl/PGraphicsOpenGL.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index 2d6dca9914..88164f43e1 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -4481,7 +4481,7 @@ public void ortho(float left, float right, // The minus sign is needed to invert the Y axis. projection.set(x, 0, 0, tx, - 0, -y, 0, -ty, + 0, -y, 0, ty, 0, 0, z, tz, 0, 0, 0, 1);