Skip to content

Commit d3a1c0a

Browse files
committed
Bundle GLFW/GLEW headers in libs/include for all platforms, progress bar in wizard
1 parent b430a4d commit d3a1c0a

10 files changed

Lines changed: 40047 additions & 96 deletions

File tree

libs/include/GL/eglew.h

Lines changed: 3051 additions & 0 deletions
Large diffs are not rendered by default.

libs/include/GL/glew.h

Lines changed: 26427 additions & 0 deletions
Large diffs are not rendered by default.

libs/include/GL/glxew.h

Lines changed: 1831 additions & 0 deletions
Large diffs are not rendered by default.

libs/include/GL/wglew.h

Lines changed: 1468 additions & 0 deletions
Large diffs are not rendered by default.

libs/include/GLFW/glfw3.h

Lines changed: 6547 additions & 0 deletions
Large diffs are not rendered by default.

libs/include/GLFW/glfw3native.h

Lines changed: 663 additions & 0 deletions
Large diffs are not rendered by default.

mode/CppMode.jar

-531 Bytes
Binary file not shown.

src/java/CppBuild.java

Lines changed: 13 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -247,84 +247,14 @@ private void showGppDialog(String html, String btn, String url,
247247
}
248248

249249
private void autoInstallWindows(RunnerListener listener) {
250-
String script =
251-
"$ErrorActionPreference = 'Stop'\n"
252-
+ "Write-Host '=== C++ Mode Auto-Installer ==='\n"
253-
+ "Write-Host ''\n"
254-
+ "$msys2Dirs = @('C:\\msys64','C:\\msys2','C:\\tools\\msys64',"
255-
+ "\"$env:USERPROFILE\\msys64\",\"$env:LOCALAPPDATA\\msys64\")\n"
256-
+ "$pacman = $null\n"
257-
+ "foreach ($dir in $msys2Dirs) {\n"
258-
+ " $p = \"$dir\\usr\\bin\\pacman.exe\"\n"
259-
+ " if (Test-Path $p) { $pacman = $p; Write-Host \"Found MSYS2 at $dir\"; break }\n"
260-
+ "}\n"
261-
+ "if (-not $pacman) {\n"
262-
+ " $inPath = Get-Command pacman -ErrorAction SilentlyContinue\n"
263-
+ " if ($inPath) { $pacman = $inPath.Source; Write-Host \"Found pacman on PATH\" }\n"
264-
+ "}\n"
265-
+ "if (-not $pacman) {\n"
266-
+ " Write-Host 'Downloading MSYS2 installer (this may take a minute)...'\n"
267-
+ " $url = 'https://github.com/msys2/msys2-installer/releases/download/nightly-x86_64/msys2-x86_64-latest.exe'\n"
268-
+ " $dest = \"$env:TEMP\\msys2-installer.exe\"\n"
269-
+ " $wc = New-Object System.Net.WebClient\n"
270-
+ " $wc.add_DownloadProgressChanged({\n"
271-
+ " param($s,$e)\n"
272-
+ " $pct = $e.ProgressPercentage\n"
273-
+ " $bar = '#' * [int]($pct/2)\n"
274-
+ " $empty = '-' * (50 - [int]($pct/2))\n"
275-
+ " Write-Host -NoNewline \"\r [$bar$empty] $pct% \"\n"
276-
+ " })\n"
277-
+ " $done = $false\n"
278-
+ " $wc.add_DownloadFileCompleted({ $done = $true })\n"
279-
+ " $wc.DownloadFileAsync([uri]$url, $dest)\n"
280-
+ " while (-not $done) { Start-Sleep -Milliseconds 100 }\n"
281-
+ " Write-Host ''\n"
282-
+ " Write-Host 'Running MSYS2 installer...'\n"
283-
+ " Start-Process -Wait $dest -ArgumentList 'install','--confirm-command','--accept-messages','--root','C:/msys64'\n"
284-
+ " $pacman = 'C:\\msys64\\usr\\bin\\pacman.exe'\n"
285-
+ " Write-Host 'MSYS2 installed.'\n"
286-
+ "}\n"
287-
+ "Write-Host ''\n"
288-
+ "Write-Host 'Installing g++, GLFW, GLEW...'\n"
289-
+ "& $pacman -S --noconfirm --needed '--overwrite=*' mingw-w64-x86_64-gcc mingw-w64-x86_64-glfw mingw-w64-x86_64-glew\n"
290-
+ "Write-Host 'Adding MSYS2 to system PATH...'\n"
291-
+ "$mingwBin = 'C:\\msys64\\mingw64\\bin'\n"
292-
+ "$currentPath = [Environment]::GetEnvironmentVariable('PATH','Machine')\n"
293-
+ "if ($currentPath -notlike \"*$mingwBin*\") {\n"
294-
+ " [Environment]::SetEnvironmentVariable('PATH', \"$mingwBin;$currentPath\", 'Machine')\n"
295-
+ " Write-Host 'Added to system PATH.'\n"
296-
+ "} else { Write-Host 'Already in PATH.' }\n"
297-
+ "Write-Host ''\n"
298-
+ "Write-Host '============================================'\n"
299-
+ "Write-Host 'Installation complete!'\n"
300-
+ "Write-Host 'Please restart Processing4 to use C++ Mode.'\n"
301-
+ "Write-Host '============================================'\n"
302-
+ "Read-Host 'Press Enter to close'\n";
250+
// Delegate to InstallWizard which handles portable gcc download in-app.
251+
// GLFW and GLEW are bundled in libs/windows-x64/ -- no MSYS2 needed.
303252
try {
304-
java.io.File tmp = java.io.File.createTempFile("cpp_install_", ".ps1");
305-
tmp.deleteOnExit();
306-
try (java.io.PrintWriter pw = new java.io.PrintWriter(tmp)) { pw.print(script); }
307-
listener.statusNotice("Launching installer...");
308-
new Thread(() -> {
309-
try {
310-
// Run as admin so PATH can be updated system-wide
311-
ProcessBuilder pb2 = new ProcessBuilder(
312-
"powershell.exe", "-ExecutionPolicy", "Bypass",
313-
"-Command",
314-
"Start-Process powershell -Verb RunAs -ArgumentList "
315-
+ "'-ExecutionPolicy Bypass -NoExit -File \"" + tmp.getAbsolutePath().replace("\\", "\\\\") + "\"'");
316-
pb2.start();
317-
javax.swing.JOptionPane.showMessageDialog(null,
318-
new javax.swing.JLabel(
319-
"<html><b>Installer launched!</b><br><br>"
320-
+ "A PowerShell window is installing g++, GLFW, and GLEW.<br><br>"
321-
+ "When it says <b>Installation complete!</b>:<br>"
322-
+ "&nbsp;&nbsp;1. Close the installer window<br>"
323-
+ "&nbsp;&nbsp;2. <b>Restart Processing4</b></html>"),
324-
"Installing...", javax.swing.JOptionPane.INFORMATION_MESSAGE);
325-
} catch (Exception e2) { listener.statusError("Error: "+e2.getMessage()); }
326-
}).start();
327-
} catch (Exception e) { listener.statusError("Error: "+e.getMessage()); }
253+
InstallWizard.run(listener);
254+
} catch (InstallWizard.CancelledByUser ignored) {
255+
} catch (Exception e) {
256+
listener.statusError("Auto-install failed: " + e.getMessage());
257+
}
328258
}
329259

330260

@@ -424,7 +354,6 @@ private void checkGppAvailable(RunnerListener listener) throws Exception {
424354
System.getProperty("user.home") + "\\msys64\\mingw64\\bin\\g++.exe",
425355
"C:\\msys64\\ucrt64\\bin\\g++.exe"})
426356
if (new File(p).exists()) return;
427-
// Try PATH g++ as final fallback (bundled DLLs cover GLFW/GLEW)
428357
try {
429358
if (Runtime.getRuntime().exec(new String[]{"g++","--version"}).waitFor()==0) return;
430359
} catch (Exception ignored) {}
@@ -435,16 +364,14 @@ private void checkGppAvailable(RunnerListener listener) throws Exception {
435364
int ch = javax.swing.JOptionPane.showOptionDialog(null,
436365
new javax.swing.JLabel(
437366
"<html><b>g++ (C++ compiler) not found.</b><br><br>"
438-
+ "C++ Mode requires MSYS2 with g++, GLFW, and GLEW.<br><br>"
367+
+ "C++ Mode needs g++ to compile sketches.<br>"
368+
+ "GLFW and GLEW are already bundled — no extra downloads needed.<br><br>"
439369
+ "<b>Auto-Install (recommended):</b><br>"
440-
+ "&nbsp;&nbsp;Click <b>Auto-Install</b> to install everything automatically.<br><br>"
370+
+ "&nbsp;&nbsp;Click <b>Auto-Install</b> to download g++ automatically.<br><br>"
441371
+ "<b>Manual:</b><br>"
442-
+ "&nbsp;&nbsp;1. Install MSYS2 from https://www.msys2.org<br>"
443-
+ "&nbsp;&nbsp;2. Open <b>MSYS2 MinGW 64-bit</b> terminal<br>"
444-
+ "&nbsp;&nbsp;3. Run:<br>"
445-
+ "&nbsp;&nbsp;&nbsp;&nbsp;<code>pacman -S mingw-w64-x86_64-gcc"
446-
+ " mingw-w64-x86_64-glfw mingw-w64-x86_64-glew</code><br>"
447-
+ "&nbsp;&nbsp;4. Restart Processing</html>"),
372+
+ "&nbsp;&nbsp;Install MSYS2 from https://www.msys2.org and run:<br>"
373+
+ "&nbsp;&nbsp;<code>pacman -S mingw-w64-x86_64-gcc</code><br>"
374+
+ "&nbsp;&nbsp;Then restart Processing.</html>"),
448375
"C++ Compiler Not Found",
449376
javax.swing.JOptionPane.YES_NO_CANCEL_OPTION,
450377
javax.swing.JOptionPane.ERROR_MESSAGE,

src/java/CppLinter.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,10 @@ private void runCheck(Sketch sketch, int currentTab, String liveText) {
165165
cmd.add("-std=c++23");
166166
cmd.add("-I");
167167
cmd.add(runtimeDir.getAbsolutePath());
168+
// Bundled headers (GLFW, GLEW)
169+
File bundledInc = new File(runtimeDir.getParentFile(), "libs/include");
170+
if (bundledInc.exists()) { cmd.add("-I"); cmd.add(bundledInc.getAbsolutePath()); }
168171
if (gch != null) {
169-
// Point g++ at the cache dir so it finds Processing.h.gch
170172
cmd.add("-I");
171173
cmd.add(gch.getParentFile().getAbsolutePath());
172174
}

src/java/InstallWizard.java

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,14 @@ public static boolean run(RunnerListener listener) throws CancelledByUser {
8585
final Object lock = new Object();
8686
SwingUtilities.invokeLater(() -> {
8787
Object[] options = { "Install", "Cancel" };
88+
String missingMsg = isWin
89+
? "C++ Mode needs a C++ compiler (g++) to compile sketches.\n\n"
90+
+ "Click Install to download g++ automatically (~130 MB).\n"
91+
+ "GLFW and GLEW are already bundled — no extra downloads needed."
92+
: "Missing: " + String.join(", ", missing) + "\n\n"
93+
+ "C++ Mode needs these to compile and run sketches.";
8894
int choice = JOptionPane.showOptionDialog(null,
89-
"Missing: " + String.join(", ", missing) + "\n\n"
90-
+ "C++ Mode needs these to compile and run sketches.",
95+
missingMsg,
9196
"C++ Mode — Missing Dependencies",
9297
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
9398
null, options, options[0]);
@@ -126,6 +131,7 @@ public static boolean run(RunnerListener listener) throws CancelledByUser {
126131
private JDialog dialog;
127132
private JTextArea log;
128133
private JLabel stepLabel;
134+
private JProgressBar progressBar;
129135
private JButton cancelButton;
130136
private final AtomicBoolean cancelled = new AtomicBoolean(false);
131137
private final AtomicBoolean succeeded = new AtomicBoolean(false);
@@ -148,11 +154,17 @@ private void buildDialog(String title) {
148154
stepLabel.setFont(stepLabel.getFont().deriveFont(Font.BOLD, 13f));
149155
root.add(stepLabel, BorderLayout.NORTH);
150156

151-
log = new JTextArea(14, 56);
157+
progressBar = new JProgressBar(0, 100);
158+
progressBar.setStringPainted(true);
159+
progressBar.setString("");
160+
progressBar.setValue(0);
161+
root.add(progressBar, BorderLayout.CENTER);
162+
163+
log = new JTextArea(10, 56);
152164
log.setEditable(false);
153165
log.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
154166
JScrollPane scroll = new JScrollPane(log);
155-
root.add(scroll, BorderLayout.CENTER);
167+
root.add(scroll, BorderLayout.SOUTH);
156168

157169
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT, 8, 0));
158170
cancelButton = new JButton("Cancel");
@@ -177,6 +189,21 @@ private void appendLog(String text) {
177189
});
178190
}
179191

192+
private void setProgress(int pct) {
193+
SwingUtilities.invokeLater(() -> {
194+
progressBar.setValue(pct);
195+
progressBar.setString(pct + "%");
196+
if (pct >= 100) progressBar.setString("Done");
197+
});
198+
}
199+
200+
private void setIndeterminate(boolean b) {
201+
SwingUtilities.invokeLater(() -> {
202+
progressBar.setIndeterminate(b);
203+
if (b) progressBar.setString("Working...");
204+
});
205+
}
206+
180207
private void requestCancel() {
181208
cancelled.set(true);
182209
finishDialog(false, "Cancelled.");
@@ -186,6 +213,9 @@ private void finishDialog(boolean success, String finalMessage) {
186213
succeeded.set(success);
187214
SwingUtilities.invokeLater(() -> {
188215
if (finalMessage != null) setStep(finalMessage);
216+
progressBar.setIndeterminate(false);
217+
progressBar.setValue(success ? 100 : progressBar.getValue());
218+
progressBar.setString(success ? "Done" : "Failed");
189219
cancelButton.setText("Close");
190220
});
191221
synchronized (doneLock) {
@@ -260,6 +290,8 @@ private boolean installPortableGcc() {
260290
appendLog("Source: " + WINLIBS_URL);
261291
appendLog("Destination: " + gccDir.getAbsolutePath());
262292
appendLog("Size: ~130 MB — please wait...");
293+
final long WINLIBS_SIZE = 136 * 1024 * 1024L; // ~130 MB
294+
setProgress(0);
263295
try (java.io.InputStream in = new java.net.URI(WINLIBS_URL).toURL().openStream();
264296
java.io.OutputStream out = new java.io.FileOutputStream(zipFile)) {
265297
byte[] buf = new byte[64 * 1024];
@@ -268,12 +300,16 @@ private boolean installPortableGcc() {
268300
if (cancelled.get()) return false;
269301
out.write(buf, 0, n);
270302
total += n;
271-
if (total % (5 * 1024 * 1024) < buf.length)
303+
int pct = (int) Math.min(99, total * 100 / WINLIBS_SIZE);
304+
setProgress(pct);
305+
if (total % (10 * 1024 * 1024) < buf.length)
272306
appendLog("Downloaded " + (total / (1024 * 1024)) + " MB...");
273307
}
274308
}
309+
setProgress(100);
275310
setStep("Extracting gcc...");
276311
appendLog("Extracting to " + gccDir.getAbsolutePath());
312+
setIndeterminate(true);
277313
// Use PowerShell Expand-Archive (available on all modern Windows)
278314
Process extract = new ProcessBuilder(
279315
"powershell", "-NoProfile", "-Command",
@@ -283,6 +319,8 @@ private boolean installPortableGcc() {
283319
streamToLog(extract);
284320
int code = extract.waitFor();
285321
zipFile.delete(); // clean up zip after extraction
322+
setIndeterminate(false);
323+
setProgress(100);
286324
if (code != 0) { appendLog("Extraction failed."); return false; }
287325
if (!getPortableGpp().exists()) {
288326
appendLog("g++.exe not found after extraction -- unexpected zip structure.");
@@ -308,8 +346,6 @@ private java.util.List<String> detectWindowsMissing() {
308346
if (new File(p).exists()) { haveGpp = true; break; }
309347
}
310348
}
311-
// GLFW and GLEW are bundled in libs/windows-x64/ -- no MSYS2 needed for them.
312-
// Only report them missing if the bundled DLLs aren't present AND MSYS2 doesn't have them.
313349
java.util.List<String> missing = new java.util.ArrayList<>();
314350
if (!haveGpp) missing.add("g++");
315351
return missing;
@@ -486,8 +522,6 @@ private boolean runMac(java.util.List<String> missing) {
486522
if (missing.contains("glew")) missingLibs.add("glew");
487523

488524
Thread worker = new Thread(() -> {
489-
// Resolve brew at known locations first -- Processing may launch without
490-
// /opt/homebrew/bin in PATH on Apple Silicon Macs.
491525
String brewExe = null;
492526
if (new File("/opt/homebrew/bin/brew").exists()) brewExe = "/opt/homebrew/bin/brew";
493527
else if (new File("/usr/local/bin/brew").exists()) brewExe = "/usr/local/bin/brew";
@@ -539,6 +573,7 @@ private boolean runMac(java.util.List<String> missing) {
539573
}
540574

541575
setStep("Installing: " + String.join(", ", missingLibs));
576+
setIndeterminate(true);
542577
try {
543578
java.util.List<String> cmd = new java.util.ArrayList<>();
544579
cmd.add(brewExe); cmd.add("install"); cmd.addAll(missingLibs);

0 commit comments

Comments
 (0)