Skip to content

Commit 1a5fdc6

Browse files
vogellaCopilot
andcommitted
Migrate Blob effect to Graphics Example
This PR migrates the Blob (metaball) effect from SWT-OldSchoolEffect to the SWT Graphics Example. Changes: - Implemented BlobTab.java extending AnimatedGraphicsTab - Registered the new tab in GraphicsExample.java - Added descriptive strings to examples_graphics.properties Contributes to #3189 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent fa04053 commit 1a5fdc6

File tree

3 files changed

+179
-0
lines changed

3 files changed

+179
-0
lines changed

examples/org.eclipse.swt.examples/src/examples_graphics.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,6 @@ StarPolygonDescription=This tab draws a polygon and shows the effects of setting
190190
AntialiasingTextDesc=This tab demonstrates antialiasing for text. Antialiasing is used for smoothing jagged edges in graphics. This tab allows the user to see the effects of different antialiasing values.
191191
Ripple=Ripple
192192
RippleDescription=This is a miscellaneous demonstration that uses a displacement map to simulate water ripples on an image. Move the mouse over the image to disturb the water.
193+
194+
Blob=Blob
195+
BlobDescription=This is a miscellaneous demonstration of an animated metaball effect where multiple blobs move randomly and blend together when overlapping.
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2018 Laurent Caron and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* W.P. van Paassen - Original Version
13+
* Laurent Caron (laurent.caron at gmail dot com) - Conversion to SWT
14+
* IBM Corporation - adaptation to GraphicsExample
15+
*******************************************************************************/
16+
17+
package org.eclipse.swt.examples.graphics;
18+
19+
import org.eclipse.swt.SWT;
20+
import org.eclipse.swt.graphics.GC;
21+
import org.eclipse.swt.graphics.Image;
22+
import org.eclipse.swt.graphics.ImageData;
23+
import org.eclipse.swt.graphics.PaletteData;
24+
import org.eclipse.swt.graphics.RGB;
25+
26+
/**
27+
* This tab displays an animated metaball/blob effect where multiple blobs
28+
* move randomly and blend together when overlapping.
29+
*/
30+
public class BlobTab extends AnimatedGraphicsTab {
31+
32+
private static final int BLOB_RADIUS = 44;
33+
private static final int BLOB_DRADIUS = BLOB_RADIUS * 2;
34+
private static final int BLOB_SRADIUS = BLOB_RADIUS * BLOB_RADIUS;
35+
private static final int NUMBER_OF_BLOBS = 20;
36+
37+
private int[][] blob;
38+
private int[] blobX;
39+
private int[] blobY;
40+
private ImageData imageData;
41+
private Image outputImage;
42+
private int lastWidth;
43+
private int lastHeight;
44+
45+
public BlobTab(GraphicsExample example) {
46+
super(example);
47+
}
48+
49+
@Override
50+
public String getCategory() {
51+
return GraphicsExample.getResourceString("Misc"); //$NON-NLS-1$
52+
}
53+
54+
@Override
55+
public String getText() {
56+
return GraphicsExample.getResourceString("Blob"); //$NON-NLS-1$
57+
}
58+
59+
@Override
60+
public String getDescription() {
61+
return GraphicsExample.getResourceString("BlobDescription"); //$NON-NLS-1$
62+
}
63+
64+
@Override
65+
public int getInitialAnimationTime() {
66+
return 10;
67+
}
68+
69+
@Override
70+
public void dispose() {
71+
if (outputImage != null) {
72+
outputImage.dispose();
73+
outputImage = null;
74+
}
75+
}
76+
77+
@Override
78+
public void next(int width, int height) {
79+
if (blobX == null) {
80+
return;
81+
}
82+
if (width != lastWidth || height != lastHeight) {
83+
init(width, height);
84+
}
85+
86+
// Clear pixel data
87+
for (int y = 0; y < height; y++) {
88+
for (int x = 0; x < width; x++) {
89+
imageData.setPixel(x, y, 0);
90+
}
91+
}
92+
93+
// Move and draw blobs
94+
for (int i = 0; i < NUMBER_OF_BLOBS; i++) {
95+
blobX[i] += -2 + (int) (5.0 * Math.random());
96+
blobY[i] += -2 + (int) (5.0 * Math.random());
97+
}
98+
99+
for (int k = 0; k < NUMBER_OF_BLOBS; ++k) {
100+
if (blobX[k] > 0 && blobX[k] < width - BLOB_DRADIUS && blobY[k] > 0 && blobY[k] < height - BLOB_DRADIUS) {
101+
int start = blobX[k] + blobY[k] * width;
102+
for (int i = 0; i < BLOB_DRADIUS; ++i) {
103+
for (int j = 0; j < BLOB_DRADIUS; ++j) {
104+
int px = (start + j) % width;
105+
int py = (start + j) / width;
106+
if (py >= 0 && py < height) {
107+
int current = imageData.getPixel(px, py);
108+
int sum = current + blob[i][j];
109+
imageData.setPixel(px, py, Math.min(sum, 255));
110+
}
111+
}
112+
start += width;
113+
}
114+
} else {
115+
blobX[k] = (width >> 1) - BLOB_RADIUS;
116+
blobY[k] = (height >> 1) - BLOB_RADIUS;
117+
}
118+
}
119+
}
120+
121+
@Override
122+
public void paint(GC gc, int width, int height) {
123+
if (blobX == null) {
124+
init(width, height);
125+
}
126+
127+
gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_BLACK));
128+
gc.fillRectangle(0, 0, width, height);
129+
130+
if (imageData == null) {
131+
return;
132+
}
133+
134+
if (outputImage != null) {
135+
outputImage.dispose();
136+
}
137+
outputImage = new Image(gc.getDevice(), imageData);
138+
gc.drawImage(outputImage, 0, 0);
139+
}
140+
141+
private void init(int width, int height) {
142+
lastWidth = width;
143+
lastHeight = height;
144+
145+
blob = new int[BLOB_DRADIUS][BLOB_DRADIUS];
146+
blobX = new int[NUMBER_OF_BLOBS];
147+
blobY = new int[NUMBER_OF_BLOBS];
148+
149+
// Create blob shape
150+
for (int i = -BLOB_RADIUS; i < BLOB_RADIUS; ++i) {
151+
for (int j = -BLOB_RADIUS; j < BLOB_RADIUS; ++j) {
152+
final int distanceSquared = i * i + j * j;
153+
if (distanceSquared <= BLOB_SRADIUS) {
154+
final float fraction = (float) distanceSquared / (float) BLOB_SRADIUS;
155+
blob[i + BLOB_RADIUS][j + BLOB_RADIUS] = (int) (Math.pow(1.0 - fraction * fraction, 4.0) * 255.0);
156+
} else {
157+
blob[i + BLOB_RADIUS][j + BLOB_RADIUS] = 0;
158+
}
159+
}
160+
}
161+
162+
// Initialize blob positions at center
163+
for (int i = 0; i < NUMBER_OF_BLOBS; i++) {
164+
blobX[i] = (width >> 1) - BLOB_RADIUS;
165+
blobY[i] = (height >> 1) - BLOB_RADIUS;
166+
}
167+
168+
// Create grayscale palette image data
169+
final RGB[] colors = new RGB[256];
170+
for (int i = 0; i < 256; ++i) {
171+
colors[i] = new RGB(i, i, i);
172+
}
173+
imageData = new ImageData(width, height, 8, new PaletteData(colors));
174+
}
175+
}

examples/org.eclipse.swt.examples/src/org/eclipse/swt/examples/graphics/GraphicsExample.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ GraphicsTab[] createTabs() {
470470
new LineJoinTab(this),
471471
new RegionClippingTab(this),
472472
new StarfieldTab(this),
473+
new BlobTab(this),
473474
new RippleTab(this),
474475
new CustomAlphaTab(this),
475476
new TextAntialiasTab(this),

0 commit comments

Comments
 (0)