Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
971d98b
Preprocessor with antlr Plugin
Stefterv Jan 30, 2025
f016cc4
Removed core dependency from the pre-processor
Stefterv Feb 5, 2025
23c8a46
- Imports cleanup
Stefterv Feb 3, 2025
5468da0
Removed outdated ant backwards compatibility marks
Stefterv Feb 4, 2025
1b8a8ed
Gradle Plugin from PoC
Stefterv Feb 5, 2025
f4d7fbf
Changed naming
Stefterv Feb 5, 2025
7f00d5b
added example of plugin usage
Stefterv Feb 5, 2025
df745bb
Merge branch 'main-gradle' into gradle/preprocessor
Stefterv Feb 5, 2025
25e147e
Merge branch 'main-gradle' into gradle/plugin
Stefterv Feb 5, 2025
031d304
Merge branch 'main-gradle' into gradle/plugin
Stefterv Feb 5, 2025
e188336
Merge branch 'main-gradle' into gradle/preprocessor
Stefterv Feb 5, 2025
44ab816
disable full screen from settings and fixed a few bugs
Stefterv Feb 5, 2025
da852b4
Fullscreen support
Stefterv Feb 5, 2025
f126d4b
Merge branch 'processing:main' into gradle-plugin
Stefterv Mar 7, 2025
c28a267
Merge branch 'processing:main' into gradle-preprocessor
Stefterv Mar 7, 2025
7e6c97a
Merge branch 'main' into gradle-plugin
Stefterv Mar 17, 2025
743ea14
Merge branch 'main' into gradle-preprocessor
Stefterv Mar 17, 2025
ad5c27e
Apply same parser & lexer fixes from before
Stefterv Mar 17, 2025
b0b12dd
Merge branch 'gradle-preprocessor' into gradle-plugin
Stefterv Mar 17, 2025
e01d02a
Update settings.gradle.kts
Stefterv Mar 17, 2025
ba49656
Adding tests and direct linking
Stefterv Mar 18, 2025
29d76eb
Merge branch 'processing:main' into gradle-plugin
Stefterv Mar 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ bin-test
processing-examples

# Maven ignores
/.kotlin/sessions
.gradle
.build/
core/build/
build/publish/
app/build
Expand All @@ -108,8 +110,11 @@ java/build/
/java/libraries/svg/bin
/java/preprocessor/build
/java/lsp/build
/java/gradle/build
/.kotlin/sessions
/core/examples/build
/java/gradle/build
/java/gradle/example/.processing

.build/
/app/windows/obj
Expand Down
5 changes: 5 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions core/src/processing/core/PApplet.java
Original file line number Diff line number Diff line change
Expand Up @@ -9942,8 +9942,8 @@ static public void runSketch(final String[] args,
boolean hideStop = false;

int displayNum = -1; // use default
boolean present = false;
boolean fullScreen = false;
boolean present = System.getProperty("processing.present", "false").equals("true");
boolean fullScreen = System.getProperty("processing.fullscreen", "false").equals("true");
float uiScale = 0;

String param, value;
Expand Down
9 changes: 8 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
kotlin = "2.0.20"
compose-plugin = "1.7.1"
jogl = "2.5.0"
antlr = "4.13.2"
jupiter = "5.12.0"

[libraries]
Expand All @@ -25,6 +26,11 @@ netbeansSwing = { module = "org.netbeans.api:org-netbeans-swing-outline", versio
ant = { module = "org.apache.ant:ant", version = "1.10.14" }
lsp4j = { module = "org.eclipse.lsp4j:org.eclipse.lsp4j", version = "0.22.0" }
jsoup = { module = "org.jsoup:jsoup", version = "1.17.2" }
antlr4 = { module = "org.antlr:antlr4", version.ref = "antlr" }
antlr4Runtime = { module = "org.antlr:antlr4-runtime", version.ref = "antlr" }
composeGradlePlugin = { module = "org.jetbrains.compose:compose-gradle-plugin", version.ref = "compose-plugin" }
kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
kotlinComposePlugin = { module = "org.jetbrains.kotlin.plugin.compose:org.jetbrains.kotlin.plugin.compose.gradle.plugin", version.ref = "kotlin" }
markdown = { module = "com.mikepenz:multiplatform-markdown-renderer-m2", version = "0.31.0" }
markdownJVM = { module = "com.mikepenz:multiplatform-markdown-renderer-jvm", version = "0.31.0" }

Expand All @@ -34,4 +40,5 @@ kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref =
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
download = { id = "de.undercouch.download", version = "5.6.0" }
mavenPublish = { id = "com.vanniktech.maven.publish", version = "0.30.0" }
mavenPublish = { id = "com.vanniktech.maven.publish", version = "0.30.0" }
gradlePublish = { id = "com.gradle.plugin-publish", version = "1.2.1" }
34 changes: 34 additions & 0 deletions java/gradle/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
plugins{
`java-gradle-plugin`
alias(libs.plugins.gradlePublish)

kotlin("jvm") version libs.versions.kotlin
}

repositories {
mavenCentral()
}

dependencies{
implementation(project(":java:preprocessor"))

implementation(libs.composeGradlePlugin)
implementation(libs.kotlinGradlePlugin)
implementation(libs.kotlinComposePlugin)

testImplementation(libs.junit)
}

gradlePlugin{
plugins{
create("processing"){
id = "processing.java.gradle"
implementationClass = "org.processing.java.gradle.ProcessingPlugin"
}
}
}
publishing{
repositories{
mavenLocal()
}
}
32 changes: 32 additions & 0 deletions java/gradle/example/brightness.pde
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Brightness
* by Rusty Robison.
*
* Brightness is the relative lightness or darkness of a color.
* Move the cursor vertically over each bar to alter its brightness.
*/

int barWidth = 20;
int lastBar = -1;

import controlP5.*;

ControlP5 cp5;


void setup() {
size(640, 360);
colorMode(HSB, width, 100, height);
noStroke();
background(0);
}

void draw() {
int whichBar = mouseX / barWidth;
if (whichBar != lastBar) {
int barX = whichBar * barWidth;
fill(barX, 100, mouseY);
rect(barX, 0, barWidth, height);
lastBar = whichBar;
}
}
3 changes: 3 additions & 0 deletions java/gradle/example/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
plugins{
id("processing.java.gradle")
}
5 changes: 5 additions & 0 deletions java/gradle/example/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
rootProject.name = "processing-gradle-plugin-demo"

pluginManagement {
includeBuild("../../../")
}
159 changes: 159 additions & 0 deletions java/gradle/src/main/kotlin/ProcessingPlugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package org.processing.java.gradle

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.internal.file.DefaultSourceDirectorySet
import org.gradle.api.internal.tasks.TaskDependencyFactory
import org.gradle.api.model.ObjectFactory
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.tasks.JavaExec
import org.jetbrains.compose.ComposeExtension
import org.jetbrains.compose.desktop.DesktopExtension
import java.io.File
import java.util.*
import javax.inject.Inject

class ProcessingPlugin @Inject constructor(private val objectFactory: ObjectFactory) : Plugin<Project> {
override fun apply(project: Project) {
project.plugins.apply(JavaPlugin::class.java)

// TODO: Only set the build directory when run from the Processing plugin
project.layout.buildDirectory.set(project.layout.projectDirectory.dir(".processing"))

project.plugins.apply("org.jetbrains.compose")
project.plugins.apply("org.jetbrains.kotlin.jvm")
project.plugins.apply("org.jetbrains.kotlin.plugin.compose")

// TODO: Add to tests
project.dependencies.add("implementation", "org.processing:core:4.4.0")
// TODO: Add tests
project.dependencies.add("implementation", project.fileTree("src").apply { include("**/code/*.jar") })

// Base JOGL and Gluegen dependencies
// TODO: Add only if user is compiling for P2D or P3D
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:jogl-all-main:2.5.0")
project.dependencies.add("runtimeOnly", "org.jogamp.gluegen:gluegen-rt-main:2.5.0")

// TODO: Only add the native dependencies for the platform the user is building for

// MacOS specific native dependencies
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:jogl-all:2.5.0:natives-macosx-universal")
project.dependencies.add("runtimeOnly", "org.jogamp.gluegen:gluegen-rt:2.5.0:natives-macosx-universal")

// Windows specific native dependencies
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:jogl-all:2.5.0:natives-windows-amd64")
project.dependencies.add("runtimeOnly", "org.jogamp.gluegen:gluegen-rt:2.5.0:natives-windows-amd64")

// Linux specific native dependencies
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:jogl-all:2.5.0:natives-linux-amd64")
project.dependencies.add("runtimeOnly", "org.jogamp.gluegen:gluegen-rt:2.5.0:natives-linux-amd64")

// NativeWindow dependencies for all platforms
project.dependencies.add("implementation", "org.jogamp.jogl:nativewindow:2.5.0")
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:nativewindow:2.5.0:natives-macosx-universal")
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:nativewindow:2.5.0:natives-windows-amd64")
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:nativewindow:2.5.0:natives-linux-amd64")

project.repositories.add(project.repositories.maven { it.setUrl("https://jogamp.org/deployment/maven") })
project.repositories.add(project.repositories.mavenCentral())
project.repositories.add(project.repositories.mavenLocal())

project.extensions.configure(ComposeExtension::class.java) { extension ->
extension.extensions.getByType(DesktopExtension::class.java).application { application ->
application.mainClass = project.layout.projectDirectory.asFile.name.replace(Regex("[^a-zA-Z0-9_]"), "_")
application.nativeDistributions.modules("java.management")
}
}
// TODO: Also only do within Processing
project.tasks.findByName("wrapper")?.enabled = false

project.tasks.create("sketch").apply {
group = "processing"
description = "Runs the Processing sketch"
dependsOn("run")
}
project.tasks.create("present").apply {
group = "processing"
description = "Presents the Processing sketch"
doFirst{
project.tasks.withType(JavaExec::class.java).configureEach{ task ->
task.systemProperty("processing.fullscreen", "true")
}
}
finalizedBy("run")
}
project.tasks.create("export").apply {
group = "processing"
description = "Creates a distributable version of the Processing sketch"

dependsOn("createDistributable")
doLast{
project.copy {
it.from(project.tasks.named("createDistributable").get().outputs.files)
it.into(project.layout.projectDirectory)
}
}
}

project.extensions.getByType(JavaPluginExtension::class.java).sourceSets.all { sourceSet ->
// TODO: also supporting normal gradle setup
val pdeSourceSet = objectFactory.newInstance(
DefaultPDESourceDirectorySet::class.java,
objectFactory.sourceDirectorySet("${sourceSet.name}.pde", "${sourceSet.name} Processing Source")
).apply {
filter.include("**/*.pde")
filter.exclude("${project.layout.buildDirectory.asFile.get().name}/**")

srcDir("./")
}
sourceSet.allSource.source(pdeSourceSet)

val outputDirectory = project.layout.buildDirectory.file( "generated/pde/" + sourceSet.name).get().asFile
sourceSet.java.srcDir(outputDirectory)

// TODO: Support multiple sketches?

val taskName = sourceSet.getTaskName("preprocess", "PDE")
project.tasks.register(taskName, ProcessingTask::class.java) { task ->
task.description = "Processes the ${sourceSet.name} PDE"
task.source = pdeSourceSet
task.outputDirectory = outputDirectory
}

project.tasks.named(
sourceSet.compileJavaTaskName
) { task -> task.dependsOn(taskName) }
}

var settingsFolder = File(System.getProperty("user.home"),".processing")
val osName = System.getProperty("os.name").lowercase()
if (osName.contains("win")) {
settingsFolder = File(System.getenv("APPDATA"), "Processing")
} else if (osName.contains("mac")) {
settingsFolder = File(System.getProperty("user.home"), "Library/Processing")
}else if (osName.contains("nix") || osName.contains("nux")) {
settingsFolder = File(System.getProperty("user.home"), ".processing")
}

val preferences = File(settingsFolder, "preferences.txt")
val prefs = Properties()
prefs.load(preferences.inputStream())
prefs.setProperty("export.application.fullscreen", "false")
prefs.setProperty("export.application.present", "false")
prefs.setProperty("export.application.stop", "false")
prefs.store(preferences.outputStream(), null)

val sketchbook = prefs.getProperty("sketchbook.path.four")

File(sketchbook, "libraries").listFiles { file -> file.isDirectory }?.forEach{
project.dependencies.add("implementation", project.fileTree(it).apply { include("**/*.jar") })
}
}
abstract class DefaultPDESourceDirectorySet @Inject constructor(
sourceDirectorySet: SourceDirectorySet,
taskDependencyFactory: TaskDependencyFactory
) : DefaultSourceDirectorySet(sourceDirectorySet, taskDependencyFactory), SourceDirectorySet
}

77 changes: 77 additions & 0 deletions java/gradle/src/main/kotlin/ProcessingTask.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package org.processing.java.gradle

import org.gradle.api.file.*
import org.gradle.api.tasks.*
import org.gradle.internal.file.Deleter
import org.gradle.work.ChangeType
import org.gradle.work.FileChange
import org.gradle.work.InputChanges
import processing.mode.java.preproc.PdePreprocessor
import java.io.File
import java.io.IOException
import java.io.UncheckedIOException
import java.util.concurrent.Callable
import javax.inject.Inject

abstract class ProcessingTask : SourceTask() {
@get:OutputDirectory
var outputDirectory: File? = null

@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
@get:IgnoreEmptyDirectories
@get:SkipWhenEmpty
open val stableSources: FileCollection = project.files(Callable<Any> { this.source })

@TaskAction
fun execute(inputChanges: InputChanges) {
val files: MutableSet<File> = HashSet()
if (inputChanges.isIncremental) {
var rebuildRequired = true
for (fileChange: FileChange in inputChanges.getFileChanges(stableSources)) {
if (fileChange.fileType == FileType.FILE) {
if (fileChange.changeType == ChangeType.REMOVED) {
rebuildRequired = true
break
}
files.add(fileChange.file)
}
}
if (rebuildRequired) {
try {
outputDirectory?.let { deleter.ensureEmptyDirectory(it) }
} catch (ex: IOException) {
throw UncheckedIOException(ex)
}
files.addAll(stableSources.files)
}
} else {
files.addAll(stableSources.files)
}

val name = project.layout.projectDirectory.asFile.name.replace(Regex("[^a-zA-Z0-9_]"), "_")
val combined = files.joinToString("\n") { it.readText() }
File(outputDirectory, "$name.java")
.bufferedWriter()
.use { out ->
val meta = PdePreprocessor
.builderFor(name)
.build()
.write(out, combined)


// TODO: Only import the libraries that are actually used
val importStatement = meta.importStatements

// for (import in importStatement) {
// project.dependencies.add("implementation", import)
// }
}
}

@get:Inject
open val deleter: Deleter
get() {
throw UnsupportedOperationException("Decorator takes care of injection")
}
}
Loading
Loading